Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace PhpParser;
|
Chris@0
|
4
|
Chris@0
|
5 class DummyNode extends NodeAbstract {
|
Chris@0
|
6 public $subNode1;
|
Chris@0
|
7 public $subNode2;
|
Chris@0
|
8
|
Chris@0
|
9 public function __construct($subNode1, $subNode2, $attributes) {
|
Chris@0
|
10 parent::__construct($attributes);
|
Chris@0
|
11 $this->subNode1 = $subNode1;
|
Chris@0
|
12 $this->subNode2 = $subNode2;
|
Chris@0
|
13 }
|
Chris@0
|
14
|
Chris@0
|
15 public function getSubNodeNames() {
|
Chris@0
|
16 return array('subNode1', 'subNode2');
|
Chris@0
|
17 }
|
Chris@0
|
18
|
Chris@0
|
19 // This method is only overwritten because the node is located in an unusual namespace
|
Chris@0
|
20 public function getType() {
|
Chris@0
|
21 return 'Dummy';
|
Chris@0
|
22 }
|
Chris@0
|
23 }
|
Chris@0
|
24
|
Chris@0
|
25 class NodeAbstractTest extends \PHPUnit_Framework_TestCase
|
Chris@0
|
26 {
|
Chris@0
|
27 public function provideNodes() {
|
Chris@0
|
28 $attributes = array(
|
Chris@0
|
29 'startLine' => 10,
|
Chris@0
|
30 'comments' => array(
|
Chris@0
|
31 new Comment('// Comment' . "\n"),
|
Chris@0
|
32 new Comment\Doc('/** doc comment */'),
|
Chris@0
|
33 ),
|
Chris@0
|
34 );
|
Chris@0
|
35
|
Chris@0
|
36 $node = new DummyNode('value1', 'value2', $attributes);
|
Chris@0
|
37 $node->notSubNode = 'value3';
|
Chris@0
|
38
|
Chris@0
|
39 return array(
|
Chris@0
|
40 array($attributes, $node),
|
Chris@0
|
41 );
|
Chris@0
|
42 }
|
Chris@0
|
43
|
Chris@0
|
44 /**
|
Chris@0
|
45 * @dataProvider provideNodes
|
Chris@0
|
46 */
|
Chris@0
|
47 public function testConstruct(array $attributes, Node $node) {
|
Chris@0
|
48 $this->assertSame('Dummy', $node->getType());
|
Chris@0
|
49 $this->assertSame(array('subNode1', 'subNode2'), $node->getSubNodeNames());
|
Chris@0
|
50 $this->assertSame(10, $node->getLine());
|
Chris@0
|
51 $this->assertSame('/** doc comment */', $node->getDocComment()->getText());
|
Chris@0
|
52 $this->assertSame('value1', $node->subNode1);
|
Chris@0
|
53 $this->assertSame('value2', $node->subNode2);
|
Chris@0
|
54 $this->assertTrue(isset($node->subNode1));
|
Chris@0
|
55 $this->assertTrue(isset($node->subNode2));
|
Chris@0
|
56 $this->assertFalse(isset($node->subNode3));
|
Chris@0
|
57 $this->assertSame($attributes, $node->getAttributes());
|
Chris@0
|
58
|
Chris@0
|
59 return $node;
|
Chris@0
|
60 }
|
Chris@0
|
61
|
Chris@0
|
62 /**
|
Chris@0
|
63 * @dataProvider provideNodes
|
Chris@0
|
64 */
|
Chris@0
|
65 public function testGetDocComment(array $attributes, Node $node) {
|
Chris@0
|
66 $this->assertSame('/** doc comment */', $node->getDocComment()->getText());
|
Chris@0
|
67 array_pop($node->getAttribute('comments')); // remove doc comment
|
Chris@0
|
68 $this->assertNull($node->getDocComment());
|
Chris@0
|
69 array_pop($node->getAttribute('comments')); // remove comment
|
Chris@0
|
70 $this->assertNull($node->getDocComment());
|
Chris@0
|
71 }
|
Chris@0
|
72
|
Chris@0
|
73 public function testSetDocComment() {
|
Chris@0
|
74 $node = new DummyNode(null, null, []);
|
Chris@0
|
75
|
Chris@0
|
76 // Add doc comment to node without comments
|
Chris@0
|
77 $docComment = new Comment\Doc('/** doc */');
|
Chris@0
|
78 $node->setDocComment($docComment);
|
Chris@0
|
79 $this->assertSame($docComment, $node->getDocComment());
|
Chris@0
|
80
|
Chris@0
|
81 // Replace it
|
Chris@0
|
82 $docComment = new Comment\Doc('/** doc 2 */');
|
Chris@0
|
83 $node->setDocComment($docComment);
|
Chris@0
|
84 $this->assertSame($docComment, $node->getDocComment());
|
Chris@0
|
85
|
Chris@0
|
86 // Add docmment to node with other comments
|
Chris@0
|
87 $c1 = new Comment('/* foo */');
|
Chris@0
|
88 $c2 = new Comment('/* bar */');
|
Chris@0
|
89 $docComment = new Comment\Doc('/** baz */');
|
Chris@0
|
90 $node->setAttribute('comments', [$c1, $c2]);
|
Chris@0
|
91 $node->setDocComment($docComment);
|
Chris@0
|
92 $this->assertSame([$c1, $c2, $docComment], $node->getAttribute('comments'));
|
Chris@0
|
93 }
|
Chris@0
|
94
|
Chris@0
|
95 /**
|
Chris@0
|
96 * @dataProvider provideNodes
|
Chris@0
|
97 */
|
Chris@0
|
98 public function testChange(array $attributes, Node $node) {
|
Chris@0
|
99 // change of line
|
Chris@0
|
100 $node->setLine(15);
|
Chris@0
|
101 $this->assertSame(15, $node->getLine());
|
Chris@0
|
102
|
Chris@0
|
103 // direct modification
|
Chris@0
|
104 $node->subNode = 'newValue';
|
Chris@0
|
105 $this->assertSame('newValue', $node->subNode);
|
Chris@0
|
106
|
Chris@0
|
107 // indirect modification
|
Chris@0
|
108 $subNode =& $node->subNode;
|
Chris@0
|
109 $subNode = 'newNewValue';
|
Chris@0
|
110 $this->assertSame('newNewValue', $node->subNode);
|
Chris@0
|
111
|
Chris@0
|
112 // removal
|
Chris@0
|
113 unset($node->subNode);
|
Chris@0
|
114 $this->assertFalse(isset($node->subNode));
|
Chris@0
|
115 }
|
Chris@0
|
116
|
Chris@0
|
117 /**
|
Chris@0
|
118 * @dataProvider provideNodes
|
Chris@0
|
119 */
|
Chris@0
|
120 public function testIteration(array $attributes, Node $node) {
|
Chris@0
|
121 // Iteration is simple object iteration over properties,
|
Chris@0
|
122 // not over subnodes
|
Chris@0
|
123 $i = 0;
|
Chris@0
|
124 foreach ($node as $key => $value) {
|
Chris@0
|
125 if ($i === 0) {
|
Chris@0
|
126 $this->assertSame('subNode1', $key);
|
Chris@0
|
127 $this->assertSame('value1', $value);
|
Chris@0
|
128 } else if ($i === 1) {
|
Chris@0
|
129 $this->assertSame('subNode2', $key);
|
Chris@0
|
130 $this->assertSame('value2', $value);
|
Chris@0
|
131 } else if ($i === 2) {
|
Chris@0
|
132 $this->assertSame('notSubNode', $key);
|
Chris@0
|
133 $this->assertSame('value3', $value);
|
Chris@0
|
134 } else {
|
Chris@0
|
135 throw new \Exception;
|
Chris@0
|
136 }
|
Chris@0
|
137 $i++;
|
Chris@0
|
138 }
|
Chris@0
|
139 $this->assertSame(3, $i);
|
Chris@0
|
140 }
|
Chris@0
|
141
|
Chris@0
|
142 public function testAttributes() {
|
Chris@0
|
143 /** @var $node Node */
|
Chris@0
|
144 $node = $this->getMockForAbstractClass('PhpParser\NodeAbstract');
|
Chris@0
|
145
|
Chris@0
|
146 $this->assertEmpty($node->getAttributes());
|
Chris@0
|
147
|
Chris@0
|
148 $node->setAttribute('key', 'value');
|
Chris@0
|
149 $this->assertTrue($node->hasAttribute('key'));
|
Chris@0
|
150 $this->assertSame('value', $node->getAttribute('key'));
|
Chris@0
|
151
|
Chris@0
|
152 $this->assertFalse($node->hasAttribute('doesNotExist'));
|
Chris@0
|
153 $this->assertNull($node->getAttribute('doesNotExist'));
|
Chris@0
|
154 $this->assertSame('default', $node->getAttribute('doesNotExist', 'default'));
|
Chris@0
|
155
|
Chris@0
|
156 $node->setAttribute('null', null);
|
Chris@0
|
157 $this->assertTrue($node->hasAttribute('null'));
|
Chris@0
|
158 $this->assertNull($node->getAttribute('null'));
|
Chris@0
|
159 $this->assertNull($node->getAttribute('null', 'default'));
|
Chris@0
|
160
|
Chris@0
|
161 $this->assertSame(
|
Chris@0
|
162 array(
|
Chris@0
|
163 'key' => 'value',
|
Chris@0
|
164 'null' => null,
|
Chris@0
|
165 ),
|
Chris@0
|
166 $node->getAttributes()
|
Chris@0
|
167 );
|
Chris@0
|
168 }
|
Chris@0
|
169
|
Chris@0
|
170 public function testJsonSerialization() {
|
Chris@0
|
171 $code = <<<'PHP'
|
Chris@0
|
172 <?php
|
Chris@0
|
173 // comment
|
Chris@0
|
174 /** doc comment */
|
Chris@0
|
175 function functionName(&$a = 0, $b = 1.0) {
|
Chris@0
|
176 echo 'Foo';
|
Chris@0
|
177 }
|
Chris@0
|
178 PHP;
|
Chris@0
|
179 $expected = <<<'JSON'
|
Chris@0
|
180 [
|
Chris@0
|
181 {
|
Chris@0
|
182 "nodeType": "Stmt_Function",
|
Chris@0
|
183 "byRef": false,
|
Chris@0
|
184 "name": "functionName",
|
Chris@0
|
185 "params": [
|
Chris@0
|
186 {
|
Chris@0
|
187 "nodeType": "Param",
|
Chris@0
|
188 "type": null,
|
Chris@0
|
189 "byRef": true,
|
Chris@0
|
190 "variadic": false,
|
Chris@0
|
191 "name": "a",
|
Chris@0
|
192 "default": {
|
Chris@0
|
193 "nodeType": "Scalar_LNumber",
|
Chris@0
|
194 "value": 0,
|
Chris@0
|
195 "attributes": {
|
Chris@0
|
196 "startLine": 4,
|
Chris@0
|
197 "endLine": 4,
|
Chris@0
|
198 "kind": 10
|
Chris@0
|
199 }
|
Chris@0
|
200 },
|
Chris@0
|
201 "attributes": {
|
Chris@0
|
202 "startLine": 4,
|
Chris@0
|
203 "endLine": 4
|
Chris@0
|
204 }
|
Chris@0
|
205 },
|
Chris@0
|
206 {
|
Chris@0
|
207 "nodeType": "Param",
|
Chris@0
|
208 "type": null,
|
Chris@0
|
209 "byRef": false,
|
Chris@0
|
210 "variadic": false,
|
Chris@0
|
211 "name": "b",
|
Chris@0
|
212 "default": {
|
Chris@0
|
213 "nodeType": "Scalar_DNumber",
|
Chris@0
|
214 "value": 1,
|
Chris@0
|
215 "attributes": {
|
Chris@0
|
216 "startLine": 4,
|
Chris@0
|
217 "endLine": 4
|
Chris@0
|
218 }
|
Chris@0
|
219 },
|
Chris@0
|
220 "attributes": {
|
Chris@0
|
221 "startLine": 4,
|
Chris@0
|
222 "endLine": 4
|
Chris@0
|
223 }
|
Chris@0
|
224 }
|
Chris@0
|
225 ],
|
Chris@0
|
226 "returnType": null,
|
Chris@0
|
227 "stmts": [
|
Chris@0
|
228 {
|
Chris@0
|
229 "nodeType": "Stmt_Echo",
|
Chris@0
|
230 "exprs": [
|
Chris@0
|
231 {
|
Chris@0
|
232 "nodeType": "Scalar_String",
|
Chris@0
|
233 "value": "Foo",
|
Chris@0
|
234 "attributes": {
|
Chris@0
|
235 "startLine": 5,
|
Chris@0
|
236 "endLine": 5,
|
Chris@0
|
237 "kind": 1
|
Chris@0
|
238 }
|
Chris@0
|
239 }
|
Chris@0
|
240 ],
|
Chris@0
|
241 "attributes": {
|
Chris@0
|
242 "startLine": 5,
|
Chris@0
|
243 "endLine": 5
|
Chris@0
|
244 }
|
Chris@0
|
245 }
|
Chris@0
|
246 ],
|
Chris@0
|
247 "attributes": {
|
Chris@0
|
248 "startLine": 4,
|
Chris@0
|
249 "comments": [
|
Chris@0
|
250 {
|
Chris@0
|
251 "nodeType": "Comment",
|
Chris@0
|
252 "text": "\/\/ comment\n",
|
Chris@0
|
253 "line": 2,
|
Chris@0
|
254 "filePos": 6
|
Chris@0
|
255 },
|
Chris@0
|
256 {
|
Chris@0
|
257 "nodeType": "Comment_Doc",
|
Chris@0
|
258 "text": "\/** doc comment *\/",
|
Chris@0
|
259 "line": 3,
|
Chris@0
|
260 "filePos": 17
|
Chris@0
|
261 }
|
Chris@0
|
262 ],
|
Chris@0
|
263 "endLine": 6
|
Chris@0
|
264 }
|
Chris@0
|
265 }
|
Chris@0
|
266 ]
|
Chris@0
|
267 JSON;
|
Chris@0
|
268
|
Chris@0
|
269 $parser = new Parser\Php7(new Lexer());
|
Chris@0
|
270 $stmts = $parser->parse(canonicalize($code));
|
Chris@0
|
271 $json = json_encode($stmts, JSON_PRETTY_PRINT);
|
Chris@0
|
272 $this->assertEquals(canonicalize($expected), canonicalize($json));
|
Chris@0
|
273 }
|
Chris@0
|
274 }
|