Compare commits

..

10 Commits

Author SHA1 Message Date
aa6aec90e1 Release PHP-Parser 3.0.1 2016-12-01 13:37:30 +01:00
3e158a2313 Wrap List_ in ArrayItem
This was correctly done for the 'key'=>list() form, but not for
unkeyed nested lists.
2016-12-01 13:32:37 +01:00
68973aed1e Release PHP-Parser 3.0 2016-11-30 19:20:29 +01:00
bcdfb703d5 Cleanup imports
Thanks PhpStorm :)
2016-11-23 22:58:18 +01:00
27281e9130 Fix attribute assignment for Error nodes 2016-11-23 22:51:32 +01:00
098294beec Support !!positions parser test mode
And use it for the group use prefix position test that was
previously implemented as a separate test.
2016-11-23 22:36:48 +01:00
b02f8ac07d Add support for dumping positions in NodeDumper 2016-11-23 22:25:17 +01:00
e52ffc4447 Support recovery from Foo:: 2016-11-22 19:47:04 +01:00
c5cdd5ad73 Support recovery from free-standing $ 2016-11-21 17:01:39 +01:00
c0630f8169 Support recovery for new without class name 2016-11-21 16:51:53 +01:00
49 changed files with 876 additions and 632 deletions

View File

@ -1,8 +1,25 @@
Version 3.0.0-dev Version 3.0.2-dev
----------------- -----------------
Nothing yet. Nothing yet.
Version 3.0.1 (2016-12-01)
--------------------------
### Fixed
* Fixed handling of nested `list()`s: If the nested list was unkeyed, it was directly included in
the list items. If it was keyed, it was wrapped in `ArrayItem`. Now nested `List_` nodes are
always wrapped in `ArrayItem`s.
Version 3.0.0 (2016-11-30)
--------------------------
### Added
* Added support for dumping node positions in the NodeDumper through the `dumpPositions` option.
* Added error recovery support for `$`, `new`, `Foo::`.
Version 3.0.0-beta2 (2016-10-29) Version 3.0.0-beta2 (2016-10-29)
-------------------------------- --------------------------------

View File

@ -6,9 +6,9 @@ PHP Parser
This is a PHP 5.2 to PHP 7.1 parser written in PHP. Its purpose is to simplify static code analysis and This is a PHP 5.2 to PHP 7.1 parser written in PHP. Its purpose is to simplify static code analysis and
manipulation. manipulation.
[Documentation for version 3.x][doc_master] (beta; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.1). [**Documentation for version 3.x**][doc_master] (stable; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.1).
[**Documentation for version 2.x**][doc_2_x] (stable; for running on PHP >= 5.4; for parsing PHP 5.2 to PHP 7.0). [Documentation for version 2.x][doc_2_x] (stable; for running on PHP >= 5.4; for parsing PHP 5.2 to PHP 7.0).
[Documentation for version 1.x][doc_1_x] (unsupported; for running on PHP >= 5.3; for parsing PHP 5.2 to PHP 5.6). [Documentation for version 1.x][doc_1_x] (unsupported; for running on PHP >= 5.3; for parsing PHP 5.2 to PHP 5.6).

View File

@ -939,7 +939,7 @@ list_expr_elements:
list_expr_element: list_expr_element:
variable { $$ = Expr\ArrayItem[$1, null, false]; } variable { $$ = Expr\ArrayItem[$1, null, false]; }
| list_expr { $$ = $1; } | list_expr { $$ = Expr\ArrayItem[$1, null, false]; }
| /* empty */ { $$ = null; } | /* empty */ { $$ = null; }
; ;

View File

