Chris@0: isPHP54 = version_compare(PHP_VERSION, '5.4.0', '>='); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function beforeTraverse(array $nodes) Chris@0: { Chris@0: $this->loopDepth = 0; Chris@0: } Chris@0: Chris@0: /** Chris@0: * @throws FatalErrorException if the node is a break or continue in a non-loop or switch context Chris@0: * @throws FatalErrorException if the node is trying to break out of more nested structures than exist Chris@0: * @throws FatalErrorException if the node is a break or continue and has a non-numeric argument Chris@0: * @throws FatalErrorException if the node is a break or continue and has an argument less than 1 Chris@0: * Chris@0: * @param Node $node Chris@0: */ Chris@0: public function enterNode(Node $node) Chris@0: { Chris@0: switch (true) { Chris@0: case $node instanceof Do_: Chris@0: case $node instanceof For_: Chris@0: case $node instanceof Foreach_: Chris@0: case $node instanceof Switch_: Chris@0: case $node instanceof While_: Chris@0: $this->loopDepth++; Chris@0: break; Chris@0: Chris@0: case $node instanceof Break_: Chris@0: case $node instanceof Continue_: Chris@0: $operator = $node instanceof Break_ ? 'break' : 'continue'; Chris@0: Chris@0: if ($this->loopDepth === 0) { Chris@0: $msg = sprintf("'%s' not in the 'loop' or 'switch' context", $operator); Chris@0: throw new FatalErrorException($msg, 0, E_ERROR, null, $node->getLine()); Chris@0: } Chris@0: Chris@0: if ($node->num instanceof LNumber || $node->num instanceof DNumber) { Chris@0: $num = $node->num->value; Chris@0: if ($this->isPHP54 && ($node->num instanceof DNumber || $num < 1)) { Chris@0: $msg = sprintf("'%s' operator accepts only positive numbers", $operator); Chris@0: throw new FatalErrorException($msg, 0, E_ERROR, null, $node->getLine()); Chris@0: } Chris@0: Chris@0: if ($num > $this->loopDepth) { Chris@0: $msg = sprintf("Cannot '%s' %d levels", $operator, $num); Chris@0: throw new FatalErrorException($msg, 0, E_ERROR, null, $node->getLine()); Chris@0: } Chris@0: } elseif ($node->num && $this->isPHP54) { Chris@0: $msg = sprintf("'%s' operator with non-constant operand is no longer supported", $operator); Chris@0: throw new FatalErrorException($msg, 0, E_ERROR, null, $node->getLine()); Chris@0: } Chris@0: break; Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param Node $node Chris@0: */ Chris@0: public function leaveNode(Node $node) Chris@0: { Chris@0: switch (true) { Chris@0: case $node instanceof Do_: Chris@0: case $node instanceof For_: Chris@0: case $node instanceof Foreach_: Chris@0: case $node instanceof Switch_: Chris@0: case $node instanceof While_: Chris@0: $this->loopDepth--; Chris@0: break; Chris@0: } Chris@0: } Chris@0: }