Skip to content

Commit d5f1c32

Browse files
committed
Initial commit
0 parents  commit d5f1c32

File tree

77 files changed

+3954
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+3954
-0
lines changed

.editorconfig

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
indent_style = space
8+
indent_size = 4
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false
13+
14+
[*.yml]
15+
indent_size = 2

.gitattributes

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
* text=auto
2+
3+
/.github export-ignore
4+
5+
/tests export-ignore
6+
phpunit.xml export-ignore
7+
8+
.editorconfig export-ignore
9+
.gitattributes export-ignore
10+
.gitignore export-ignore
11+

.github/workflows/codestyle.yml

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: codestyle
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
psalm:
9+
name: Code Style
10+
runs-on: ${{ matrix.os }}
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
php: [ '8.2' ]
15+
os: [ ubuntu-latest ]
16+
steps:
17+
- name: Set Git To Use LF
18+
run: |
19+
git config --global core.autocrlf false
20+
git config --global core.eol lf
21+
- name: Checkout
22+
uses: actions/[email protected]
23+
- name: Setup PHP ${{ matrix.php }}
24+
uses: shivammathur/setup-php@v2
25+
with:
26+
php-version: ${{ matrix.php }}
27+
- name: Validate Composer
28+
run: composer validate
29+
- name: Install Dependencies
30+
uses: nick-invision/retry@v2
31+
with:
32+
timeout_minutes: 5
33+
max_attempts: 5
34+
command: composer update --prefer-dist --no-interaction --no-progress
35+
- name: Check Code Style
36+
run: composer phpcs:check

.github/workflows/main.yml

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: build
2+
3+
on:
4+
push:
5+
pull_request:
6+
schedule:
7+
- cron: '0 0 * * *'
8+
9+
jobs:
10+
tests:
11+
name: Unit Tests (${{matrix.php}}, ${{ matrix.os }}, ${{ matrix.stability }})
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
php: [ '8.1', '8.2' ]
17+
os: [ ubuntu-latest, macos-latest, windows-latest ]
18+
stability: [ prefer-lowest, prefer-stable ]
19+
steps:
20+
- name: Checkout
21+
uses: actions/[email protected]
22+
- name: Setup PHP ${{ matrix.php }}
23+
uses: shivammathur/setup-php@v2
24+
with:
25+
php-version: ${{ matrix.php }}
26+
tools: composer:v2
27+
- name: Validate Composer
28+
run: composer validate
29+
- name: Install Dependencies
30+
uses: nick-invision/retry@v2
31+
with:
32+
timeout_minutes: 5
33+
max_attempts: 5
34+
command: composer update --prefer-dist --no-interaction --no-progress
35+
- name: Execute Tests
36+
run: vendor/bin/phpunit --testdox

.github/workflows/security.yml

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: security
2+
3+
on:
4+
push:
5+
pull_request:
6+
schedule:
7+
- cron: '0 0 * * *'
8+
9+
jobs:
10+
security:
11+
name: Security
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
php: [ '8.2' ]
17+
os: [ ubuntu-latest ]
18+
steps:
19+
- name: Set Git To Use LF
20+
run: |
21+
git config --global core.autocrlf false
22+
git config --global core.eol lf
23+
- name: Checkout
24+
uses: actions/[email protected]
25+
- name: Setup PHP ${{ matrix.php }}
26+
uses: shivammathur/setup-php@v2
27+
with:
28+
php-version: ${{ matrix.php }}
29+
- name: Validate Composer
30+
run: composer validate
31+
- name: Install Dependencies
32+
uses: nick-invision/retry@v2
33+
with:
34+
timeout_minutes: 5
35+
max_attempts: 5
36+
command: composer update --prefer-dist --no-interaction --no-progress
37+
- name: Composer Audit
38+
run: composer audit
39+
- name: Security Advisories
40+
run: composer require --dev roave/security-advisories:dev-latest