@ -667,6 +667,7 @@ name:
class_name_reference: class_name_reference:
class_name { $$ = $1; } class_name { $$ = $1; }
| new_variable { $$ = $1; } | new_variable { $$ = $1; }
| error { $$ = Expr\Error[]; $this->errorState = 2; }
; ;
class_name_or_var: class_name_or_var:
@ -695,6 +696,10 @@ constant:
name { $$ = Expr\ConstFetch[$1]; } name { $$ = Expr\ConstFetch[$1]; }
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier
{ $$ = Expr\ClassConstFetch[$1, $3]; } { $$ = Expr\ClassConstFetch[$1, $3]; }
/* We interpret and isolated FOO:: as an unfinished class constant fetch. It could also be
an unfinished static property fetch or unfinished scoped call. */
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error
{ $$ = Expr\ClassConstFetch[$1, Expr\Error[]]; $this->errorState = 2; }
; ;
array_short_syntax: array_short_syntax:
@ -777,6 +782,7 @@ simple_variable:
T_VARIABLE { $$ = parseVar($1); } T_VARIABLE { $$ = parseVar($1); }
| '$' '{' expr '}' { $$ = $3; } | '$' '{' expr '}' { $$ = $3; }
| '$' simple_variable { $$ = Expr\Variable[$2]; } | '$' simple_variable { $$ = Expr\Variable[$2]; }
| '$' error { $$ = Expr\Error[]; $this->errorState = 2; }
; ;
static_member: static_member:
@ -817,7 +823,7 @@ list_expr_elements:
list_expr_element: list_expr_element:
variable { $$ = Expr\ArrayItem[$1, null, false]; } variable { $$ = Expr\ArrayItem[$1, null, false]; }
| list_expr { $$ = $1; } | list_expr { $$ = Expr\ArrayItem[$1, null, false]; }
| expr T_DOUBLE_ARROW variable { $$ = Expr\ArrayItem[$3, $1, false]; } | expr T_DOUBLE_ARROW variable { $$ = Expr\ArrayItem[$3, $1, false]; }
| expr T_DOUBLE_ARROW list_expr { $$ = Expr\ArrayItem[$3, $1, false]; } | expr T_DOUBLE_ARROW list_expr { $$ = Expr\ArrayItem[$3, $1, false]; }
| /* empty */ { $$ = null; } | /* empty */ { $$ = null; }

View File

