File: AST_builders.markdown

package info (click to toggle)
php-parser 5.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 4,532 kB
  • sloc: php: 23,585; yacc: 1,272; makefile: 39; sh: 8
file content (141 lines) | stat: -rw-r--r-- 5,552 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
AST builders
============

When PHP-Parser is used to generate (or modify) code by first creating an Abstract Syntax Tree and
then using the [pretty printer](Pretty_printing.markdown) to convert it to PHP code, it can often
be tedious to manually construct AST nodes. The project provides a number of utilities to simplify
the construction of common AST nodes.

Fluent builders
---------------

The library comes with a number of builders, which allow creating node trees using a fluent
interface. Builders are created using the `BuilderFactory` and the final constructed node is
accessed through `getNode()`. Fluent builders are available for
the following syntactic elements:

 * namespaces and use statements
 * classes, interfaces, traits and enums
 * methods, functions and parameters
 * properties, class constants and enum cases
 * trait uses and trait use adaptations

Here is an example:

```php
use PhpParser\BuilderFactory;
use PhpParser\PrettyPrinter;
use PhpParser\Node;

$factory = new BuilderFactory;
$node = $factory->namespace('Name\Space')
    ->addStmt($factory->use('Some\Other\Thingy')->as('SomeClass'))
    ->addStmt($factory->useFunction('strlen'))
    ->addStmt($factory->useConst('PHP_VERSION'))
    ->addStmt($factory->class('SomeOtherClass')
        ->extend('SomeClass')
        ->implement('A\Few', '\Interfaces')
        ->makeAbstract() // ->makeFinal()

        ->addStmt($factory->useTrait('FirstTrait'))

        ->addStmt($factory->useTrait('SecondTrait', 'ThirdTrait')
            ->and('AnotherTrait')
            ->with($factory->traitUseAdaptation('foo')->as('bar'))
            ->with($factory->traitUseAdaptation('AnotherTrait', 'baz')->as('test'))
            ->with($factory->traitUseAdaptation('AnotherTrait', 'func')->insteadof('SecondTrait')))

        ->addStmt($factory->method('someMethod')
            ->makePublic()
            ->makeAbstract() // ->makeFinal()
            ->setReturnType('bool') // ->makeReturnByRef()
            ->addParam($factory->param('someParam')->setType('SomeClass'))
            ->setDocComment('/**
                              * This method does something.
                              *
                              * @param SomeClass And takes a parameter
                              */')
        )

        ->addStmt($factory->method('anotherMethod')
            ->makeProtected() // ->makePublic() [default], ->makePrivate()
            ->addParam($factory->param('someParam')->setDefault('test'))
            // it is possible to add manually created nodes
            ->addStmt(new Node\Expr\Print_(new Node\Expr\Variable('someParam')))
        )

        // properties will be correctly reordered above the methods
        ->addStmt($factory->property('someProperty')->makeProtected())
        ->addStmt($factory->property('anotherProperty')->makePrivate()->setDefault(array(1, 2, 3)))
    )

    ->getNode()
;

$stmts = array($node);
$prettyPrinter = new PrettyPrinter\Standard();
echo $prettyPrinter->prettyPrintFile($stmts);
```

This will produce the following output with the standard pretty printer:

```php
<?php

namespace Name\Space;

use Some\Other\Thingy as SomeClass;
use function strlen;
use const PHP_VERSION;
abstract class SomeOtherClass extends SomeClass implements A\Few, \Interfaces
{
    use FirstTrait;
    use SecondTrait, ThirdTrait, AnotherTrait {
        foo as bar;
        AnotherTrait::baz as test;
        AnotherTrait::func insteadof SecondTrait;
    }
    protected $someProperty;
    private $anotherProperty = [1, 2, 3];
    /**
     * This method does something.
     *
     * @param SomeClass And takes a parameter
     */
    abstract public function someMethod(SomeClass $someParam): bool;
    protected function anotherMethod($someParam = 'test')
    {
        print $someParam;
    }
}
```

Additional helper methods
-------------------------

The `BuilderFactory` also provides a number of additional helper methods, which directly return
nodes. The following methods are currently available:

 * `val($value)`: Creates an AST node for a literal value like `42` or `[1, 2, 3]`.
 * `var($name)`: Creates variable node.
 * `args(array $args)`: Creates an array of function/method arguments, including the required `Arg`
   wrappers. Also converts literals to AST nodes.
 * `funcCall($name, array $args = [])`: Create a function call node. Converts `$name` to a `Name`
   node and normalizes arguments.
 * `methodCall(Expr $var, $name, array $args = [])`: Create a method call node. Converts `$name` to
   an `Identifier` node and normalizes arguments.
 * `staticCall($class, $name, array $args = [])`: Create a static method call node. Converts
   `$class` to a `Name` node, `$name` to an `Identifier` node and normalizes arguments.
 * `new($class, array $args = [])`: Create a "new" (object creation) node. Converts `$class` to a
   `Name` node.
 * `constFetch($name)`: Create a constant fetch node. Converts `$name` to a `Name` node.
 * `classConstFetch($class, $name)`: Create a class constant fetch node. Converts `$class` to a
   `Name` node and `$name` to an `Identifier` node.
 * `propertyFetch($var, $name)`: Creates a property fetch node. Converts `$name` to an `Identifier`
   node.
 * `concat(...$exprs)`: Create a tree of `BinaryOp\Concat` nodes for the given expressions.
 * `attribute($name, $args)`: Create a `Attribute` node. Converts `$name` to a `Name` node and
   normalizes arguments.

These methods may be expanded on an as-needed basis. Please open an issue or PR if a common
operation is missing.