.github/workflows/static-analysis.yml

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: static-analysis
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
psalm:
9+
name: Psalm
10+
runs-on: ${{ matrix.os }}
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
php: [ '8.2' ]
15+
os: [ ubuntu-latest ]
16+
steps:
17+
- name: Set Git To Use LF
18+
run: |
19+
git config --global core.autocrlf false
20+
git config --global core.eol lf
21+
- name: Checkout
22+
uses: actions/[email protected]
23+
- name: Setup PHP ${{ matrix.php }}
24+
uses: shivammathur/setup-php@v2
25+
with:
26+
php-version: ${{ matrix.php }}
27+
- name: Validate Composer
28+
run: composer validate
29+
- name: Install Dependencies
30+
uses: nick-invision/retry@v2
31+
with:
32+
timeout_minutes: 5
33+
max_attempts: 5
34+
command: composer update --prefer-dist --no-interaction --no-progress
35+
- name: Static Analysis
36+
continue-on-error: true
37+
run: composer psalm:check

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.idea/
2+
vendor/
3+
4+
composer.lock
5+
.phpunit.result.cache

.php-cs-fixer.php

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
$files = PhpCsFixer\Finder::create()
4+
->in(__DIR__ . '/src')
5+
;
6+
7+
$rules = [
8+
'@PER' => true,
9+
'@PER:risky' => true,
10+
'strict_param' => true,
11+
'array_syntax' => ['syntax' => 'short'],
12+
];
13+
14+
return (new PhpCsFixer\Config())
15+
->setRules($rules)
16+
->setCacheFile(__DIR__ . '/vendor/.php-cs-fixer.cache')
17+
->setFinder($files)
18+
;

