ffi/ide-helper-generator

PHP FFI IDE 辅助生成器

0.1.12 2024-05-06 20:43 UTC

This package is auto-updated.

Last update: 2024-09-06 21:20:40 UTC


README

PHP 8.1+ Latest Stable Version Latest Unstable Version Total Downloads License MIT

要求

安装

库作为 composer 仓库可用,并且可以在项目根目录下作为开发依赖使用以下命令安装。

$ composer require ffi/ide-helper-generator --dev

用法

生成元数据

在生成辅助工具之前,必须解析头文件以构建元数据数据。为此,将使用 castxml,它反过来使用原始编译器(如 clang)来构建抽象语法树(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')
;

您还可以通过添加文件存在性检查来优化此步骤

if (!is_file('/path/to/metadata.xml')) {
    // Generate metadata: (new CastXMLGenerator())->...
}

分析元数据

在生成元数据后,应解析它并在内存中构建抽象语法树。

use FFI\Generator\Metadata\CastXMLParser;

$ast = (new CastXMLParser())
    ->parse('/path/to/metadata.xml')
;

构建 IDE 辅助工具

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);

您还可以覆盖一些命名方法

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);
        }
    }
);

示例

以下是最简单的复杂代码示例

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);