Chris@13
|
1 <?php declare(strict_types=1);
|
Chris@0
|
2
|
Chris@0
|
3 namespace PhpParser;
|
Chris@0
|
4
|
Chris@13
|
5 use PhpParser\Builder;
|
Chris@13
|
6 use PhpParser\Node\Arg;
|
Chris@0
|
7 use PhpParser\Node\Expr;
|
Chris@13
|
8 use PhpParser\Node\Expr\BinaryOp\Concat;
|
Chris@13
|
9 use PhpParser\Node\Identifier;
|
Chris@13
|
10 use PhpParser\Node\Name;
|
Chris@13
|
11 use PhpParser\Node\Scalar\LNumber;
|
Chris@13
|
12 use PhpParser\Node\Scalar\String_;
|
Chris@13
|
13 use PHPUnit\Framework\TestCase;
|
Chris@13
|
14 use Symfony\Component\Yaml\Tests\A;
|
Chris@0
|
15
|
Chris@13
|
16 class BuilderFactoryTest extends TestCase
|
Chris@0
|
17 {
|
Chris@0
|
18 /**
|
Chris@0
|
19 * @dataProvider provideTestFactory
|
Chris@0
|
20 */
|
Chris@0
|
21 public function testFactory($methodName, $className) {
|
Chris@0
|
22 $factory = new BuilderFactory;
|
Chris@0
|
23 $this->assertInstanceOf($className, $factory->$methodName('test'));
|
Chris@0
|
24 }
|
Chris@0
|
25
|
Chris@0
|
26 public function provideTestFactory() {
|
Chris@13
|
27 return [
|
Chris@13
|
28 ['namespace', Builder\Namespace_::class],
|
Chris@13
|
29 ['class', Builder\Class_::class],
|
Chris@13
|
30 ['interface', Builder\Interface_::class],
|
Chris@13
|
31 ['trait', Builder\Trait_::class],
|
Chris@13
|
32 ['method', Builder\Method::class],
|
Chris@13
|
33 ['function', Builder\Function_::class],
|
Chris@13
|
34 ['property', Builder\Property::class],
|
Chris@13
|
35 ['param', Builder\Param::class],
|
Chris@13
|
36 ['use', Builder\Use_::class],
|
Chris@13
|
37 ];
|
Chris@13
|
38 }
|
Chris@13
|
39
|
Chris@13
|
40 public function testVal() {
|
Chris@13
|
41 // This method is a wrapper around BuilderHelpers::normalizeValue(),
|
Chris@13
|
42 // which is already tested elsewhere
|
Chris@13
|
43 $factory = new BuilderFactory();
|
Chris@13
|
44 $this->assertEquals(
|
Chris@13
|
45 new String_("foo"),
|
Chris@13
|
46 $factory->val("foo")
|
Chris@0
|
47 );
|
Chris@0
|
48 }
|
Chris@0
|
49
|
Chris@13
|
50 public function testConcat() {
|
Chris@0
|
51 $factory = new BuilderFactory();
|
Chris@13
|
52 $varA = new Expr\Variable('a');
|
Chris@13
|
53 $varB = new Expr\Variable('b');
|
Chris@13
|
54 $varC = new Expr\Variable('c');
|
Chris@13
|
55
|
Chris@13
|
56 $this->assertEquals(
|
Chris@13
|
57 new Concat($varA, $varB),
|
Chris@13
|
58 $factory->concat($varA, $varB)
|
Chris@13
|
59 );
|
Chris@13
|
60 $this->assertEquals(
|
Chris@13
|
61 new Concat(new Concat($varA, $varB), $varC),
|
Chris@13
|
62 $factory->concat($varA, $varB, $varC)
|
Chris@13
|
63 );
|
Chris@13
|
64 $this->assertEquals(
|
Chris@13
|
65 new Concat(new Concat(new String_("a"), $varB), new String_("c")),
|
Chris@13
|
66 $factory->concat("a", $varB, "c")
|
Chris@13
|
67 );
|
Chris@13
|
68 }
|
Chris@13
|
69
|
Chris@13
|
70 /**
|
Chris@13
|
71 * @expectedException \LogicException
|
Chris@13
|
72 * @expectedExceptionMessage Expected at least two expressions
|
Chris@13
|
73 */
|
Chris@13
|
74 public function testConcatOneError() {
|
Chris@13
|
75 (new BuilderFactory())->concat("a");
|
Chris@13
|
76 }
|
Chris@13
|
77
|
Chris@13
|
78 /**
|
Chris@13
|
79 * @expectedException \LogicException
|
Chris@13
|
80 * @expectedExceptionMessage Expected string or Expr
|
Chris@13
|
81 */
|
Chris@13
|
82 public function testConcatInvalidExpr() {
|
Chris@13
|
83 (new BuilderFactory())->concat("a", 42);
|
Chris@13
|
84 }
|
Chris@13
|
85
|
Chris@13
|
86 public function testArgs() {
|
Chris@13
|
87 $factory = new BuilderFactory();
|
Chris@13
|
88 $unpack = new Arg(new Expr\Variable('c'), false, true);
|
Chris@13
|
89 $this->assertEquals(
|
Chris@13
|
90 [
|
Chris@13
|
91 new Arg(new Expr\Variable('a')),
|
Chris@13
|
92 new Arg(new String_('b')),
|
Chris@13
|
93 $unpack
|
Chris@13
|
94 ],
|
Chris@13
|
95 $factory->args([new Expr\Variable('a'), 'b', $unpack])
|
Chris@13
|
96 );
|
Chris@13
|
97 }
|
Chris@13
|
98
|
Chris@13
|
99 public function testCalls() {
|
Chris@13
|
100 $factory = new BuilderFactory();
|
Chris@13
|
101
|
Chris@13
|
102 // Simple function call
|
Chris@13
|
103 $this->assertEquals(
|
Chris@13
|
104 new Expr\FuncCall(
|
Chris@13
|
105 new Name('var_dump'),
|
Chris@13
|
106 [new Arg(new String_('str'))]
|
Chris@13
|
107 ),
|
Chris@13
|
108 $factory->funcCall('var_dump', ['str'])
|
Chris@13
|
109 );
|
Chris@13
|
110 // Dynamic function call
|
Chris@13
|
111 $this->assertEquals(
|
Chris@13
|
112 new Expr\FuncCall(new Expr\Variable('fn')),
|
Chris@13
|
113 $factory->funcCall(new Expr\Variable('fn'))
|
Chris@13
|
114 );
|
Chris@13
|
115
|
Chris@13
|
116 // Simple method call
|
Chris@13
|
117 $this->assertEquals(
|
Chris@13
|
118 new Expr\MethodCall(
|
Chris@13
|
119 new Expr\Variable('obj'),
|
Chris@13
|
120 new Identifier('method'),
|
Chris@13
|
121 [new Arg(new LNumber(42))]
|
Chris@13
|
122 ),
|
Chris@13
|
123 $factory->methodCall(new Expr\Variable('obj'), 'method', [42])
|
Chris@13
|
124 );
|
Chris@13
|
125 // Explicitly pass Identifier node
|
Chris@13
|
126 $this->assertEquals(
|
Chris@13
|
127 new Expr\MethodCall(
|
Chris@13
|
128 new Expr\Variable('obj'),
|
Chris@13
|
129 new Identifier('method')
|
Chris@13
|
130 ),
|
Chris@13
|
131 $factory->methodCall(new Expr\Variable('obj'), new Identifier('method'))
|
Chris@13
|
132 );
|
Chris@13
|
133 // Dynamic method call
|
Chris@13
|
134 $this->assertEquals(
|
Chris@13
|
135 new Expr\MethodCall(
|
Chris@13
|
136 new Expr\Variable('obj'),
|
Chris@13
|
137 new Expr\Variable('method')
|
Chris@13
|
138 ),
|
Chris@13
|
139 $factory->methodCall(new Expr\Variable('obj'), new Expr\Variable('method'))
|
Chris@13
|
140 );
|
Chris@13
|
141
|
Chris@13
|
142 // Simple static method call
|
Chris@13
|
143 $this->assertEquals(
|
Chris@13
|
144 new Expr\StaticCall(
|
Chris@13
|
145 new Name\FullyQualified('Foo'),
|
Chris@13
|
146 new Identifier('bar'),
|
Chris@13
|
147 [new Arg(new Expr\Variable('baz'))]
|
Chris@13
|
148 ),
|
Chris@13
|
149 $factory->staticCall('\Foo', 'bar', [new Expr\Variable('baz')])
|
Chris@13
|
150 );
|
Chris@13
|
151 // Dynamic static method call
|
Chris@13
|
152 $this->assertEquals(
|
Chris@13
|
153 new Expr\StaticCall(
|
Chris@13
|
154 new Expr\Variable('foo'),
|
Chris@13
|
155 new Expr\Variable('bar')
|
Chris@13
|
156 ),
|
Chris@13
|
157 $factory->staticCall(new Expr\Variable('foo'), new Expr\Variable('bar'))
|
Chris@13
|
158 );
|
Chris@13
|
159
|
Chris@13
|
160 // Simple new call
|
Chris@13
|
161 $this->assertEquals(
|
Chris@13
|
162 new Expr\New_(new Name\FullyQualified('stdClass')),
|
Chris@13
|
163 $factory->new('\stdClass')
|
Chris@13
|
164 );
|
Chris@13
|
165 // Dynamic new call
|
Chris@13
|
166 $this->assertEquals(
|
Chris@13
|
167 new Expr\New_(
|
Chris@13
|
168 new Expr\Variable('foo'),
|
Chris@13
|
169 [new Arg(new String_('bar'))]
|
Chris@13
|
170 ),
|
Chris@13
|
171 $factory->new(new Expr\Variable('foo'), ['bar'])
|
Chris@13
|
172 );
|
Chris@13
|
173 }
|
Chris@13
|
174
|
Chris@13
|
175 public function testConstFetches() {
|
Chris@13
|
176 $factory = new BuilderFactory();
|
Chris@13
|
177 $this->assertEquals(
|
Chris@13
|
178 new Expr\ConstFetch(new Name('FOO')),
|
Chris@13
|
179 $factory->constFetch('FOO')
|
Chris@13
|
180 );
|
Chris@13
|
181 $this->assertEquals(
|
Chris@13
|
182 new Expr\ClassConstFetch(new Name('Foo'), new Identifier('BAR')),
|
Chris@13
|
183 $factory->classConstFetch('Foo', 'BAR')
|
Chris@13
|
184 );
|
Chris@13
|
185 $this->assertEquals(
|
Chris@13
|
186 new Expr\ClassConstFetch(new Expr\Variable('foo'), new Identifier('BAR')),
|
Chris@13
|
187 $factory->classConstFetch(new Expr\Variable('foo'), 'BAR')
|
Chris@13
|
188 );
|
Chris@13
|
189 }
|
Chris@13
|
190
|
Chris@13
|
191 /**
|
Chris@13
|
192 * @expectedException \LogicException
|
Chris@13
|
193 * @expectedExceptionMessage Expected string or instance of Node\Identifier
|
Chris@13
|
194 */
|
Chris@13
|
195 public function testInvalidIdentifier() {
|
Chris@13
|
196 (new BuilderFactory())->classConstFetch('Foo', new Expr\Variable('foo'));
|
Chris@13
|
197 }
|
Chris@13
|
198
|
Chris@13
|
199 /**
|
Chris@13
|
200 * @expectedException \LogicException
|
Chris@13
|
201 * @expectedExceptionMessage Expected string or instance of Node\Identifier or Node\Expr
|
Chris@13
|
202 */
|
Chris@13
|
203 public function testInvalidIdentifierOrExpr() {
|
Chris@13
|
204 (new BuilderFactory())->staticCall('Foo', new Name('bar'));
|
Chris@13
|
205 }
|
Chris@13
|
206
|
Chris@13
|
207 /**
|
Chris@13
|
208 * @expectedException \LogicException
|
Chris@13
|
209 * @expectedExceptionMessage Name must be a string or an instance of Node\Name or Node\Expr
|
Chris@13
|
210 */
|
Chris@13
|
211 public function testInvalidNameOrExpr() {
|
Chris@13
|
212 (new BuilderFactory())->funcCall(new Node\Stmt\Return_());
|
Chris@0
|
213 }
|
Chris@0
|
214
|
Chris@0
|
215 public function testIntegration() {
|
Chris@0
|
216 $factory = new BuilderFactory;
|
Chris@0
|
217 $node = $factory->namespace('Name\Space')
|
Chris@0
|
218 ->addStmt($factory->use('Foo\Bar\SomeOtherClass'))
|
Chris@0
|
219 ->addStmt($factory->use('Foo\Bar')->as('A'))
|
Chris@0
|
220 ->addStmt($factory
|
Chris@0
|
221 ->class('SomeClass')
|
Chris@0
|
222 ->extend('SomeOtherClass')
|
Chris@0
|
223 ->implement('A\Few', '\Interfaces')
|
Chris@0
|
224 ->makeAbstract()
|
Chris@0
|
225
|
Chris@0
|
226 ->addStmt($factory->method('firstMethod'))
|
Chris@0
|
227
|
Chris@0
|
228 ->addStmt($factory->method('someMethod')
|
Chris@0
|
229 ->makePublic()
|
Chris@0
|
230 ->makeAbstract()
|
Chris@0
|
231 ->addParam($factory->param('someParam')->setTypeHint('SomeClass'))
|
Chris@0
|
232 ->setDocComment('/**
|
Chris@0
|
233 * This method does something.
|
Chris@0
|
234 *
|
Chris@0
|
235 * @param SomeClass And takes a parameter
|
Chris@0
|
236 */'))
|
Chris@0
|
237
|
Chris@0
|
238 ->addStmt($factory->method('anotherMethod')
|
Chris@0
|
239 ->makeProtected()
|
Chris@0
|
240 ->addParam($factory->param('someParam')->setDefault('test'))
|
Chris@0
|
241 ->addStmt(new Expr\Print_(new Expr\Variable('someParam'))))
|
Chris@0
|
242
|
Chris@0
|
243 ->addStmt($factory->property('someProperty')->makeProtected())
|
Chris@0
|
244 ->addStmt($factory->property('anotherProperty')
|
Chris@0
|
245 ->makePrivate()
|
Chris@13
|
246 ->setDefault([1, 2, 3])))
|
Chris@0
|
247 ->getNode()
|
Chris@0
|
248 ;
|
Chris@0
|
249
|
Chris@0
|
250 $expected = <<<'EOC'
|
Chris@0
|
251 <?php
|
Chris@0
|
252
|
Chris@0
|
253 namespace Name\Space;
|
Chris@0
|
254
|
Chris@0
|
255 use Foo\Bar\SomeOtherClass;
|
Chris@0
|
256 use Foo\Bar as A;
|
Chris@0
|
257 abstract class SomeClass extends SomeOtherClass implements A\Few, \Interfaces
|
Chris@0
|
258 {
|
Chris@0
|
259 protected $someProperty;
|
Chris@0
|
260 private $anotherProperty = array(1, 2, 3);
|
Chris@0
|
261 function firstMethod()
|
Chris@0
|
262 {
|
Chris@0
|
263 }
|
Chris@0
|
264 /**
|
Chris@0
|
265 * This method does something.
|
Chris@0
|
266 *
|
Chris@0
|
267 * @param SomeClass And takes a parameter
|
Chris@0
|
268 */
|
Chris@0
|
269 public abstract function someMethod(SomeClass $someParam);
|
Chris@0
|
270 protected function anotherMethod($someParam = 'test')
|
Chris@0
|
271 {
|
Chris@0
|
272 print $someParam;
|
Chris@0
|
273 }
|
Chris@0
|
274 }
|
Chris@0
|
275 EOC;
|
Chris@0
|
276
|
Chris@13
|
277 $stmts = [$node];
|
Chris@0
|
278 $prettyPrinter = new PrettyPrinter\Standard();
|
Chris@0
|
279 $generated = $prettyPrinter->prettyPrintFile($stmts);
|
Chris@0
|
280
|
Chris@0
|
281 $this->assertEquals(
|
Chris@0
|
282 str_replace("\r\n", "\n", $expected),
|
Chris@0
|
283 str_replace("\r\n", "\n", $generated)
|
Chris@0
|
284 );
|
Chris@0
|
285 }
|
Chris@0
|
286 }
|