Chris@13: subNode1 = $subNode1; Chris@0: $this->subNode2 = $subNode2; Chris@0: } Chris@0: Chris@13: public function getSubNodeNames() : array { Chris@13: return ['subNode1', 'subNode2']; Chris@0: } Chris@0: Chris@0: // This method is only overwritten because the node is located in an unusual namespace Chris@13: public function getType() : string { Chris@0: return 'Dummy'; Chris@0: } Chris@0: } Chris@0: Chris@17: class NodeAbstractTest extends \PHPUnit\Framework\TestCase Chris@0: { Chris@0: public function provideNodes() { Chris@13: $attributes = [ Chris@0: 'startLine' => 10, Chris@13: 'endLine' => 11, Chris@13: 'startTokenPos' => 12, Chris@13: 'endTokenPos' => 13, Chris@13: 'startFilePos' => 14, Chris@13: 'endFilePos' => 15, Chris@13: 'comments' => [ Chris@0: new Comment('// Comment' . "\n"), Chris@0: new Comment\Doc('/** doc comment */'), Chris@13: ], Chris@13: ]; Chris@0: Chris@0: $node = new DummyNode('value1', 'value2', $attributes); Chris@0: $node->notSubNode = 'value3'; Chris@0: Chris@13: return [ Chris@13: [$attributes, $node], Chris@13: ]; Chris@0: } Chris@0: Chris@0: /** Chris@0: * @dataProvider provideNodes Chris@0: */ Chris@0: public function testConstruct(array $attributes, Node $node) { Chris@0: $this->assertSame('Dummy', $node->getType()); Chris@13: $this->assertSame(['subNode1', 'subNode2'], $node->getSubNodeNames()); Chris@0: $this->assertSame(10, $node->getLine()); Chris@13: $this->assertSame(10, $node->getStartLine()); Chris@13: $this->assertSame(11, $node->getEndLine()); Chris@13: $this->assertSame(12, $node->getStartTokenPos()); Chris@13: $this->assertSame(13, $node->getEndTokenPos()); Chris@13: $this->assertSame(14, $node->getStartFilePos()); Chris@13: $this->assertSame(15, $node->getEndFilePos()); Chris@0: $this->assertSame('/** doc comment */', $node->getDocComment()->getText()); Chris@0: $this->assertSame('value1', $node->subNode1); Chris@0: $this->assertSame('value2', $node->subNode2); Chris@13: $this->assertObjectHasAttribute('subNode1', $node); Chris@13: $this->assertObjectHasAttribute('subNode2', $node); Chris@13: $this->assertObjectNotHasAttribute('subNode3', $node); Chris@0: $this->assertSame($attributes, $node->getAttributes()); Chris@13: $this->assertSame($attributes['comments'], $node->getComments()); Chris@0: Chris@0: return $node; Chris@0: } Chris@0: Chris@0: /** Chris@0: * @dataProvider provideNodes Chris@0: */ Chris@0: public function testGetDocComment(array $attributes, Node $node) { Chris@0: $this->assertSame('/** doc comment */', $node->getDocComment()->getText()); Chris@13: $comments = $node->getComments(); Chris@13: Chris@13: array_pop($comments); // remove doc comment Chris@13: $node->setAttribute('comments', $comments); Chris@0: $this->assertNull($node->getDocComment()); Chris@13: Chris@13: array_pop($comments); // remove comment Chris@13: $node->setAttribute('comments', $comments); Chris@0: $this->assertNull($node->getDocComment()); Chris@0: } Chris@0: Chris@0: public function testSetDocComment() { Chris@0: $node = new DummyNode(null, null, []); Chris@0: Chris@0: // Add doc comment to node without comments Chris@0: $docComment = new Comment\Doc('/** doc */'); Chris@0: $node->setDocComment($docComment); Chris@0: $this->assertSame($docComment, $node->getDocComment()); Chris@0: Chris@0: // Replace it Chris@0: $docComment = new Comment\Doc('/** doc 2 */'); Chris@0: $node->setDocComment($docComment); Chris@0: $this->assertSame($docComment, $node->getDocComment()); Chris@0: Chris@0: // Add docmment to node with other comments Chris@0: $c1 = new Comment('/* foo */'); Chris@0: $c2 = new Comment('/* bar */'); Chris@0: $docComment = new Comment\Doc('/** baz */'); Chris@0: $node->setAttribute('comments', [$c1, $c2]); Chris@0: $node->setDocComment($docComment); Chris@0: $this->assertSame([$c1, $c2, $docComment], $node->getAttribute('comments')); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @dataProvider provideNodes Chris@0: */ Chris@0: public function testChange(array $attributes, Node $node) { Chris@0: // direct modification Chris@0: $node->subNode = 'newValue'; Chris@0: $this->assertSame('newValue', $node->subNode); Chris@0: Chris@0: // indirect modification Chris@0: $subNode =& $node->subNode; Chris@0: $subNode = 'newNewValue'; Chris@0: $this->assertSame('newNewValue', $node->subNode); Chris@0: Chris@0: // removal Chris@0: unset($node->subNode); Chris@13: $this->assertObjectNotHasAttribute('subNode', $node); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @dataProvider provideNodes Chris@0: */ Chris@0: public function testIteration(array $attributes, Node $node) { Chris@0: // Iteration is simple object iteration over properties, Chris@0: // not over subnodes Chris@0: $i = 0; Chris@0: foreach ($node as $key => $value) { Chris@0: if ($i === 0) { Chris@0: $this->assertSame('subNode1', $key); Chris@0: $this->assertSame('value1', $value); Chris@13: } elseif ($i === 1) { Chris@0: $this->assertSame('subNode2', $key); Chris@0: $this->assertSame('value2', $value); Chris@13: } elseif ($i === 2) { Chris@0: $this->assertSame('notSubNode', $key); Chris@0: $this->assertSame('value3', $value); Chris@0: } else { Chris@0: throw new \Exception; Chris@0: } Chris@0: $i++; Chris@0: } Chris@0: $this->assertSame(3, $i); Chris@0: } Chris@0: Chris@0: public function testAttributes() { Chris@0: /** @var $node Node */ Chris@13: $node = $this->getMockForAbstractClass(NodeAbstract::class); Chris@0: Chris@0: $this->assertEmpty($node->getAttributes()); Chris@0: Chris@0: $node->setAttribute('key', 'value'); Chris@0: $this->assertTrue($node->hasAttribute('key')); Chris@0: $this->assertSame('value', $node->getAttribute('key')); Chris@0: Chris@0: $this->assertFalse($node->hasAttribute('doesNotExist')); Chris@0: $this->assertNull($node->getAttribute('doesNotExist')); Chris@0: $this->assertSame('default', $node->getAttribute('doesNotExist', 'default')); Chris@0: Chris@0: $node->setAttribute('null', null); Chris@0: $this->assertTrue($node->hasAttribute('null')); Chris@0: $this->assertNull($node->getAttribute('null')); Chris@0: $this->assertNull($node->getAttribute('null', 'default')); Chris@0: Chris@0: $this->assertSame( Chris@13: [ Chris@0: 'key' => 'value', Chris@0: 'null' => null, Chris@13: ], Chris@13: $node->getAttributes() Chris@13: ); Chris@13: Chris@13: $node->setAttributes( Chris@13: [ Chris@13: 'a' => 'b', Chris@13: 'c' => null, Chris@13: ] Chris@13: ); Chris@13: $this->assertSame( Chris@13: [ Chris@13: 'a' => 'b', Chris@13: 'c' => null, Chris@13: ], Chris@0: $node->getAttributes() Chris@0: ); Chris@0: } Chris@0: Chris@0: public function testJsonSerialization() { Chris@0: $code = <<<'PHP' Chris@0: parse(canonicalize($code)); Chris@0: $json = json_encode($stmts, JSON_PRETTY_PRINT); Chris@0: $this->assertEquals(canonicalize($expected), canonicalize($json)); Chris@0: } Chris@0: }