ffi / ide-helper-generator
FFI IDE helper generator for PHP
Installs: 5 916
Dependents: 5
Suggesters: 0
Security: 0
Stars: 4
Watchers: 1
Forks: 0
Open Issues: 1
Requires
- php: ^8.1
- ext-dom: *
- ext-libxml: *
- ext-mbstring: *
- nikic/php-parser: ^4.16|^5.0
- symfony/process: ^5.4|^6.0|^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.22
- php-parallel-lint/php-console-highlighter: ^1.0
- phpunit/phpunit: ^10.3
- symfony/var-dumper: ^5.4|^6.0
- vimeo/psalm: ^5.14
README
Requirements
Installation
Library is available as composer repository and can be installed using the following command in a root of your project as dev-dependency.
$ composer require ffi/ide-helper-generator --dev
Usage
Generate Metadata
Before generating the helper, the headers must be parsed to build the metadata
data. To do this, castxml
will be used, which in turn uses the original
compiler (like clang
) to build the AST.
use FFI\Generator\Metadata\CastXMLGenerator; (new CastXMLGenerator( binary: 'castxml', // path to binary (optional) temp: 'storage', // path to temp directory (optional) )) ->generate('/path/to/headers.h') ->save('/path/to/metadata.xml') ;
You can also to optimize this step by adding a file existence check:
if (!is_file('/path/to/metadata.xml')) { // Generate metadata: (new CastXMLGenerator())->... }
Analyze Metadata
After the metadata is generated, it should be parsed and an abstract syntax tree built in memory.
use FFI\Generator\Metadata\CastXMLParser; $ast = (new CastXMLParser()) ->parse('/path/to/metadata.xml') ;
Building IDE Helper
use FFI\Generator\PhpStormMetadataGenerator; use FFI\Generator\SimpleNamingStrategy; $generator = new PhpStormMetadataGenerator( argumentSetPrefix: 'ffi_', // Optional prefix for all argument sets to be registered // in metadata files. ignoreDirectories: ['/usr'], // Optional list of directories with headers whose types // should be excluded from the generated code. naming: new SimpleNamingStrategy( entrypoint: 'FFI\\Generated\\EntrypointInterface', // The name of the main FFI class // for which methods for autocomplete // will be generated. externalNamespace: 'FFI\\Generated', // Namespace for all public types (e.g. enums) that // can be used in PHP code. internalNamespace: 'PHPSTORM_META', // Namespace for all generated types which should not // be included in the PHP code and will only be used // for autocomplete. ), ); // Pass AST into generator $result = $generator->generate($ast); // Write result code into stdout echo $result; file_put_contents(__DIR__ . '/.phpstorm.meta.php', (string)$result);
You can also override some naming methods:
use FFI\Generator\PhpStormMetadataGenerator; use FFI\Generator\SimpleNamingStrategy; $generator = new PhpStormMetadataGenerator( naming: new class extends SimpleNamingStrategy { // Each enum value will be converted to CamelCase // instead of UPPER_SNAKE_CASE (by default) protected function getEnumValueName(string $name): string { return $this->toCamelCase($name); } } );
Example
Below is the simplest complex code example:
use FFI\Generator\Metadata\CastXMLGenerator; use FFI\Generator\Metadata\CastXMLParser; use FFI\Generator\PhpStormMetadataGenerator; use FFI\Generator\SimpleNamingStrategy; const INPUT_HEADERS = __DIR__ . '/path/to/headers.h'; const OUTPUT_FILE = __DIR__ . '/path/to/.phpstorm.meta.php'; fwrite(STDOUT, " - [1/3] Generating metadata files\n"); if (!is_file(INPUT_HEADERS . '.xml')) { (new CastXMLGenerator()) ->generate(INPUT_HEADERS) ->save(INPUT_HEADERS . '.xml') ; } fwrite(STDOUT, " - [2/3] Building AST\n"); $ast = (new CastXMLParser()) ->parse(INPUT_HEADERS . '.xml') ; fwrite(STDOUT, " - [3/3] Generating IDE helper\n"); $result = (new PhpStormMetadataGenerator()) ->generate($ast) ; fwrite(STDOUT, " - DONE!\n"); file_put_contents(OUTPUT_FILE, (string)$result);