Chris@13
|
1 AST builders
|
Chris@13
|
2 ============
|
Chris@13
|
3
|
Chris@13
|
4 When PHP-Parser is used to generate (or modify) code by first creating an Abstract Syntax Tree and
|
Chris@13
|
5 then using the [pretty printer](Pretty_printing.markdown) to convert it to PHP code, it can often
|
Chris@13
|
6 be tedious to manually construct AST nodes. The project provides a number of utilities to simplify
|
Chris@13
|
7 the construction of common AST nodes.
|
Chris@13
|
8
|
Chris@13
|
9 Fluent builders
|
Chris@13
|
10 ---------------
|
Chris@13
|
11
|
Chris@13
|
12 The library comes with a number of builders, which allow creating node trees using a fluent
|
Chris@13
|
13 interface. Builders are created using the `BuilderFactory` and the final constructed node is
|
Chris@13
|
14 accessed through `getNode()`. Fluent builders are available for
|
Chris@13
|
15 the following syntactic elements:
|
Chris@13
|
16
|
Chris@13
|
17 * namespaces and use statements
|
Chris@13
|
18 * classes, interfaces and traits
|
Chris@13
|
19 * methods, functions and parameters
|
Chris@13
|
20 * properties
|
Chris@13
|
21
|
Chris@13
|
22 Here is an example:
|
Chris@13
|
23
|
Chris@13
|
24 ```php
|
Chris@13
|
25 use PhpParser\BuilderFactory;
|
Chris@13
|
26 use PhpParser\PrettyPrinter;
|
Chris@13
|
27 use PhpParser\Node;
|
Chris@13
|
28
|
Chris@13
|
29 $factory = new BuilderFactory;
|
Chris@13
|
30 $node = $factory->namespace('Name\Space')
|
Chris@17
|
31 ->addStmt($factory->use('Some\Other\Thingy')->as('SomeClass'))
|
Chris@17
|
32 ->addStmt($factory->useFunction('strlen'))
|
Chris@17
|
33 ->addStmt($factory->useConst('PHP_VERSION'))
|
Chris@13
|
34 ->addStmt($factory->class('SomeOtherClass')
|
Chris@13
|
35 ->extend('SomeClass')
|
Chris@13
|
36 ->implement('A\Few', '\Interfaces')
|
Chris@13
|
37 ->makeAbstract() // ->makeFinal()
|
Chris@13
|
38
|
Chris@17
|
39 ->addStmt($factory->useTrait('FirstTrait'))
|
Chris@17
|
40
|
Chris@17
|
41 ->addStmt($factory->useTrait('SecondTrait', 'ThirdTrait')
|
Chris@17
|
42 ->and('AnotherTrait')
|
Chris@17
|
43 ->with($factory->traitUseAdaptation('foo')->as('bar'))
|
Chris@17
|
44 ->with($factory->traitUseAdaptation('AnotherTrait', 'baz')->as('test'))
|
Chris@17
|
45 ->with($factory->traitUseAdaptation('AnotherTrait', 'func')->insteadof('SecondTrait')))
|
Chris@17
|
46
|
Chris@13
|
47 ->addStmt($factory->method('someMethod')
|
Chris@13
|
48 ->makePublic()
|
Chris@13
|
49 ->makeAbstract() // ->makeFinal()
|
Chris@17
|
50 ->setReturnType('bool') // ->makeReturnByRef()
|
Chris@17
|
51 ->addParam($factory->param('someParam')->setType('SomeClass'))
|
Chris@13
|
52 ->setDocComment('/**
|
Chris@13
|
53 * This method does something.
|
Chris@13
|
54 *
|
Chris@13
|
55 * @param SomeClass And takes a parameter
|
Chris@13
|
56 */')
|
Chris@13
|
57 )
|
Chris@13
|
58
|
Chris@13
|
59 ->addStmt($factory->method('anotherMethod')
|
Chris@13
|
60 ->makeProtected() // ->makePublic() [default], ->makePrivate()
|
Chris@13
|
61 ->addParam($factory->param('someParam')->setDefault('test'))
|
Chris@13
|
62 // it is possible to add manually created nodes
|
Chris@13
|
63 ->addStmt(new Node\Expr\Print_(new Node\Expr\Variable('someParam')))
|
Chris@13
|
64 )
|
Chris@13
|
65
|
Chris@13
|
66 // properties will be correctly reordered above the methods
|
Chris@13
|
67 ->addStmt($factory->property('someProperty')->makeProtected())
|
Chris@13
|
68 ->addStmt($factory->property('anotherProperty')->makePrivate()->setDefault(array(1, 2, 3)))
|
Chris@13
|
69 )
|
Chris@13
|
70
|
Chris@13
|
71 ->getNode()
|
Chris@13
|
72 ;
|
Chris@13
|
73
|
Chris@13
|
74 $stmts = array($node);
|
Chris@13
|
75 $prettyPrinter = new PrettyPrinter\Standard();
|
Chris@13
|
76 echo $prettyPrinter->prettyPrintFile($stmts);
|
Chris@13
|
77 ```
|
Chris@13
|
78
|
Chris@13
|
79 This will produce the following output with the standard pretty printer:
|
Chris@13
|
80
|
Chris@13
|
81 ```php
|
Chris@13
|
82 <?php
|
Chris@13
|
83
|
Chris@13
|
84 namespace Name\Space;
|
Chris@13
|
85
|
Chris@13
|
86 use Some\Other\Thingy as SomeClass;
|
Chris@17
|
87 use function strlen;
|
Chris@17
|
88 use const PHP_VERSION;
|
Chris@13
|
89 abstract class SomeOtherClass extends SomeClass implements A\Few, \Interfaces
|
Chris@13
|
90 {
|
Chris@17
|
91 use FirstTrait;
|
Chris@17
|
92 use SecondTrait, ThirdTrait, AnotherTrait {
|
Chris@17
|
93 foo as bar;
|
Chris@17
|
94 AnotherTrait::baz as test;
|
Chris@17
|
95 AnotherTrait::func insteadof SecondTrait;
|
Chris@17
|
96 }
|
Chris@13
|
97 protected $someProperty;
|
Chris@13
|
98 private $anotherProperty = array(1, 2, 3);
|
Chris@13
|
99 /**
|
Chris@13
|
100 * This method does something.
|
Chris@13
|
101 *
|
Chris@13
|
102 * @param SomeClass And takes a parameter
|
Chris@13
|
103 */
|
Chris@13
|
104 public abstract function someMethod(SomeClass $someParam) : bool;
|
Chris@13
|
105 protected function anotherMethod($someParam = 'test')
|
Chris@13
|
106 {
|
Chris@13
|
107 print $someParam;
|
Chris@13
|
108 }
|
Chris@13
|
109 }
|
Chris@13
|
110 ```
|
Chris@13
|
111
|
Chris@13
|
112 Additional helper methods
|
Chris@13
|
113 -------------------------
|
Chris@13
|
114
|
Chris@13
|
115 The `BuilderFactory` also provides a number of additional helper methods, which directly return
|
Chris@13
|
116 nodes. The following methods are currently available:
|
Chris@13
|
117
|
Chris@13
|
118 * `val($value)`: Creates an AST node for a literal value like `42` or `[1, 2, 3]`.
|
Chris@17
|
119 * `var($name)`: Creates variable node.
|
Chris@13
|
120 * `args(array $args)`: Creates an array of function/method arguments, including the required `Arg`
|
Chris@13
|
121 wrappers. Also converts literals to AST nodes.
|
Chris@13
|
122 * `funcCall($name, array $args = [])`: Create a function call node. Converts `$name` to a `Name`
|
Chris@13
|
123 node and normalizes arguments.
|
Chris@13
|
124 * `methodCall(Expr $var, $name, array $args = [])`: Create a method call node. Converts `$name` to
|
Chris@13
|
125 an `Identifier` node and normalizes arguments.
|
Chris@13
|
126 * `staticCall($class, $name, array $args = [])`: Create a static method call node. Converts
|
Chris@13
|
127 `$class` to a `Name` node, `$name` to an `Identifier` node and normalizes arguments.
|
Chris@13
|
128 * `new($class, array $args = [])`: Create a "new" (object creation) node. Converts `$class` to a
|
Chris@13
|
129 `Name` node.
|
Chris@13
|
130 * `constFetch($name)`: Create a constant fetch node. Converts `$name` to a `Name` node.
|
Chris@13
|
131 * `classConstFetch($class, $name)`: Create a class constant fetch node. Converts `$class` to a
|
Chris@13
|
132 `Name` node and `$name` to an `Identifier` node.
|
Chris@17
|
133 * `propertyFetch($var, $name)`: Creates a property fetch node. Converts `$name` to an `Identifier`
|
Chris@17
|
134 node.
|
Chris@13
|
135 * `concat(...$exprs)`: Create a tree of `BinaryOp\Concat` nodes for the given expressions.
|
Chris@13
|
136
|
Chris@13
|
137 These methods may be expanded on an as-needed basis. Please open an issue or PR if a common
|
Chris@17
|
138 operation is missing.
|