LICENSE.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright © Kirill Nesmeyanov
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# FFI IDE Helper Generator
2+
3+
<p align="center">
4+
<a href="https://packagist.org/packages/ffi/ide-helper-generator"><img src="https://poser.pugx.org/ffi/ide-helper-generator/require/php?style=for-the-badge" alt="PHP 8.1+"></a>
5+
<a href="https://packagist.org/packages/ffi/ide-helper-generator"><img src="https://poser.pugx.org/ffi/ide-helper-generator/version?style=for-the-badge" alt="Latest Stable Version"></a>
6+
<a href="https://packagist.org/packages/ffi/ide-helper-generator"><img src="https://poser.pugx.org/ffi/ide-helper-generator/v/unstable?style=for-the-badge" alt="Latest Unstable Version"></a>
7+
<a href="https://packagist.org/packages/ffi/ide-helper-generator"><img src="https://poser.pugx.org/ffi/ide-helper-generator/downloads?style=for-the-badge" alt="Total Downloads"></a>
8+
<a href="https://raw.githubusercontent.com/php-ffi/ide-helper-generator/master/LICENSE.md"><img src="https://poser.pugx.org/ffi/ide-helper-generator/license?style=for-the-badge" alt="License MIT"></a>
9+
</p>
10+
<p align="center">
11+
<a href="https://github.com/php-ffi/ide-helper-generator/actions"><img src="https://github.com/php-ffi/ide-helper-generator/workflows/build/badge.svg"></a>
12+
</p>
13+
14+
## Requirements
15+
16+
- PHP ^8.1
17+
- [castxml](https://github.com/CastXML/CastXML) ([binaries](https://github.com/CastXML/CastXMLSuperbuild/releases))
18+
19+
## Installation
20+
21+
Library is available as composer repository and can be installed using the
22+
following command in a root of your project as dev-dependency.
23+
24+
```sh
25+
$ composer require ffi/ide-helper-generator --dev
26+
```
27+
28+
## Usage
29+
30+
### Generate Metadata
31+
32+
Before generating the helper, the headers must be parsed to build the metadata
33+
data. To do this, `castxml` will be used, which in turn uses the original
34+
compiler (like `clang`) to build the AST.
35+
36+
```php
37+
use FFI\Generator\Metadata\CastXMLGenerator;
38+
39+
(new CastXMLGenerator(
40+
binary: 'castxml', // path to binary (optional)
41+
temp: 'storage', // path to temp directory (optional)
42+
))
43+
->generate('/path/to/headers.h')
44+
->save('/path/to/metadata.xml')
45+
;
46+
```
47+
48+
You can also to optimize this step by adding a file existence check:
49+
50+
```php
51+
if (!is_file('/path/to/metadata.xml')) {
52+
// Generate metadata: (new CastXMLGenerator())->...
53+
}
54+
```
55+
56+
### Analyze Metadata
57+
58+
After the metadata is generated, it should be parsed and an abstract syntax tree
59+
built in memory.
60+
61+
```php
62+
use FFI\Generator\Metadata\CastXMLParser;
63+
64+
$ast = (new CastXMLParser())
65+
->parse('/path/to/metadata.xml')
66+
;
67+
```
68+
69+
### Building IDE Helper
70+
71+
```php
72+
use FFI\Generator\PhpStormMetadataGenerator;
73+
use FFI\Generator\SimpleNamingStrategy;
74+
75+
$generator = new PhpStormMetadataGenerator(
76+
argumentSetPrefix: 'ffi_', // Optional prefix for all argument sets to be registered
77+
// in metadata files.
78+
79+
ignoreDirectories: ['/usr'], // Optional list of directories with headers whose types
80+
// should be excluded from the generated code.
81+
82+
naming: new SimpleNamingStrategy(
83+
entrypoint: 'FFI\\Generated\\EntrypointInterface', // The name of the main FFI class
84+
// for which methods for autocomplete
85+
// will be generated.
86+
87+
externalNamespace: 'FFI\\Generated', // Namespace for all public types (e.g. enums) that
88+
// can be used in PHP code.
89+
90+
internalNamespace: 'PHPSTORM_META', // Namespace for all generated types which should not
91+
// be included in the PHP code and will only be used
92+
// for autocomplete.
93+
),
94+
);
95+
96+
// Pass AST into generator
97+
$result = $generator->generate($ast);
98+
99+
// Write result code into stdout
100+
echo $result;
101+
102+
file_put_contents(__DIR__ . '/.phpstorm.meta.php', (string)$result);
103+
```
104+
105+
You can also override some naming methods:
106+
107+
```php
108+
use FFI\Generator\PhpStormMetadataGenerator;
109+
use FFI\Generator\SimpleNamingStrategy;
110+
111+
$generator = new PhpStormMetadataGenerator(
112+
naming: new class extends SimpleNamingStrategy
113+
{
114+
// Each enum value will be converted to CamelCase
115+
// instead of UPPER_SNAKE_CASE (by default)
116+
protected function getEnumValueName(string $name): string
117+
{
118+
return $this->toCamelCase($name);
119+
}
120+
}
121+
);
122+
```
123+
124+
## Example
125+
126+
Below is the simplest complex code example:
127+
128+
```php
129+
use FFI\Generator\Metadata\CastXMLGenerator;
130+
use FFI\Generator\Metadata\CastXMLParser;
131+
use FFI\Generator\PhpStormMetadataGenerator;
132+
use FFI\Generator\SimpleNamingStrategy;
133+
134+
const INPUT_HEADERS = __DIR__ . '/path/to/headers.h';
135+
const OUTPUT_FILE = __DIR__ . '/path/to/.phpstorm.meta.php';
136+
137+
fwrite(STDOUT, " - [1/3] Generating metadata files\n");
138+
if (!is_file(INPUT_HEADERS . '.xml')) {
139+
(new CastXMLGenerator())
140+
->generate(INPUT_HEADERS)
141+
->save(INPUT_HEADERS . '.xml')
142+
;
143+
}
144+
145+
fwrite(STDOUT, " - [2/3] Building AST\n");
146+
$ast = (new CastXMLParser())
147+
->parse(INPUT_HEADERS . '.xml')
148+
;
149+
150+
fwrite(STDOUT, " - [3/3] Generating IDE helper\n");
151+
$result = (new PhpStormMetadataGenerator())
152+
->generate($ast)
153+
;
154+
155+
fwrite(STDOUT, " - DONE!\n");
156+
file_put_contents(OUTPUT_FILE, (string)$result);
157+
```

0 commit comments

Comments
 (0)