Mercurial > hg > isophonics-drupal-site
comparison vendor/nikic/php-parser/test/PhpParser/NodeTraverserTest.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 5fb285c0d0e3 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace PhpParser; | |
4 | |
5 use PhpParser\Node\Expr; | |
6 use PhpParser\Node\Scalar\String_; | |
7 | |
8 class NodeTraverserTest extends \PHPUnit_Framework_TestCase | |
9 { | |
10 public function testNonModifying() { | |
11 $str1Node = new String_('Foo'); | |
12 $str2Node = new String_('Bar'); | |
13 $echoNode = new Node\Stmt\Echo_(array($str1Node, $str2Node)); | |
14 $stmts = array($echoNode); | |
15 | |
16 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
17 | |
18 $visitor->expects($this->at(0))->method('beforeTraverse')->with($stmts); | |
19 $visitor->expects($this->at(1))->method('enterNode')->with($echoNode); | |
20 $visitor->expects($this->at(2))->method('enterNode')->with($str1Node); | |
21 $visitor->expects($this->at(3))->method('leaveNode')->with($str1Node); | |
22 $visitor->expects($this->at(4))->method('enterNode')->with($str2Node); | |
23 $visitor->expects($this->at(5))->method('leaveNode')->with($str2Node); | |
24 $visitor->expects($this->at(6))->method('leaveNode')->with($echoNode); | |
25 $visitor->expects($this->at(7))->method('afterTraverse')->with($stmts); | |
26 | |
27 $traverser = new NodeTraverser; | |
28 $traverser->addVisitor($visitor); | |
29 | |
30 $this->assertEquals($stmts, $traverser->traverse($stmts)); | |
31 } | |
32 | |
33 public function testModifying() { | |
34 $str1Node = new String_('Foo'); | |
35 $str2Node = new String_('Bar'); | |
36 $printNode = new Expr\Print_($str1Node); | |
37 | |
38 // first visitor changes the node, second verifies the change | |
39 $visitor1 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
40 $visitor2 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
41 | |
42 // replace empty statements with string1 node | |
43 $visitor1->expects($this->at(0))->method('beforeTraverse')->with(array()) | |
44 ->will($this->returnValue(array($str1Node))); | |
45 $visitor2->expects($this->at(0))->method('beforeTraverse')->with(array($str1Node)); | |
46 | |
47 // replace string1 node with print node | |
48 $visitor1->expects($this->at(1))->method('enterNode')->with($str1Node) | |
49 ->will($this->returnValue($printNode)); | |
50 $visitor2->expects($this->at(1))->method('enterNode')->with($printNode); | |
51 | |
52 // replace string1 node with string2 node | |
53 $visitor1->expects($this->at(2))->method('enterNode')->with($str1Node) | |
54 ->will($this->returnValue($str2Node)); | |
55 $visitor2->expects($this->at(2))->method('enterNode')->with($str2Node); | |
56 | |
57 // replace string2 node with string1 node again | |
58 $visitor1->expects($this->at(3))->method('leaveNode')->with($str2Node) | |
59 ->will($this->returnValue($str1Node)); | |
60 $visitor2->expects($this->at(3))->method('leaveNode')->with($str1Node); | |
61 | |
62 // replace print node with string1 node again | |
63 $visitor1->expects($this->at(4))->method('leaveNode')->with($printNode) | |
64 ->will($this->returnValue($str1Node)); | |
65 $visitor2->expects($this->at(4))->method('leaveNode')->with($str1Node); | |
66 | |
67 // replace string1 node with empty statements again | |
68 $visitor1->expects($this->at(5))->method('afterTraverse')->with(array($str1Node)) | |
69 ->will($this->returnValue(array())); | |
70 $visitor2->expects($this->at(5))->method('afterTraverse')->with(array()); | |
71 | |
72 $traverser = new NodeTraverser; | |
73 $traverser->addVisitor($visitor1); | |
74 $traverser->addVisitor($visitor2); | |
75 | |
76 // as all operations are reversed we end where we start | |
77 $this->assertEquals(array(), $traverser->traverse(array())); | |
78 } | |
79 | |
80 public function testRemove() { | |
81 $str1Node = new String_('Foo'); | |
82 $str2Node = new String_('Bar'); | |
83 | |
84 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
85 | |
86 // remove the string1 node, leave the string2 node | |
87 $visitor->expects($this->at(2))->method('leaveNode')->with($str1Node) | |
88 ->will($this->returnValue(false)); | |
89 | |
90 $traverser = new NodeTraverser; | |
91 $traverser->addVisitor($visitor); | |
92 | |
93 $this->assertEquals(array($str2Node), $traverser->traverse(array($str1Node, $str2Node))); | |
94 } | |
95 | |
96 public function testMerge() { | |
97 $strStart = new String_('Start'); | |
98 $strMiddle = new String_('End'); | |
99 $strEnd = new String_('Middle'); | |
100 $strR1 = new String_('Replacement 1'); | |
101 $strR2 = new String_('Replacement 2'); | |
102 | |
103 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
104 | |
105 // replace strMiddle with strR1 and strR2 by merge | |
106 $visitor->expects($this->at(4))->method('leaveNode')->with($strMiddle) | |
107 ->will($this->returnValue(array($strR1, $strR2))); | |
108 | |
109 $traverser = new NodeTraverser; | |
110 $traverser->addVisitor($visitor); | |
111 | |
112 $this->assertEquals( | |
113 array($strStart, $strR1, $strR2, $strEnd), | |
114 $traverser->traverse(array($strStart, $strMiddle, $strEnd)) | |
115 ); | |
116 } | |
117 | |
118 public function testDeepArray() { | |
119 $strNode = new String_('Foo'); | |
120 $stmts = array(array(array($strNode))); | |
121 | |
122 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
123 $visitor->expects($this->at(1))->method('enterNode')->with($strNode); | |
124 | |
125 $traverser = new NodeTraverser; | |
126 $traverser->addVisitor($visitor); | |
127 | |
128 $this->assertEquals($stmts, $traverser->traverse($stmts)); | |
129 } | |
130 | |
131 public function testDontTraverseChildren() { | |
132 $strNode = new String_('str'); | |
133 $printNode = new Expr\Print_($strNode); | |
134 $varNode = new Expr\Variable('foo'); | |
135 $mulNode = new Expr\BinaryOp\Mul($varNode, $varNode); | |
136 $negNode = new Expr\UnaryMinus($mulNode); | |
137 $stmts = array($printNode, $negNode); | |
138 | |
139 $visitor1 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
140 $visitor2 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
141 | |
142 $visitor1->expects($this->at(1))->method('enterNode')->with($printNode) | |
143 ->will($this->returnValue(NodeTraverser::DONT_TRAVERSE_CHILDREN)); | |
144 $visitor2->expects($this->at(1))->method('enterNode')->with($printNode); | |
145 | |
146 $visitor1->expects($this->at(2))->method('leaveNode')->with($printNode); | |
147 $visitor2->expects($this->at(2))->method('leaveNode')->with($printNode); | |
148 | |
149 $visitor1->expects($this->at(3))->method('enterNode')->with($negNode); | |
150 $visitor2->expects($this->at(3))->method('enterNode')->with($negNode); | |
151 | |
152 $visitor1->expects($this->at(4))->method('enterNode')->with($mulNode); | |
153 $visitor2->expects($this->at(4))->method('enterNode')->with($mulNode) | |
154 ->will($this->returnValue(NodeTraverser::DONT_TRAVERSE_CHILDREN)); | |
155 | |
156 $visitor1->expects($this->at(5))->method('leaveNode')->with($mulNode); | |
157 $visitor2->expects($this->at(5))->method('leaveNode')->with($mulNode); | |
158 | |
159 $visitor1->expects($this->at(6))->method('leaveNode')->with($negNode); | |
160 $visitor2->expects($this->at(6))->method('leaveNode')->with($negNode); | |
161 | |
162 $traverser = new NodeTraverser; | |
163 $traverser->addVisitor($visitor1); | |
164 $traverser->addVisitor($visitor2); | |
165 | |
166 $this->assertEquals($stmts, $traverser->traverse($stmts)); | |
167 } | |
168 | |
169 public function testStopTraversal() { | |
170 $varNode1 = new Expr\Variable('a'); | |
171 $varNode2 = new Expr\Variable('b'); | |
172 $varNode3 = new Expr\Variable('c'); | |
173 $mulNode = new Expr\BinaryOp\Mul($varNode1, $varNode2); | |
174 $printNode = new Expr\Print_($varNode3); | |
175 $stmts = [$mulNode, $printNode]; | |
176 | |
177 // From enterNode() with array parent | |
178 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
179 $visitor->expects($this->at(1))->method('enterNode')->with($mulNode) | |
180 ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); | |
181 $visitor->expects($this->at(2))->method('afterTraverse'); | |
182 $traverser = new NodeTraverser; | |
183 $traverser->addVisitor($visitor); | |
184 $this->assertEquals($stmts, $traverser->traverse($stmts)); | |
185 | |
186 // From enterNode with Node parent | |
187 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
188 $visitor->expects($this->at(2))->method('enterNode')->with($varNode1) | |
189 ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); | |
190 $visitor->expects($this->at(3))->method('afterTraverse'); | |
191 $traverser = new NodeTraverser; | |
192 $traverser->addVisitor($visitor); | |
193 $this->assertEquals($stmts, $traverser->traverse($stmts)); | |
194 | |
195 // From leaveNode with Node parent | |
196 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
197 $visitor->expects($this->at(3))->method('leaveNode')->with($varNode1) | |
198 ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); | |
199 $visitor->expects($this->at(4))->method('afterTraverse'); | |
200 $traverser = new NodeTraverser; | |
201 $traverser->addVisitor($visitor); | |
202 $this->assertEquals($stmts, $traverser->traverse($stmts)); | |
203 | |
204 // From leaveNode with array parent | |
205 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
206 $visitor->expects($this->at(6))->method('leaveNode')->with($mulNode) | |
207 ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); | |
208 $visitor->expects($this->at(7))->method('afterTraverse'); | |
209 $traverser = new NodeTraverser; | |
210 $traverser->addVisitor($visitor); | |
211 $this->assertEquals($stmts, $traverser->traverse($stmts)); | |
212 | |
213 // Check that pending array modifications are still carried out | |
214 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
215 $visitor->expects($this->at(6))->method('leaveNode')->with($mulNode) | |
216 ->will($this->returnValue(NodeTraverser::REMOVE_NODE)); | |
217 $visitor->expects($this->at(7))->method('enterNode')->with($printNode) | |
218 ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); | |
219 $visitor->expects($this->at(8))->method('afterTraverse'); | |
220 $traverser = new NodeTraverser; | |
221 $traverser->addVisitor($visitor); | |
222 $this->assertEquals([$printNode], $traverser->traverse($stmts)); | |
223 | |
224 } | |
225 | |
226 public function testRemovingVisitor() { | |
227 $visitor1 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
228 $visitor2 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
229 $visitor3 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
230 | |
231 $traverser = new NodeTraverser; | |
232 $traverser->addVisitor($visitor1); | |
233 $traverser->addVisitor($visitor2); | |
234 $traverser->addVisitor($visitor3); | |
235 | |
236 $preExpected = array($visitor1, $visitor2, $visitor3); | |
237 $this->assertAttributeSame($preExpected, 'visitors', $traverser, 'The appropriate visitors have not been added'); | |
238 | |
239 $traverser->removeVisitor($visitor2); | |
240 | |
241 $postExpected = array(0 => $visitor1, 2 => $visitor3); | |
242 $this->assertAttributeSame($postExpected, 'visitors', $traverser, 'The appropriate visitors are not present after removal'); | |
243 } | |
244 | |
245 public function testNoCloneNodes() { | |
246 $stmts = array(new Node\Stmt\Echo_(array(new String_('Foo'), new String_('Bar')))); | |
247 | |
248 $traverser = new NodeTraverser; | |
249 | |
250 $this->assertSame($stmts, $traverser->traverse($stmts)); | |
251 } | |
252 | |
253 /** | |
254 * @expectedException \LogicException | |
255 * @expectedExceptionMessage leaveNode() may only return an array if the parent structure is an array | |
256 */ | |
257 public function testReplaceByArrayOnlyAllowedIfParentIsArray() { | |
258 $stmts = array(new Node\Expr\UnaryMinus(new Node\Scalar\LNumber(42))); | |
259 | |
260 $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); | |
261 $visitor->method('leaveNode')->willReturn(array(new Node\Scalar\DNumber(42.0))); | |
262 | |
263 $traverser = new NodeTraverser(); | |
264 $traverser->addVisitor($visitor); | |
265 $traverser->traverse($stmts); | |
266 } | |
267 } |