open-code-modeling / php-code-ast
Open Code Modeling PHP 代码抽象语法树
0.12.3
2021-08-27 08:03 UTC
Requires
- php: ^7.4 || ^8.0
- ext-json: *
- nikic/php-parser: ^4.2
Requires (Dev)
- laminas/laminas-filter: ^2.9
- open-code-modeling/php-filter: ^0.1.1
- phpspec/prophecy-phpunit: ^2.0
- phpunit/phpunit: ^9.5.0
- prooph/php-cs-fixer-config: ^v0.4.0
- psalm/plugin-phpunit: ^0.15.0
- roave/security-advisories: dev-master
- vimeo/psalm: ^4.4
- 0.13.x-dev
- 0.12.x-dev
- 0.12.3
- 0.12.2
- 0.12.1
- 0.12.0
- 0.11.x-dev
- 0.11.1
- 0.11.0
- 0.10.x-dev
- 0.10.4
- 0.10.3
- 0.10.2
- 0.10.1
- 0.10.0
- 0.9.x-dev
- 0.9.0
- 0.8.x-dev
- 0.8.6
- 0.8.5
- 0.8.4
- 0.8.3
- 0.8.2
- 0.8.1
- 0.8.0
- 0.7.x-dev
- 0.7.1
- 0.7.0
- 0.6.x-dev
- 0.6.1
- 0.6.0
- 0.5.x-dev
- 0.5.1
- 0.5.0
- 0.4.0
- v0.3.1
- v0.3.0
- v0.2.3
- v0.2.2
- 0.2.1
- 0.2.0
- 0.1.0
- dev-feature/php-attributes-readonly-props
- dev-master
- dev-feature/node-collector
This package is auto-updated.
Last update: 2024-08-30 01:55:12 UTC
README
基于AST的PHP代码生成。
安装
$ composer require open-code-modeling/php-code-ast
使用
请参阅
tests
文件夹中的单元测试以获取全面示例。
让我们从一个简单的例子开始,使用ClassBuilder
生成一个类
<?php $parser = (new PhpParser\ParserFactory())->create(PhpParser\ParserFactory::ONLY_PHP7); $printer = new PhpParser\PrettyPrinter\Standard(['shortArraySyntax' => true]); $ast = $parser->parse(''); $classBuilder = OpenCodeModeling\CodeAst\Builder\ClassBuilder::fromScratch('TestClass', 'My\\Awesome\\Service'); $classBuilder ->setFinal(true) ->setExtends('BaseClass') ->setNamespaceImports('Foo\\Bar') ->setImplements('\\Iterator', 'Bar'); $nodeTraverser = new PhpParser\NodeTraverser(); $classBuilder->injectVisitors($nodeTraverser, $parser); print_r($printer->prettyPrintFile($nodeTraverser->traverse($ast)));
将打印以下输出
<?php declare (strict_types=1); namespace My\Awesome\Service; use Foo\Bar; final class TestClass extends BaseClass implements \Iterator, Bar { }
所有这些操作都是通过PHP AST完成的,并且它会检查AST令牌是否已定义。因此,它不会覆盖您的代码。
您还可以使用代码和PHP AST访问者类通过低级API生成代码。要向上面的类添加一个toInt()
方法,您可以通过ClassMethod
访问者添加它。
<?php $method = new OpenCodeModeling\CodeAst\Code\MethodGenerator( 'toInt', [], OpenCodeModeling\CodeAst\Code\MethodGenerator::FLAG_PUBLIC, new OpenCodeModeling\CodeAst\Code\BodyGenerator($this->parser, 'return $this->myValue;') ); $method->setReturnType('int'); $nodeTraverser->addVisitor(new OpenCodeModeling\CodeAst\NodeVisitor\ClassMethod($method)); print_r($printer->prettyPrintFile($nodeTraverser->traverse($ast)));
这将打印以下输出。
<?php declare (strict_types=1); namespace My\Awesome\Service; use Foo\Bar; final class TestClass extends BaseClass implements \Iterator, Bar { public function toInt() : int { return $this->myValue; } }
现在,将toInt()
方法的主体更改为其他内容。您会看到您的更改将不会被覆盖。
反向使用
还可以从解析的PHP AST创建一个工厂类。您可以通过调用OpenCodeModeling\CodeAst\Builder\ClassBuilder::fromNodes()
来创建OpenCodeModeling\CodeAst\Builder\ClassBuilder
的一个实例。
<?php $parser = (new PhpParser\ParserFactory())->create(PhpParser\ParserFactory::ONLY_PHP7); $printer = new PhpParser\PrettyPrinter\Standard(['shortArraySyntax' => true]); $expected = <<<'EOF' <?php declare (strict_types=1); namespace My\Awesome\Service; use Foo\Bar; final class TestClass extends BaseClass implements \Iterator, Bar { private const PRIV = 'private'; } EOF; $ast = $parser->parse($expected); $classBuilder = OpenCodeModeling\CodeAst\Builder\ClassBuilder::fromNodes(...$ast); $classBuilder->getName(); // TestClass $classBuilder->getExtends(); // BaseClass $classBuilder->isFinal(); // true $classBuilder->isStrict(); // true $classBuilder->isAbstract(); // false