1 <?php declare(strict_types=1);
5 use PHPUnit\Framework\TestCase;
7 class DummyNode extends NodeAbstract
12 public function __construct($subNode1, $subNode2, $attributes) {
13 parent::__construct($attributes);
14 $this->subNode1 = $subNode1;
15 $this->subNode2 = $subNode2;
18 public function getSubNodeNames() : array {
19 return ['subNode1', 'subNode2'];
22 // This method is only overwritten because the node is located in an unusual namespace
23 public function getType() : string {
28 class NodeAbstractTest extends TestCase
30 public function provideNodes() {
34 'startTokenPos' => 12,
39 new Comment('// Comment' . "\n"),
40 new Comment\Doc('/** doc comment */'),
44 $node = new DummyNode('value1', 'value2', $attributes);
45 $node->notSubNode = 'value3';
53 * @dataProvider provideNodes
55 public function testConstruct(array $attributes, Node $node) {
56 $this->assertSame('Dummy', $node->getType());
57 $this->assertSame(['subNode1', 'subNode2'], $node->getSubNodeNames());
58 $this->assertSame(10, $node->getLine());
59 $this->assertSame(10, $node->getStartLine());
60 $this->assertSame(11, $node->getEndLine());
61 $this->assertSame(12, $node->getStartTokenPos());
62 $this->assertSame(13, $node->getEndTokenPos());
63 $this->assertSame(14, $node->getStartFilePos());
64 $this->assertSame(15, $node->getEndFilePos());
65 $this->assertSame('/** doc comment */', $node->getDocComment()->getText());
66 $this->assertSame('value1', $node->subNode1);
67 $this->assertSame('value2', $node->subNode2);
68 $this->assertObjectHasAttribute('subNode1', $node);
69 $this->assertObjectHasAttribute('subNode2', $node);
70 $this->assertObjectNotHasAttribute('subNode3', $node);
71 $this->assertSame($attributes, $node->getAttributes());
72 $this->assertSame($attributes['comments'], $node->getComments());
78 * @dataProvider provideNodes
80 public function testGetDocComment(array $attributes, Node $node) {
81 $this->assertSame('/** doc comment */', $node->getDocComment()->getText());
82 $comments = $node->getComments();
84 array_pop($comments); // remove doc comment
85 $node->setAttribute('comments', $comments);
86 $this->assertNull($node->getDocComment());
88 array_pop($comments); // remove comment
89 $node->setAttribute('comments', $comments);
90 $this->assertNull($node->getDocComment());
93 public function testSetDocComment() {
94 $node = new DummyNode(null, null, []);
96 // Add doc comment to node without comments
97 $docComment = new Comment\Doc('/** doc */');
98 $node->setDocComment($docComment);
99 $this->assertSame($docComment, $node->getDocComment());
102 $docComment = new Comment\Doc('/** doc 2 */');
103 $node->setDocComment($docComment);
104 $this->assertSame($docComment, $node->getDocComment());
106 // Add docmment to node with other comments
107 $c1 = new Comment('/* foo */');
108 $c2 = new Comment('/* bar */');
109 $docComment = new Comment\Doc('/** baz */');
110 $node->setAttribute('comments', [$c1, $c2]);
111 $node->setDocComment($docComment);
112 $this->assertSame([$c1, $c2, $docComment], $node->getAttribute('comments'));
116 * @dataProvider provideNodes
118 public function testChange(array $attributes, Node $node) {
119 // direct modification
120 $node->subNode = 'newValue';
121 $this->assertSame('newValue', $node->subNode);
123 // indirect modification
124 $subNode =& $node->subNode;
125 $subNode = 'newNewValue';
126 $this->assertSame('newNewValue', $node->subNode);
129 unset($node->subNode);
130 $this->assertObjectNotHasAttribute('subNode', $node);
134 * @dataProvider provideNodes
136 public function testIteration(array $attributes, Node $node) {
137 // Iteration is simple object iteration over properties,
140 foreach ($node as $key => $value) {
142 $this->assertSame('subNode1', $key);
143 $this->assertSame('value1', $value);
144 } elseif ($i === 1) {
145 $this->assertSame('subNode2', $key);
146 $this->assertSame('value2', $value);
147 } elseif ($i === 2) {
148 $this->assertSame('notSubNode', $key);
149 $this->assertSame('value3', $value);
151 throw new \Exception;
155 $this->assertSame(3, $i);
158 public function testAttributes() {
159 /** @var $node Node */
160 $node = $this->getMockForAbstractClass(NodeAbstract::class);
162 $this->assertEmpty($node->getAttributes());
164 $node->setAttribute('key', 'value');
165 $this->assertTrue($node->hasAttribute('key'));
166 $this->assertSame('value', $node->getAttribute('key'));
168 $this->assertFalse($node->hasAttribute('doesNotExist'));
169 $this->assertNull($node->getAttribute('doesNotExist'));
170 $this->assertSame('default', $node->getAttribute('doesNotExist', 'default'));
172 $node->setAttribute('null', null);
173 $this->assertTrue($node->hasAttribute('null'));
174 $this->assertNull($node->getAttribute('null'));
175 $this->assertNull($node->getAttribute('null', 'default'));
182 $node->getAttributes()
185 $node->setAttributes(
196 $node->getAttributes()
200 public function testJsonSerialization() {
205 function functionName(&$a = 0, $b = 1.0) {
209 $expected = <<<'JSON'
212 "nodeType": "Stmt_Function",
215 "nodeType": "Identifier",
216 "name": "functionName",
229 "nodeType": "Expr_Variable",
237 "nodeType": "Scalar_LNumber",
256 "nodeType": "Expr_Variable",
264 "nodeType": "Scalar_DNumber",
280 "nodeType": "Stmt_Echo",
283 "nodeType": "Scalar_String",
302 "nodeType": "Comment",
303 "text": "\/\/ comment\n",
309 "nodeType": "Comment_Doc",
310 "text": "\/** doc comment *\/",
322 $parser = new Parser\Php7(new Lexer());
323 $stmts = $parser->parse(canonicalize($code));
324 $json = json_encode($stmts, JSON_PRETTY_PRINT);
325 $this->assertEquals(canonicalize($expected), canonicalize($json));