@ -3,8 +3,6 @@
namespace PhpParser\Builder; namespace PhpParser\Builder;
use PhpParser; use PhpParser;
use PhpParser\Node;
use PhpParser\Node\Stmt;
abstract class Declaration extends PhpParser\BuilderAbstract abstract class Declaration extends PhpParser\BuilderAbstract
{ {

View File

@ -4,7 +4,6 @@ namespace PhpParser\Builder;
use PhpParser; use PhpParser;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Node\Stmt;
abstract class FunctionLike extends Declaration abstract class FunctionLike extends Declaration
{ {

View File

@ -3,7 +3,6 @@
namespace PhpParser\Builder; namespace PhpParser\Builder;
use PhpParser; use PhpParser;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt; use PhpParser\Node\Stmt;
class Trait_ extends Declaration class Trait_ extends Declaration

View File

@ -2,12 +2,12 @@
namespace PhpParser; namespace PhpParser;
use PhpParser\Node\Name;
use PhpParser\Node\Expr;
use PhpParser\Node\NullableType;
use PhpParser\Node\Stmt;
use PhpParser\Node\Scalar;
use PhpParser\Comment; use PhpParser\Comment;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt;
abstract class BuilderAbstract implements Builder { abstract class BuilderAbstract implements Builder {
/** /**

View File

@ -2,7 +2,6 @@
namespace PhpParser; namespace PhpParser;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Parser\Tokens; use PhpParser\Parser\Tokens;
class Lexer class Lexer

View File

@ -2,8 +2,8 @@
namespace PhpParser\Node\Expr; namespace PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Expr; use PhpParser\Node\Expr;
use PhpParser\Node\Name;
class ClassConstFetch extends Expr class ClassConstFetch extends Expr
{ {

View File

@ -2,8 +2,8 @@
namespace PhpParser\Node\Expr; namespace PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Expr; use PhpParser\Node\Expr;
use PhpParser\Node\Name;
class ConstFetch extends Expr class ConstFetch extends Expr
{ {

View File

@ -2,8 +2,8 @@
namespace PhpParser\Node\Expr; namespace PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Expr; use PhpParser\Node\Expr;
use PhpParser\Node\Name;
class Instanceof_ extends Expr class Instanceof_ extends Expr
{ {

View File

@ -2,8 +2,8 @@
namespace PhpParser\Node\Expr; namespace PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Expr; use PhpParser\Node\Expr;
use PhpParser\Node\Name;
class StaticPropertyFetch extends Expr class StaticPropertyFetch extends Expr
{ {

View File

@ -2,7 +2,6 @@
namespace PhpParser\Node; namespace PhpParser\Node;
use PhpParser\Error;
use PhpParser\NodeAbstract; use PhpParser\NodeAbstract;
class Param extends NodeAbstract class Param extends NodeAbstract

View File

@ -3,7 +3,6 @@
namespace PhpParser\Node\Stmt; namespace PhpParser\Node\Stmt;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Error;
class ClassConst extends Node\Stmt class ClassConst extends Node\Stmt
{ {

View File

@ -4,7 +4,6 @@ namespace PhpParser\Node\Stmt;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Node\FunctionLike; use PhpParser\Node\FunctionLike;
use PhpParser\Error;
class ClassMethod extends Node\Stmt implements FunctionLike class ClassMethod extends Node\Stmt implements FunctionLike
{ {

View File

@ -2,8 +2,8 @@
namespace PhpParser\Node\Stmt; namespace PhpParser\Node\Stmt;
use PhpParser\Node;
use PhpParser\Error; use PhpParser\Error;
use PhpParser\Node;
class Class_ extends ClassLike class Class_ extends ClassLike
{ {

View File

@ -3,6 +3,7 @@
namespace PhpParser\Node\Stmt; namespace PhpParser\Node\Stmt;
use PhpParser\Node; use PhpParser\Node;
class Declare_ extends Node\Stmt class Declare_ extends Node\Stmt
{ {
/** @var DeclareDeclare[] List of declares */ /** @var DeclareDeclare[] List of declares */

View File

@ -2,8 +2,8 @@
namespace PhpParser\Node\Stmt; namespace PhpParser\Node\Stmt;
use PhpParser\Node\Stmt;
use PhpParser\Node\Name; use PhpParser\Node\Name;
use PhpParser\Node\Stmt;
class GroupUse extends Stmt class GroupUse extends Stmt
{ {

View File

@ -3,7 +3,6 @@
namespace PhpParser\Node\Stmt; namespace PhpParser\Node\Stmt;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Error;
class Interface_ extends ClassLike class Interface_ extends ClassLike
{ {

View File

@ -3,7 +3,6 @@
namespace PhpParser\Node\Stmt; namespace PhpParser\Node\Stmt;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Error;
class Namespace_ extends Node\Stmt class Namespace_ extends Node\Stmt
{ {

View File

@ -3,7 +3,6 @@
namespace PhpParser\Node\Stmt; namespace PhpParser\Node\Stmt;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Error;
class Property extends Node\Stmt class Property extends Node\Stmt
{ {

View File

@ -3,7 +3,6 @@
namespace PhpParser\Node\Stmt; namespace PhpParser\Node\Stmt;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Error;
class TryCatch extends Node\Stmt class TryCatch extends Node\Stmt
{ {

View File

@ -3,7 +3,6 @@
namespace PhpParser\Node\Stmt; namespace PhpParser\Node\Stmt;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Error;
class UseUse extends Node\Stmt class UseUse extends Node\Stmt
{ {

View File

@ -11,27 +11,46 @@ use PhpParser\Node\Stmt\UseUse;
class NodeDumper class NodeDumper
{ {
private $dumpComments; private $dumpComments;
private $dumpPositions;
private $code;
/** /**
* Constructs a NodeDumper. * Constructs a NodeDumper.
* *
* @param array $options Boolean option 'dumpComments' controls whether comments should be * Supported options:
* dumped * * bool dumpComments: Whether comments should be dumped.
* * bool dumpPositions: Whether line/offset information should be dumped. To dump offset
* information, the code needs to be passed to dump().
*
* @param array $options Options (see description)
*/ */
public function __construct(array $options = []) { public function __construct(array $options = []) {
$this->dumpComments = !empty($options['dumpComments']); $this->dumpComments = !empty($options['dumpComments']);
$this->dumpPositions = !empty($options['dumpPositions']);
} }
/** /**
* Dumps a node or array. * Dumps a node or array.
* *
* @param array|Node $node Node or array to dump * @param array|Node $node Node or array to dump
* @param string|null $code Code corresponding to dumped AST. This only needs to be passed if
* the dumpPositions option is enabled and the dumping of node offsets
* is desired.
* *
* @return string Dumped value * @return string Dumped value
*/ */
public function dump($node) { public function dump($node, $code = null) {
$this->code = $code;
return $this->dumpRecursive($node);
}
protected function dumpRecursive($node) {
if ($node instanceof Node) { if ($node instanceof Node) {
$r = $node->getType() . '('; $r = $node->getType();
if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) {
$r .= $p;
}
$r .= '(';
foreach ($node->getSubNodeNames() as $key) { foreach ($node->getSubNodeNames() as $key) {
$r .= "\n " . $key . ': '; $r .= "\n " . $key . ': ';
@ -55,12 +74,12 @@ class NodeDumper
$r .= $value; $r .= $value;
} }
} else { } else {
$r .= str_replace("\n", "\n ", $this->dump($value)); $r .= str_replace("\n", "\n ", $this->dumpRecursive($value));
} }
} }
if ($this->dumpComments && $comments = $node->getAttribute('comments')) { if ($this->dumpComments && $comments = $node->getAttribute('comments')) {
$r .= "\n comments: " . str_replace("\n", "\n ", $this->dump($comments)); $r .= "\n comments: " . str_replace("\n", "\n ", $this->dumpRecursive($comments));
} }
} elseif (is_array($node)) { } elseif (is_array($node)) {
$r = 'array('; $r = 'array(';
@ -77,7 +96,7 @@ class NodeDumper
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
$r .= $value; $r .= $value;
} else { } else {
$r .= str_replace("\n", "\n ", $this->dump($value)); $r .= str_replace("\n", "\n ", $this->dumpRecursive($value));
} }
} }
} elseif ($node instanceof Comment) { } elseif ($node instanceof Comment) {
@ -144,4 +163,34 @@ class NodeDumper
} }
return $map[$type] . ' (' . $type . ')'; return $map[$type] . ' (' . $type . ')';
} }
protected function dumpPosition(Node $node) {
if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) {
return null;
}
$start = $node->getAttribute('startLine');
$end = $node->getAttribute('endLine');
if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos')
&& null !== $this->code
) {
$start .= ':' . $this->toColumn($this->code, $node->getAttribute('startFilePos'));
$end .= ':' . $this->toColumn($this->code, $node->getAttribute('endFilePos'));
}
return "[$start - $end]";
}
// Copied from Error class
private function toColumn($code, $pos) {
if ($pos > strlen($code)) {
throw new \RuntimeException('Invalid position information');
}
$lineStartPos = strrpos($code, "\n", $pos - strlen($code));
if (false === $lineStartPos) {
$lineStartPos = -1;
}
return $pos - $lineStartPos;
}
} }

View File

@ -2,14 +2,14 @@
namespace PhpParser\NodeVisitor; namespace PhpParser\NodeVisitor;
use PhpParser\ErrorHandler;
use PhpParser\NodeVisitorAbstract;
use PhpParser\Error; use PhpParser\Error;
use PhpParser\ErrorHandler;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Name; use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Expr;
use PhpParser\Node\Stmt; use PhpParser\Node\Stmt;
use PhpParser\NodeVisitorAbstract;
class NameResolver extends NodeVisitorAbstract class NameResolver extends NodeVisitorAbstract
{ {

View File

@ -3035,7 +3035,7 @@ class Php5 extends \PhpParser\ParserAbstract
} }
protected function reduceRule523() { protected function reduceRule523() {
$this->semValue = $this->semStack[$this->stackPos-(1-1)]; $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes);
} }
protected function reduceRule524() { protected function reduceRule524() {

File diff suppressed because it is too large Load Diff

View File

@ -312,7 +312,9 @@ abstract class ParserAbstract implements Parser
} }
//$this->traceShift($this->errorSymbol); //$this->traceShift($this->errorSymbol);
$stateStack[++$this->stackPos] = $state = $action; ++$this->stackPos;
$stateStack[$this->stackPos] = $state = $action;
$this->endAttributes = $this->endAttributeStack[$this->stackPos];
break; break;
case 3: case 3:
@ -365,6 +367,7 @@ abstract class ParserAbstract implements Parser
) { ) {
if ($this->action[$idx] != $this->unexpectedTokenRule if ($this->action[$idx] != $this->unexpectedTokenRule
&& $this->action[$idx] != $this->defaultAction && $this->action[$idx] != $this->defaultAction
&& $symbol != $this->errorSymbol
) { ) {
if (count($expected) == 4) { if (count($expected) == 4) {
/* Too many expected tokens */ /* Too many expected tokens */

View File

@ -2,16 +2,16 @@
namespace PhpParser\PrettyPrinter; namespace PhpParser\PrettyPrinter;
use PhpParser\PrettyPrinterAbstract;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Node\Scalar;
use PhpParser\Node\Scalar\MagicConst;
use PhpParser\Node\Expr; use PhpParser\Node\Expr;
use PhpParser\Node\Expr\AssignOp; use PhpParser\Node\Expr\AssignOp;
use PhpParser\Node\Expr\BinaryOp; use PhpParser\Node\Expr\BinaryOp;
use PhpParser\Node\Expr\Cast; use PhpParser\Node\Expr\Cast;
use PhpParser\Node\Stmt;
use PhpParser\Node\Name; use PhpParser\Node\Name;
use PhpParser\Node\Scalar;
use PhpParser\Node\Scalar\MagicConst;
use PhpParser\Node\Stmt;
use PhpParser\PrettyPrinterAbstract;
class Standard extends PrettyPrinterAbstract class Standard extends PrettyPrinterAbstract
{ {

View File

@ -2,10 +2,10 @@
namespace PhpParser\Serializer; namespace PhpParser\Serializer;
use XMLWriter;
use PhpParser\Node;
use PhpParser\Comment; use PhpParser\Comment;
use PhpParser\Node;
use PhpParser\Serializer; use PhpParser\Serializer;
use XMLWriter;
class XML implements Serializer class XML implements Serializer
{ {

View File

@ -2,9 +2,9 @@
namespace PhpParser\Unserializer; namespace PhpParser\Unserializer;
use XMLReader;
use DomainException; use DomainException;
use PhpParser\Unserializer; use PhpParser\Unserializer;
use XMLReader;
class XML implements Unserializer class XML implements Unserializer
{ {

View File

@ -2,9 +2,6 @@
namespace PhpParser; namespace PhpParser;
use PhpParser\Node\Expr;
use PhpParser\Node\Scalar;
/* The autoloader is already active at this point, so we only check effects here. */ /* The autoloader is already active at this point, so we only check effects here. */
class AutoloaderTest extends \PHPUnit_Framework_TestCase { class AutoloaderTest extends \PHPUnit_Framework_TestCase {

View File

@ -4,9 +4,9 @@ namespace PhpParser\Builder;
use PhpParser\Comment; use PhpParser\Comment;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Node\Stmt;
use PhpParser\Node\Expr\Print_; use PhpParser\Node\Expr\Print_;
use PhpParser\Node\Scalar\String_; use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt;
class FunctionTest extends \PHPUnit_Framework_TestCase class FunctionTest extends \PHPUnit_Framework_TestCase
{ {

View File

@ -2,10 +2,10 @@
namespace PhpParser\Builder; namespace PhpParser\Builder;
use PhpParser\Node;
use PhpParser\Node\Stmt;
use PhpParser\Node\Scalar\DNumber;
use PhpParser\Comment; use PhpParser\Comment;
use PhpParser\Node;
use PhpParser\Node\Scalar\DNumber;
use PhpParser\Node\Stmt;
class InterfaceTest extends \PHPUnit_Framework_TestCase class InterfaceTest extends \PHPUnit_Framework_TestCase
{ {

View File

@ -2,11 +2,11 @@
namespace PhpParser\Builder; namespace PhpParser\Builder;
use PhpParser\Comment;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Node\Expr\Print_; use PhpParser\Node\Expr\Print_;
use PhpParser\Node\Scalar\String_; use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt; use PhpParser\Node\Stmt;
use PhpParser\Comment;
class MethodTest extends \PHPUnit_Framework_TestCase class MethodTest extends \PHPUnit_Framework_TestCase
{ {

View File

@ -2,11 +2,11 @@
namespace PhpParser\Builder; namespace PhpParser\Builder;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt;
use PhpParser\Node\Expr;
use PhpParser\Node\Scalar;
use PhpParser\Comment; use PhpParser\Comment;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt;
class PropertyTest extends \PHPUnit_Framework_TestCase class PropertyTest extends \PHPUnit_Framework_TestCase
{ {

View File

@ -3,8 +3,6 @@
namespace PhpParser\Builder; namespace PhpParser\Builder;
use PhpParser\Comment; use PhpParser\Comment;
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt; use PhpParser\Node\Stmt;
class TraitTest extends \PHPUnit_Framework_TestCase class TraitTest extends \PHPUnit_Framework_TestCase

View File

@ -2,8 +2,6 @@
namespace PhpParser; namespace PhpParser;
use PhpParser\Comment;
require_once __DIR__ . '/CodeTestAbstract.php'; require_once __DIR__ . '/CodeTestAbstract.php';
class CodeParsingTest extends CodeTestAbstract class CodeParsingTest extends CodeTestAbstract
@ -11,20 +9,28 @@ class CodeParsingTest extends CodeTestAbstract
/** /**
* @dataProvider provideTestParse * @dataProvider provideTestParse
*/ */
public function testParse($name, $code, $expected, $mode) { public function testParse($name, $code, $expected, $modeLine) {
if (null !== $modeLine) {
$modes = array_fill_keys(explode(',', $modeLine), true);
} else {
$modes = [];
}
$lexer = new Lexer\Emulative(array('usedAttributes' => array( $lexer = new Lexer\Emulative(array('usedAttributes' => array(
'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments' 'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments'
))); )));
$parser5 = new Parser\Php5($lexer); $parser5 = new Parser\Php5($lexer);
$parser7 = new Parser\Php7($lexer); $parser7 = new Parser\Php7($lexer);
$output5 = $this->getParseOutput($parser5, $code); $dumpPositions = isset($modes['positions']);
$output7 = $this->getParseOutput($parser7, $code); $output5 = $this->getParseOutput($parser5, $code, $dumpPositions);
$output7 = $this->getParseOutput($parser7, $code, $dumpPositions);
if ($mode === 'php5') { if (isset($modes['php5'])) {
$this->assertSame($expected, $output5, $name); $this->assertSame($expected, $output5, $name);
$this->assertNotSame($expected, $output7, $name); $this->assertNotSame($expected, $output7, $name);
} else if ($mode === 'php7') { } else if (isset($modes['php7'])) {
$this->assertNotSame($expected, $output5, $name); $this->assertNotSame($expected, $output5, $name);
$this->assertSame($expected, $output7, $name); $this->assertSame($expected, $output7, $name);
} else { } else {
@ -33,7 +39,7 @@ class CodeParsingTest extends CodeTestAbstract
} }
} }
private function getParseOutput(Parser $parser, $code) { private function getParseOutput(Parser $parser, $code, $dumpPositions) {
$errors = new ErrorHandler\Collecting; $errors = new ErrorHandler\Collecting;
$stmts = $parser->parse($code, $errors); $stmts = $parser->parse($code, $errors);
@ -43,8 +49,8 @@ class CodeParsingTest extends CodeTestAbstract
} }
if (null !== $stmts) { if (null !== $stmts) {
$dumper = new NodeDumper(['dumpComments' => true]); $dumper = new NodeDumper(['dumpComments' => true, 'dumpPositions' => $dumpPositions]);
$output .= $dumper->dump($stmts); $output .= $dumper->dump($stmts, $code);
} }
return canonicalize($output); return canonicalize($output);

View File

@ -10,7 +10,6 @@ class NodeDumperTest extends \PHPUnit_Framework_TestCase
/** /**
* @dataProvider provideTestDump * @dataProvider provideTestDump
* @covers PhpParser\NodeDumper::dump
*/ */
public function testDump($node, $dump) { public function testDump($node, $dump) {
$dumper = new NodeDumper; $dumper = new NodeDumper;
@ -61,6 +60,40 @@ class NodeDumperTest extends \PHPUnit_Framework_TestCase
); );
} }
public function testDumpWithPositions() {
$parser = (new ParserFactory)->create(
ParserFactory::ONLY_PHP7,
new Lexer(['usedAttributes' => ['startLine', 'endLine', 'startFilePos', 'endFilePos']])
);
$dumper = new NodeDumper(['dumpPositions' => true]);
$code = "<?php\n\$a = 1;\necho \$a;";
$expected = <<<'OUT'
array(
0: Expr_Assign[2:1 - 2:6](
var: Expr_Variable[2:1 - 2:2](
name: a
)
expr: Scalar_LNumber[2:6 - 2:6](
value: 1
)
)
1: Stmt_Echo[3:1 - 3:8](
exprs: array(
0: Expr_Variable[3:6 - 3:7](
name: a
)
)
)
)
OUT;
$stmts = $parser->parse($code);
$dump = $dumper->dump($stmts, $code);
$this->assertSame($this->canonicalize($expected), $this->canonicalize($dump));
}
/** /**
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
* @expectedExceptionMessage Can only dump nodes and arrays. * @expectedExceptionMessage Can only dump nodes and arrays.

View File

@ -2,8 +2,8 @@
namespace PhpParser; namespace PhpParser;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Expr; use PhpParser\Node\Expr;
use PhpParser\Node\Scalar\String_;
class NodeTraverserTest extends \PHPUnit_Framework_TestCase class NodeTraverserTest extends \PHPUnit_Framework_TestCase
{ {

View File

@ -4,9 +4,9 @@ namespace PhpParser\NodeVisitor;
use PhpParser; use PhpParser;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Name; use PhpParser\Node\Name;
use PhpParser\Node\Stmt; use PhpParser\Node\Stmt;
use PhpParser\Node\Expr;
class NameResolverTest extends \PHPUnit_Framework_TestCase class NameResolverTest extends \PHPUnit_Framework_TestCase
{ {

View File

@ -4,10 +4,10 @@ namespace PhpParser\Parser;
use PhpParser\Error; use PhpParser\Error;
use PhpParser\Lexer; use PhpParser\Lexer;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\ParserTest;
use PhpParser\Node\Expr; use PhpParser\Node\Expr;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Stmt; use PhpParser\Node\Stmt;
use PhpParser\ParserTest;
require_once __DIR__ . '/../ParserTest.php'; require_once __DIR__ . '/../ParserTest.php';

View File

@ -171,17 +171,6 @@ EOC;
array("?>\nFoo", ['hasLeadingNewline' => true]), array("?>\nFoo", ['hasLeadingNewline' => true]),
); );
} }
public function testGroupUsePrefixFileOffsets() {
$parser = $this->getParser(new Lexer(
['usedAttributes' => ['startFilePos', 'endFilePos']]
));
$stmts = $parser->parse('<?php use Foo\Bar\{Baz};');
/** @var Node\Stmt\GroupUse $groupUse */
$groupUse = $stmts[0];
$this->assertSame(10, $groupUse->prefix->getAttribute('startFilePos'));
$this->assertSame(16, $groupUse->prefix->getAttribute('endFilePos'));
}
} }
class InvalidTokenLexer extends Lexer { class InvalidTokenLexer extends Lexer {

View File

@ -2,8 +2,8 @@
namespace PhpParser\Unserializer; namespace PhpParser\Unserializer;
use PhpParser\Node\Scalar;
use PhpParser\Comment; use PhpParser\Comment;
use PhpParser\Node\Scalar;
class XMLTest extends \PHPUnit_Framework_TestCase class XMLTest extends \PHPUnit_Framework_TestCase
{ {

View File

@ -245,13 +245,14 @@ Syntax error, unexpected EOF from 8:12 to 8:12
$foo-> $foo->
; ;
----- -----
Syntax error, unexpected ';' from 3:1 to 3:1 !!positions
Syntax error, unexpected ';', expecting T_STRING or T_VARIABLE or '{' or '$' from 3:1 to 3:1
array( array(
0: Expr_PropertyFetch( 0: Expr_PropertyFetch[2:1 - 3:1](
var: Expr_Variable( var: Expr_Variable[2:1 - 2:4](
name: foo name: foo
) )
name: Expr_Error( name: Expr_Error[3:1 - 3:1](
) )
) )
) )
@ -261,22 +262,114 @@ function foo() {
$bar-> $bar->
} }
----- -----
Syntax error, unexpected '}' from 4:1 to 4:1 !!positions
Syntax error, unexpected '}', expecting T_STRING or T_VARIABLE or '{' or '$' from 4:1 to 4:1
array( array(
0: Stmt_Function( 0: Stmt_Function[2:1 - 4:1](
byRef: false byRef: false
name: foo name: foo
params: array( params: array(
) )
returnType: null returnType: null
stmts: array( stmts: array(
0: Expr_PropertyFetch( 0: Expr_PropertyFetch[3:5 - 4:1](
var: Expr_Variable( var: Expr_Variable[3:5 - 3:8](
name: bar name: bar
) )
name: Expr_Error( name: Expr_Error[4:1 - 4:1](
) )
) )
) )
) )
)
-----
<?php
new T
-----
Syntax error, unexpected EOF from 2:6 to 2:6
array(
0: Expr_New(
class: Name(
parts: array(
0: T
)
)
args: array(
)
)
)
-----
<?php
new
-----
!!php7,positions
Syntax error, unexpected EOF from 2:4 to 2:4
array(
0: Expr_New[2:1 - 2:4](
class: Expr_Error[2:4 - 2:4](
)
args: array(
)
)
)
-----
<?php
$foo instanceof
-----
!!php7
Syntax error, unexpected EOF from 2:16 to 2:16
array(
0: Expr_Instanceof(
expr: Expr_Variable(
name: foo
)
class: Expr_Error(
)
)
)
-----
<?php
$
-----
!!php7
Syntax error, unexpected EOF, expecting T_VARIABLE or '{' or '$' from 2:2 to 2:2
array(
0: Expr_Variable(
name: Expr_Error(
)
)
)
-----
<?php
Foo::$
-----
!!php7
Syntax error, unexpected EOF, expecting T_VARIABLE or '{' or '$' from 2:7 to 2:7
array(
0: Expr_StaticPropertyFetch(
class: Name(
parts: array(
0: Foo
)
)
name: Expr_Error(
)
)
)
-----
<?php
Foo::
-----
!!php7
Syntax error, unexpected EOF from 2:6 to 2:6
array(
0: Expr_ClassConstFetch(
class: Name(
parts: array(
0: Foo
)
)
name: Expr_Error(
)
)
) )

View File

@ -246,17 +246,21 @@ array(
) )
byRef: false byRef: false
) )
1: Expr_List( 1: Expr_ArrayItem(
items: array( key: null
0: null value: Expr_List(
1: Expr_ArrayItem( items: array(
key: null 0: null
value: Expr_Variable( 1: Expr_ArrayItem(
name: c key: null
value: Expr_Variable(
name: c
)
byRef: false
) )
byRef: false
) )
) )
byRef: false
) )
2: Expr_ArrayItem( 2: Expr_ArrayItem(
key: null key: null

View File

@ -3,6 +3,21 @@ New without a class
<?php <?php
new; new;
----- -----
!!php5
Syntax error, unexpected ';' from 2:4 to 2:4 Syntax error, unexpected ';' from 2:4 to 2:4
array( array(
) )
-----
<?php
new;
-----
!!php7
Syntax error, unexpected ';' from 2:4 to 2:4
array(
0: Expr_New(
class: Expr_Error(
)
args: array(
)
)
)

View File

@ -0,0 +1,28 @@
Ensure correct file position attributes for group use prefix
-----
<?php
use Foo\Bar\{Baz};
-----
!!positions
array(
0: Stmt_GroupUse[2:1 - 2:17](
type: TYPE_UNKNOWN (0)
prefix: Name[2:5 - 2:11](
parts: array(
0: Foo
1: Bar
)
)
uses: array(
0: Stmt_UseUse[2:14 - 2:16](
type: TYPE_NORMAL (1)
name: Name[2:14 - 2:16](
parts: array(
0: Baz
)
)
alias: Baz
)
)
)
)