mirror of
https://github.com/danog/PHP-Parser.git
synced 2024-11-30 04:19:30 +01:00
Throw if NodeVisitor returns invalid value
This commit is contained in:
parent
2b6804aa50
commit
2b72bae3d9
@ -104,7 +104,7 @@ class NodeTraverser implements NodeTraverserInterface
|
|||||||
foreach ($node->getSubNodeNames() as $name) {
|
foreach ($node->getSubNodeNames() as $name) {
|
||||||
$subNode =& $node->$name;
|
$subNode =& $node->$name;
|
||||||
|
|
||||||
if (is_array($subNode)) {
|
if (\is_array($subNode)) {
|
||||||
$subNode = $this->traverseArray($subNode);
|
$subNode = $this->traverseArray($subNode);
|
||||||
if ($this->stopTraversal) {
|
if ($this->stopTraversal) {
|
||||||
break;
|
break;
|
||||||
@ -113,13 +113,19 @@ class NodeTraverser implements NodeTraverserInterface
|
|||||||
$traverseChildren = true;
|
$traverseChildren = true;
|
||||||
foreach ($this->visitors as $visitor) {
|
foreach ($this->visitors as $visitor) {
|
||||||
$return = $visitor->enterNode($subNode);
|
$return = $visitor->enterNode($subNode);
|
||||||
if (self::DONT_TRAVERSE_CHILDREN === $return) {
|
if (null !== $return) {
|
||||||
|
if ($return instanceof Node) {
|
||||||
|
$subNode = $return;
|
||||||
|
} elseif (self::DONT_TRAVERSE_CHILDREN === $return) {
|
||||||
$traverseChildren = false;
|
$traverseChildren = false;
|
||||||
} else if (self::STOP_TRAVERSAL === $return) {
|
} elseif (self::STOP_TRAVERSAL === $return) {
|
||||||
$this->stopTraversal = true;
|
$this->stopTraversal = true;
|
||||||
break 2;
|
break 2;
|
||||||
} else if (null !== $return) {
|
} else {
|
||||||
$subNode = $return;
|
throw new \LogicException(
|
||||||
|
'enterNode() returned invalid value of type ' . gettype($return)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,17 +138,22 @@ class NodeTraverser implements NodeTraverserInterface
|
|||||||
|
|
||||||
foreach ($this->visitors as $visitor) {
|
foreach ($this->visitors as $visitor) {
|
||||||
$return = $visitor->leaveNode($subNode);
|
$return = $visitor->leaveNode($subNode);
|
||||||
if (self::STOP_TRAVERSAL === $return) {
|
if (null !== $return) {
|
||||||
|
if ($return instanceof Node) {
|
||||||
|
$subNode = $return;
|
||||||
|
} elseif (self::STOP_TRAVERSAL === $return) {
|
||||||
$this->stopTraversal = true;
|
$this->stopTraversal = true;
|
||||||
break 2;
|
break 2;
|
||||||
} else if (null !== $return) {
|
} elseif (\is_array($return)) {
|
||||||
if (is_array($return)) {
|
|
||||||
throw new \LogicException(
|
throw new \LogicException(
|
||||||
'leaveNode() may only return an array ' .
|
'leaveNode() may only return an array ' .
|
||||||
'if the parent structure is an array'
|
'if the parent structure is an array'
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
throw new \LogicException(
|
||||||
|
'leaveNode() returned invalid value of type ' . gettype($return)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
$subNode = $return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,13 +177,19 @@ class NodeTraverser implements NodeTraverserInterface
|
|||||||
$traverseChildren = true;
|
$traverseChildren = true;
|
||||||
foreach ($this->visitors as $visitor) {
|
foreach ($this->visitors as $visitor) {
|
||||||
$return = $visitor->enterNode($node);
|
$return = $visitor->enterNode($node);
|
||||||
if (self::DONT_TRAVERSE_CHILDREN === $return) {
|
if (null !== $return) {
|
||||||
|
if ($return instanceof Node) {
|
||||||
|
$node = $return;
|
||||||
|
} elseif (self::DONT_TRAVERSE_CHILDREN === $return) {
|
||||||
$traverseChildren = false;
|
$traverseChildren = false;
|
||||||
} else if (self::STOP_TRAVERSAL === $return) {
|
} elseif (self::STOP_TRAVERSAL === $return) {
|
||||||
$this->stopTraversal = true;
|
$this->stopTraversal = true;
|
||||||
break 2;
|
break 2;
|
||||||
} else if (null !== $return) {
|
} else {
|
||||||
$node = $return;
|
throw new \LogicException(
|
||||||
|
'enterNode() returned invalid value of type ' . gettype($return)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,21 +202,26 @@ class NodeTraverser implements NodeTraverserInterface
|
|||||||
|
|
||||||
foreach ($this->visitors as $visitor) {
|
foreach ($this->visitors as $visitor) {
|
||||||
$return = $visitor->leaveNode($node);
|
$return = $visitor->leaveNode($node);
|
||||||
|
if (null !== $return) {
|
||||||
if (self::REMOVE_NODE === $return) {
|
if ($return instanceof Node) {
|
||||||
|
$node = $return;
|
||||||
|
} elseif (\is_array($return)) {
|
||||||
|
$doNodes[] = array($i, $return);
|
||||||
|
break;
|
||||||
|
} elseif (self::REMOVE_NODE === $return) {
|
||||||
$doNodes[] = array($i, array());
|
$doNodes[] = array($i, array());
|
||||||
break;
|
break;
|
||||||
} else if (self::STOP_TRAVERSAL === $return) {
|
} else if (self::STOP_TRAVERSAL === $return) {
|
||||||
$this->stopTraversal = true;
|
$this->stopTraversal = true;
|
||||||
break 2;
|
break 2;
|
||||||
} elseif (is_array($return)) {
|
} else {
|
||||||
$doNodes[] = array($i, $return);
|
throw new \LogicException(
|
||||||
break;
|
'leaveNode() returned invalid value of type ' . gettype($return)
|
||||||
} elseif (null !== $return) {
|
);
|
||||||
$node = $return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (is_array($node)) {
|
}
|
||||||
|
} else if (\is_array($node)) {
|
||||||
throw new \LogicException('Invalid node structure: Contains nested arrays');
|
throw new \LogicException('Invalid node structure: Contains nested arrays');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,17 +250,44 @@ class NodeTraverserTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \LogicException
|
* @dataProvider provideTestInvalidReturn
|
||||||
* @expectedExceptionMessage leaveNode() may only return an array if the parent structure is an array
|
|
||||||
*/
|
*/
|
||||||
public function testReplaceByArrayOnlyAllowedIfParentIsArray() {
|
public function testInvalidReturn($visitor, $message) {
|
||||||
$stmts = array(new Node\Expr\UnaryMinus(new Node\Scalar\LNumber(42)));
|
$this->setExpectedException(\LogicException::class, $message);
|
||||||
|
|
||||||
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
$stmts = array(new Node\Expr\UnaryMinus(new Node\Scalar\LNumber(42)));
|
||||||
$visitor->method('leaveNode')->willReturn(array(new Node\Scalar\DNumber(42.0)));
|
|
||||||
|
|
||||||
$traverser = new NodeTraverser();
|
$traverser = new NodeTraverser();
|
||||||
$traverser->addVisitor($visitor);
|
$traverser->addVisitor($visitor);
|
||||||
$traverser->traverse($stmts);
|
$traverser->traverse($stmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function provideTestInvalidReturn() {
|
||||||
|
$visitor1 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
||||||
|
$visitor1->expects($this->at(1))->method('enterNode')
|
||||||
|
->will($this->returnValue('foobar'));
|
||||||
|
|
||||||
|
$visitor2 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
||||||
|
$visitor2->expects($this->at(2))->method('enterNode')
|
||||||
|
->will($this->returnValue('foobar'));
|
||||||
|
|
||||||
|
$visitor3 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
||||||
|
$visitor3->expects($this->at(3))->method('leaveNode')
|
||||||
|
->will($this->returnValue('foobar'));
|
||||||
|
|
||||||
|
$visitor4 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
||||||
|
$visitor4->expects($this->at(4))->method('leaveNode')
|
||||||
|
->will($this->returnValue('foobar'));
|
||||||
|
|
||||||
|
$visitor5 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
||||||
|
$visitor5->method('leaveNode')->willReturn(array(new Node\Scalar\DNumber(42.0)));
|
||||||
|
|
||||||
|
return [
|
||||||
|
[$visitor1, 'enterNode() returned invalid value of type string'],
|
||||||
|
[$visitor2, 'enterNode() returned invalid value of type string'],
|
||||||
|
[$visitor3, 'leaveNode() returned invalid value of type string'],
|
||||||
|
[$visitor4, 'leaveNode() returned invalid value of type string'],
|
||||||
|
[$visitor5, 'leaveNode() may only return an array if the parent structure is an array'],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user