mirror of
https://github.com/nikic/PHP-Parser.git
synced 2025-07-16 20:06:32 +02:00
Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a1e8e1a30e | ||
|
d77e6cd6e9 | ||
|
a10780ca0d | ||
|
4d4896e553 | ||
|
6fa073879e | ||
|
5a3a1ec25c | ||
|
4a7d011317 | ||
|
7f862ac21c | ||
|
0808939f81 | ||
|
7bfc320bda | ||
|
bc0bff3f87 | ||
|
c28b8556f5 | ||
|
3da86df48f | ||
|
901b895c02 | ||
|
c877c1a64f | ||
|
c3cbf07946 | ||
|
2b9e2f71b7 | ||
|
d5873b177b | ||
|
48ec654d0c | ||
|
c12a4c8239 | ||
|
86ea6fe8c4 | ||
|
1b59e918f7 |
@@ -1,5 +1,5 @@
|
||||
language: php
|
||||
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
|
58
CHANGELOG.md
58
CHANGELOG.md
@@ -1,8 +1,64 @@
|
||||
Version 3.0.5-dev
|
||||
Version 3.1.2-dev
|
||||
-----------------
|
||||
|
||||
Nothing yet.
|
||||
|
||||
Version 3.1.1 (2017-09-02)
|
||||
--------------------------
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed syntax error on comment after brace-style namespace declaration. (#412)
|
||||
* Added support for TraitUse statements in trait builder. (#413)
|
||||
|
||||
Version 3.1.0 (2017-07-28)
|
||||
--------------------------
|
||||
|
||||
### Added
|
||||
|
||||
* [PHP 7.2] Added support for trailing comma in group use statements.
|
||||
* [PHP 7.2] Added support for `object` type. This means `object` types will now be represented as a
|
||||
builtin type (a simple `"object"` string), rather than a class `Name`.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Floating-point numbers are now printed correctly if the LC_NUMERIC locale uses a comma as decimal
|
||||
separator.
|
||||
|
||||
### Changed
|
||||
|
||||
* `Name::$parts` is no longer deprecated.
|
||||
|
||||
Version 3.0.6 (2017-06-28)
|
||||
--------------------------
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed the spelling of `Class_::VISIBILITY_MODIFIER_MASK`. The previous spelling of
|
||||
`Class_::VISIBILITY_MODIFER_MASK` is preserved for backwards compatibility.
|
||||
* The pretty printing will now preserve comments inside array literals and function calls by
|
||||
printing the array items / function arguments on separate lines. Array literals and functions that
|
||||
do not contain comments are not affected.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `Builder\Param::makeVariadic()`.
|
||||
|
||||
### Deprecated
|
||||
|
||||
* The `Node::setLine()` method has been deprecated.
|
||||
|
||||
Version 3.0.5 (2017-03-05)
|
||||
--------------------------
|
||||
|
||||
### Fixed
|
||||
|
||||
* Name resolution of `NullableType`s is now performed earlier, so that a fully resolved signature is
|
||||
available when a function is entered. (#360)
|
||||
* `Error` nodes are now considered empty, while previously they extended until the token where the
|
||||
error occurred. This made some nodes larger than expected. (#359)
|
||||
* Fixed notices being thrown during error recovery in some situations. (#362)
|
||||
|
||||
Version 3.0.4 (2017-02-10)
|
||||
--------------------------
|
||||
|
||||
|
@@ -59,6 +59,10 @@ no_comma:
|
||||
| ',' { $this->emitError(new Error('A trailing comma is not allowed here', attributes())); }
|
||||
;
|
||||
|
||||
optional_comma:
|
||||
/* empty */
|
||||
| ','
|
||||
|
||||
top_statement:
|
||||
statement { $$ = $1; }
|
||||
| function_declaration_statement { $$ = $1; }
|
||||
@@ -95,7 +99,7 @@ group_use_declaration:
|
||||
;
|
||||
|
||||
unprefixed_use_declarations:
|
||||
non_empty_unprefixed_use_declarations no_comma { $$ = $1; }
|
||||
non_empty_unprefixed_use_declarations optional_comma { $$ = $1; }
|
||||
;
|
||||
|
||||
non_empty_unprefixed_use_declarations:
|
||||
@@ -114,7 +118,7 @@ non_empty_use_declarations:
|
||||
;
|
||||
|
||||
inline_use_declarations:
|
||||
non_empty_inline_use_declarations no_comma { $$ = $1; }
|
||||
non_empty_inline_use_declarations optional_comma { $$ = $1; }
|
||||
;
|
||||
|
||||
non_empty_inline_use_declarations:
|
||||
@@ -763,7 +767,7 @@ constant:
|
||||
/* 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; }
|
||||
{ $$ = Expr\ClassConstFetch[$1, new Expr\Error(stackAttributes(#3))]; $this->errorState = 2; }
|
||||
;
|
||||
|
||||
array_short_syntax:
|
||||
|
@@ -16,6 +16,8 @@ class Param extends PhpParser\BuilderAbstract
|
||||
|
||||
protected $byRef = false;
|
||||
|
||||
protected $variadic = false;
|
||||
|
||||
/**
|
||||
* Creates a parameter builder.
|
||||
*
|
||||
@@ -65,6 +67,17 @@ class Param extends PhpParser\BuilderAbstract
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the parameter variadic
|
||||
*
|
||||
* @return $this The builder instance (for fluid interface)
|
||||
*/
|
||||
public function makeVariadic() {
|
||||
$this->variadic = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the built parameter node.
|
||||
*
|
||||
@@ -72,7 +85,7 @@ class Param extends PhpParser\BuilderAbstract
|
||||
*/
|
||||
public function getNode() {
|
||||
return new Node\Param(
|
||||
$this->name, $this->default, $this->type, $this->byRef
|
||||
$this->name, $this->default, $this->type, $this->byRef, $this->variadic
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ use PhpParser\Node\Stmt;
|
||||
class Trait_ extends Declaration
|
||||
{
|
||||
protected $name;
|
||||
protected $uses = array();
|
||||
protected $properties = array();
|
||||
protected $methods = array();
|
||||
|
||||
@@ -34,6 +35,8 @@ class Trait_ extends Declaration
|
||||
$this->properties[] = $stmt;
|
||||
} else if ($stmt instanceof Stmt\ClassMethod) {
|
||||
$this->methods[] = $stmt;
|
||||
} else if ($stmt instanceof Stmt\TraitUse) {
|
||||
$this->uses[] = $stmt;
|
||||
} else {
|
||||
throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType()));
|
||||
}
|
||||
@@ -49,7 +52,7 @@ class Trait_ extends Declaration
|
||||
public function getNode() {
|
||||
return new Stmt\Trait_(
|
||||
$this->name, array(
|
||||
'stmts' => array_merge($this->properties, $this->methods)
|
||||
'stmts' => array_merge($this->uses, $this->properties, $this->methods)
|
||||
), $this->attributes
|
||||
);
|
||||
}
|
||||
|
@@ -80,7 +80,7 @@ abstract class BuilderAbstract implements Builder {
|
||||
}
|
||||
|
||||
$builtinTypes = array(
|
||||
'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void'
|
||||
'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object'
|
||||
);
|
||||
|
||||
$lowerType = strtolower($type);
|
||||
|
@@ -185,15 +185,17 @@ class Lexer
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for unterminated comment
|
||||
$lastToken = $this->tokens[count($this->tokens) - 1];
|
||||
if ($this->isUnterminatedComment($lastToken)) {
|
||||
$errorHandler->handleError(new Error('Unterminated comment', [
|
||||
'startLine' => $line - substr_count($lastToken[1], "\n"),
|
||||
'endLine' => $line,
|
||||
'startFilePos' => $filePos - \strlen($lastToken[1]),
|
||||
'endFilePos' => $filePos,
|
||||
]));
|
||||
if (count($this->tokens) > 0) {
|
||||
// Check for unterminated comment
|
||||
$lastToken = $this->tokens[count($this->tokens) - 1];
|
||||
if ($this->isUnterminatedComment($lastToken)) {
|
||||
$errorHandler->handleError(new Error('Unterminated comment', [
|
||||
'startLine' => $line - substr_count($lastToken[1], "\n"),
|
||||
'endLine' => $line,
|
||||
'startFilePos' => $filePos - \strlen($lastToken[1]),
|
||||
'endFilePos' => $filePos,
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -29,6 +29,8 @@ interface Node
|
||||
* Sets line the node started in.
|
||||
*
|
||||
* @param int $line Line
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function setLine($line);
|
||||
|
||||
|
@@ -8,7 +8,6 @@ class Name extends NodeAbstract
|
||||
{
|
||||
/**
|
||||
* @var string[] Parts of the name
|
||||
* @deprecated Avoid directly accessing $parts, use methods instead.
|
||||
*/
|
||||
public $parts;
|
||||
|
||||
|
@@ -30,7 +30,7 @@ class ClassConst extends Node\Stmt
|
||||
|
||||
public function isPublic() {
|
||||
return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
|
||||
|| ($this->flags & Class_::VISIBILITY_MODIFER_MASK) === 0;
|
||||
|| ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
|
||||
}
|
||||
|
||||
public function isProtected() {
|
||||
|
@@ -69,7 +69,7 @@ class ClassMethod extends Node\Stmt implements FunctionLike
|
||||
|
||||
public function isPublic() {
|
||||
return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
|
||||
|| ($this->flags & Class_::VISIBILITY_MODIFER_MASK) === 0;
|
||||
|| ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
|
||||
}
|
||||
|
||||
public function isProtected() {
|
||||
|
@@ -14,7 +14,9 @@ class Class_ extends ClassLike
|
||||
const MODIFIER_ABSTRACT = 16;
|
||||
const MODIFIER_FINAL = 32;
|
||||
|
||||
const VISIBILITY_MODIFER_MASK = 7; // 1 | 2 | 4
|
||||
const VISIBILITY_MODIFIER_MASK = 7; // 1 | 2 | 4
|
||||
/** @deprecated */
|
||||
const VISIBILITY_MODIFER_MASK = self::VISIBILITY_MODIFIER_MASK;
|
||||
|
||||
/** @var int Type */
|
||||
public $flags;
|
||||
@@ -74,7 +76,7 @@ class Class_ extends ClassLike
|
||||
* @internal
|
||||
*/
|
||||
public static function verifyModifier($a, $b) {
|
||||
if ($a & self::VISIBILITY_MODIFER_MASK && $b & self::VISIBILITY_MODIFER_MASK) {
|
||||
if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) {
|
||||
throw new Error('Multiple access type modifiers are not allowed');
|
||||
}
|
||||
|
||||
|
@@ -34,7 +34,7 @@ class Property extends Node\Stmt
|
||||
|
||||
public function isPublic() {
|
||||
return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0
|
||||
|| ($this->flags & Class_::VISIBILITY_MODIFER_MASK) === 0;
|
||||
|| ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
|
||||
}
|
||||
|
||||
public function isProtected() {
|
||||
|
@@ -37,6 +37,8 @@ abstract class NodeAbstract implements Node, \JsonSerializable
|
||||
* Sets line the node started in.
|
||||
*
|
||||
* @param int $line Line
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function setLine($line) {
|
||||
$this->setAttribute('startLine', (int) $line);
|
||||
|
@@ -120,10 +120,6 @@ class NameResolver extends NodeVisitorAbstract
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ($node instanceof Node\NullableType) {
|
||||
if ($node->type instanceof Name) {
|
||||
$node->type = $this->resolveClassName($node->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,13 +168,20 @@ class NameResolver extends NodeVisitorAbstract
|
||||
/** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */
|
||||
private function resolveSignature($node) {
|
||||
foreach ($node->params as $param) {
|
||||
if ($param->type instanceof Name) {
|
||||
$param->type = $this->resolveClassName($param->type);
|
||||
}
|
||||
$param->type = $this->resolveType($param->type);
|
||||
}
|
||||
if ($node->returnType instanceof Name) {
|
||||
$node->returnType = $this->resolveClassName($node->returnType);
|
||||
$node->returnType = $this->resolveType($node->returnType);
|
||||
}
|
||||
|
||||
private function resolveType($node) {
|
||||
if ($node instanceof Node\NullableType) {
|
||||
$node->type = $this->resolveType($node->type);
|
||||
return $node;
|
||||
}
|
||||
if ($node instanceof Name) {
|
||||
return $this->resolveClassName($node);
|
||||
}
|
||||
return $node;
|
||||
}
|
||||
|
||||
protected function resolveClassName(Name $name) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -315,7 +315,11 @@ abstract class ParserAbstract implements Parser
|
||||
//$this->traceShift($this->errorSymbol);
|
||||
++$this->stackPos;
|
||||
$stateStack[$this->stackPos] = $state = $action;
|
||||
$this->endAttributes = $this->endAttributeStack[$this->stackPos];
|
||||
|
||||
// We treat the error symbol as being empty, so we reset the end attributes
|
||||
// to the end attributes of the last non-error symbol
|
||||
$this->endAttributeStack[$this->stackPos] = $this->endAttributeStack[$this->stackPos - 1];
|
||||
$this->endAttributes = $this->endAttributeStack[$this->stackPos - 1];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
@@ -441,6 +445,7 @@ abstract class ParserAbstract implements Parser
|
||||
if ($stmt instanceof Node\Stmt\Namespace_) {
|
||||
$afterFirstNamespace = true;
|
||||
} elseif (!$stmt instanceof Node\Stmt\HaltCompiler
|
||||
&& !$stmt instanceof Node\Stmt\Nop
|
||||
&& $afterFirstNamespace && !$hasErrored) {
|
||||
$this->emitError(new Error(
|
||||
'No code may exist outside of namespace {}', $stmt->getAttributes()));
|
||||
@@ -525,6 +530,7 @@ abstract class ParserAbstract implements Parser
|
||||
'string' => true,
|
||||
'iterable' => true,
|
||||
'void' => true,
|
||||
'object' => true,
|
||||
];
|
||||
|
||||
if (!$name->isUnqualified()) {
|
||||
|
@@ -182,6 +182,11 @@ class Standard extends PrettyPrinterAbstract
|
||||
$stringValue = sprintf('%.17G', $node->value);
|
||||
}
|
||||
|
||||
// %G is locale dependent and there exists no locale-independent alternative. We don't want
|
||||
// mess with switching locales here, so let's assume that a comma is the only non-standard
|
||||
// decimal separator we may encounter...
|
||||
$stringValue = str_replace(',', '.', $stringValue);
|
||||
|
||||
// ensure that number is really printed as float
|
||||
return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue;
|
||||
}
|
||||
@@ -438,12 +443,12 @@ class Standard extends PrettyPrinterAbstract
|
||||
|
||||
protected function pExpr_FuncCall(Expr\FuncCall $node) {
|
||||
return $this->pCallLhs($node->name)
|
||||
. '(' . $this->pCommaSeparated($node->args) . ')';
|
||||
. '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
}
|
||||
|
||||
protected function pExpr_MethodCall(Expr\MethodCall $node) {
|
||||
return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name)
|
||||
. '(' . $this->pCommaSeparated($node->args) . ')';
|
||||
. '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
}
|
||||
|
||||
protected function pExpr_StaticCall(Expr\StaticCall $node) {
|
||||
@@ -453,7 +458,7 @@ class Standard extends PrettyPrinterAbstract
|
||||
? $this->p($node->name)
|
||||
: '{' . $this->p($node->name) . '}')
|
||||
: $node->name)
|
||||
. '(' . $this->pCommaSeparated($node->args) . ')';
|
||||
. '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
}
|
||||
|
||||
protected function pExpr_Empty(Expr\Empty_ $node) {
|
||||
@@ -501,9 +506,9 @@ class Standard extends PrettyPrinterAbstract
|
||||
$syntax = $node->getAttribute('kind',
|
||||
$this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG);
|
||||
if ($syntax === Expr\Array_::KIND_SHORT) {
|
||||
return '[' . $this->pCommaSeparated($node->items) . ']';
|
||||
return '[' . $this->pMaybeMultiline($node->items, true) . ']';
|
||||
} else {
|
||||
return 'array(' . $this->pCommaSeparated($node->items) . ')';
|
||||
return 'array(' . $this->pMaybeMultiline($node->items, true) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,10 +558,10 @@ class Standard extends PrettyPrinterAbstract
|
||||
|
||||
protected function pExpr_New(Expr\New_ $node) {
|
||||
if ($node->class instanceof Stmt\Class_) {
|
||||
$args = $node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : '';
|
||||
$args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : '';
|
||||
return 'new ' . $this->pClassCommon($node->class, $args);
|
||||
}
|
||||
return 'new ' . $this->p($node->class) . '(' . $this->pCommaSeparated($node->args) . ')';
|
||||
return 'new ' . $this->p($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
}
|
||||
|
||||
protected function pExpr_Clone(Expr\Clone_ $node) {
|
||||
@@ -944,4 +949,21 @@ class Standard extends PrettyPrinterAbstract
|
||||
return '(' . $this->p($node) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
private function hasNodeWithComments(array $nodes) {
|
||||
foreach ($nodes as $node) {
|
||||
if ($node && $node->getAttribute('comments')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function pMaybeMultiline(array $nodes, $trailingComma = false) {
|
||||
if (!$this->hasNodeWithComments($nodes)) {
|
||||
return $this->pCommaSeparated($nodes);
|
||||
} else {
|
||||
return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -286,6 +286,38 @@ abstract class PrettyPrinterAbstract
|
||||
return $this->pImplode($nodes, ', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretty prints a comma-separated list of nodes in multiline style, including comments.
|
||||
*
|
||||
* The result includes a leading newline and one level of indentation (same as pStmts).
|
||||
*
|
||||
* @param Node[] $nodes Array of Nodes to be printed
|
||||
* @param bool $trailingComma Whether to use a trailing comma
|
||||
*
|
||||
* @return string Comma separated pretty printed nodes in multiline style
|
||||
*/
|
||||
protected function pCommaSeparatedMultiline(array $nodes, $trailingComma) {
|
||||
$result = '';
|
||||
$lastIdx = count($nodes) - 1;
|
||||
foreach ($nodes as $idx => $node) {
|
||||
if ($node !== null) {
|
||||
$comments = $node->getAttribute('comments', array());
|
||||
if ($comments) {
|
||||
$result .= "\n" . $this->pComments($comments);
|
||||
}
|
||||
|
||||
$result .= "\n" . $this->p($node);
|
||||
} else {
|
||||
$result .= "\n";
|
||||
}
|
||||
if ($trailingComma || $idx !== $lastIdx) {
|
||||
$result .= ',';
|
||||
}
|
||||
}
|
||||
|
||||
return preg_replace('~\n(?!$|' . $this->noIndentToken . ')~', "\n ", $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the pretty printer that a string shall not be indented.
|
||||
*
|
||||
|
@@ -112,6 +112,7 @@ class ParamTest extends \PHPUnit_Framework_TestCase
|
||||
array('float', 'float'),
|
||||
array('string', 'string'),
|
||||
array('iterable', 'iterable'),
|
||||
array('object', 'object'),
|
||||
array('Array', 'array'),
|
||||
array('CALLABLE', 'callable'),
|
||||
array('Some\Class', new Node\Name('Some\Class')),
|
||||
@@ -155,4 +156,16 @@ class ParamTest extends \PHPUnit_Framework_TestCase
|
||||
$node
|
||||
);
|
||||
}
|
||||
|
||||
public function testVariadic() {
|
||||
$node = $this->createParamBuilder('test')
|
||||
->makeVariadic()
|
||||
->getNode()
|
||||
;
|
||||
|
||||
$this->assertEquals(
|
||||
new Node\Param('test', null, null, false, true),
|
||||
$node
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace PhpParser\Builder;
|
||||
|
||||
use PhpParser\Comment;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt;
|
||||
|
||||
class TraitTest extends \PHPUnit_Framework_TestCase
|
||||
@@ -18,19 +19,21 @@ class TraitTest extends \PHPUnit_Framework_TestCase
|
||||
$prop = new Stmt\Property(Stmt\Class_::MODIFIER_PUBLIC, array(
|
||||
new Stmt\PropertyProperty('test')
|
||||
));
|
||||
$use = new Stmt\TraitUse([new Name('OtherTrait')]);
|
||||
$trait = $this->createTraitBuilder('TestTrait')
|
||||
->setDocComment('/** Nice trait */')
|
||||
->addStmt($method1)
|
||||
->addStmts(array($method2, $method3))
|
||||
->addStmts([$method2, $method3])
|
||||
->addStmt($prop)
|
||||
->addStmt($use)
|
||||
->getNode();
|
||||
$this->assertEquals(new Stmt\Trait_('TestTrait', array(
|
||||
'stmts' => array($prop, $method1, $method2, $method3)
|
||||
), array(
|
||||
'comments' => array(
|
||||
$this->assertEquals(new Stmt\Trait_('TestTrait', [
|
||||
'stmts' => [$use, $prop, $method1, $method2, $method3]
|
||||
], [
|
||||
'comments' => [
|
||||
new Comment\Doc('/** Nice trait */')
|
||||
)
|
||||
)), $trait);
|
||||
]
|
||||
]), $trait);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -201,7 +201,13 @@ class LexerTest extends \PHPUnit_Framework_TestCase
|
||||
array(), array()
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
// tests no tokens
|
||||
array(
|
||||
'',
|
||||
array(),
|
||||
array()
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -178,7 +178,7 @@ class NodeTraverserTest extends \PHPUnit_Framework_TestCase
|
||||
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
||||
$visitor->expects($this->at(1))->method('enterNode')->with($mulNode)
|
||||
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
|
||||
$visitor->expects($this->at(2))->method('afterTraversal');
|
||||
$visitor->expects($this->at(2))->method('afterTraverse');
|
||||
$traverser = new NodeTraverser;
|
||||
$traverser->addVisitor($visitor);
|
||||
$this->assertEquals($stmts, $traverser->traverse($stmts));
|
||||
@@ -187,7 +187,7 @@ class NodeTraverserTest extends \PHPUnit_Framework_TestCase
|
||||
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
||||
$visitor->expects($this->at(2))->method('enterNode')->with($varNode1)
|
||||
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
|
||||
$visitor->expects($this->at(3))->method('afterTraversal');
|
||||
$visitor->expects($this->at(3))->method('afterTraverse');
|
||||
$traverser = new NodeTraverser;
|
||||
$traverser->addVisitor($visitor);
|
||||
$this->assertEquals($stmts, $traverser->traverse($stmts));
|
||||
@@ -196,7 +196,7 @@ class NodeTraverserTest extends \PHPUnit_Framework_TestCase
|
||||
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
||||
$visitor->expects($this->at(3))->method('leaveNode')->with($varNode1)
|
||||
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
|
||||
$visitor->expects($this->at(4))->method('afterTraversal');
|
||||
$visitor->expects($this->at(4))->method('afterTraverse');
|
||||
$traverser = new NodeTraverser;
|
||||
$traverser->addVisitor($visitor);
|
||||
$this->assertEquals($stmts, $traverser->traverse($stmts));
|
||||
@@ -205,7 +205,7 @@ class NodeTraverserTest extends \PHPUnit_Framework_TestCase
|
||||
$visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock();
|
||||
$visitor->expects($this->at(6))->method('leaveNode')->with($mulNode)
|
||||
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
|
||||
$visitor->expects($this->at(7))->method('afterTraversal');
|
||||
$visitor->expects($this->at(7))->method('afterTraverse');
|
||||
$traverser = new NodeTraverser;
|
||||
$traverser->addVisitor($visitor);
|
||||
$this->assertEquals($stmts, $traverser->traverse($stmts));
|
||||
@@ -216,7 +216,7 @@ class NodeTraverserTest extends \PHPUnit_Framework_TestCase
|
||||
->will($this->returnValue(NodeTraverser::REMOVE_NODE));
|
||||
$visitor->expects($this->at(7))->method('enterNode')->with($printNode)
|
||||
->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL));
|
||||
$visitor->expects($this->at(8))->method('afterTraversal');
|
||||
$visitor->expects($this->at(8))->method('afterTraverse');
|
||||
$traverser = new NodeTraverser;
|
||||
$traverser->addVisitor($visitor);
|
||||
$this->assertEquals([$printNode], $traverser->traverse($stmts));
|
||||
|
@@ -248,11 +248,11 @@ $foo->
|
||||
!!positions
|
||||
Syntax error, unexpected ';', expecting T_STRING or T_VARIABLE or '{' or '$' from 3:1 to 3:1
|
||||
array(
|
||||
0: Expr_PropertyFetch[2:1 - 3:1](
|
||||
0: Expr_PropertyFetch[2:1 - 2:6](
|
||||
var: Expr_Variable[2:1 - 2:4](
|
||||
name: foo
|
||||
)
|
||||
name: Expr_Error[3:1 - 3:1](
|
||||
name: Expr_Error[3:1 - 2:6](
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -272,11 +272,11 @@ array(
|
||||
)
|
||||
returnType: null
|
||||
stmts: array(
|
||||
0: Expr_PropertyFetch[3:5 - 4:1](
|
||||
0: Expr_PropertyFetch[3:5 - 3:10](
|
||||
var: Expr_Variable[3:5 - 3:8](
|
||||
name: bar
|
||||
)
|
||||
name: Expr_Error[4:1 - 4:1](
|
||||
name: Expr_Error[4:1 - 3:10](
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -305,8 +305,8 @@ 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](
|
||||
0: Expr_New[2:1 - 2:3](
|
||||
class: Expr_Error[2:4 - 2:3](
|
||||
)
|
||||
args: array(
|
||||
)
|
||||
@@ -544,8 +544,6 @@ for ($a, ; $b, ; $c, );
|
||||
function ($a, ) use ($b, ) {};
|
||||
-----
|
||||
!!php7
|
||||
A trailing comma is not allowed here from 3:9 to 3:9
|
||||
A trailing comma is not allowed here from 4:18 to 4:18
|
||||
A trailing comma is not allowed here from 5:6 to 5:6
|
||||
A trailing comma is not allowed here from 6:13 to 6:13
|
||||
A trailing comma is not allowed here from 8:21 to 8:21
|
||||
@@ -834,4 +832,35 @@ array(
|
||||
stmts: array(
|
||||
)
|
||||
)
|
||||
)
|
||||
-----
|
||||
<?php
|
||||
|
||||
foo(Bar::);
|
||||
-----
|
||||
!!php7,positions
|
||||
Syntax error, unexpected ')' from 3:10 to 3:10
|
||||
array(
|
||||
0: Expr_FuncCall[3:1 - 3:10](
|
||||
name: Name[3:1 - 3:3](
|
||||
parts: array(
|
||||
0: foo
|
||||
)
|
||||
)
|
||||
args: array(
|
||||
0: Arg[3:5 - 3:9](
|
||||
value: Expr_ClassConstFetch[3:5 - 3:9](
|
||||
class: Name[3:5 - 3:7](
|
||||
parts: array(
|
||||
0: Bar
|
||||
)
|
||||
)
|
||||
name: Expr_Error[3:10 - 3:9](
|
||||
)
|
||||
)
|
||||
byRef: false
|
||||
unpack: false
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
@@ -1,7 +1,7 @@
|
||||
Scalar type declarations
|
||||
-----
|
||||
<?php
|
||||
function test(bool $a, Int $b, FLOAT $c, StRiNg $d, iterable $e) : void {}
|
||||
function test(bool $a, Int $b, FLOAT $c, StRiNg $d, iterable $e, object $f) : void {}
|
||||
-----
|
||||
!!php7
|
||||
array(
|
||||
@@ -44,9 +44,16 @@ array(
|
||||
name: e
|
||||
default: null
|
||||
)
|
||||
5: Param(
|
||||
type: object
|
||||
byRef: false
|
||||
variadic: false
|
||||
name: f
|
||||
default: null
|
||||
)
|
||||
)
|
||||
returnType: void
|
||||
stmts: array(
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
22
test/code/parser/stmt/namespace/commentAfterNamespace.test
Normal file
22
test/code/parser/stmt/namespace/commentAfterNamespace.test
Normal file
@@ -0,0 +1,22 @@
|
||||
Trailing comment after braced namespace declaration
|
||||
-----
|
||||
<?php
|
||||
namespace Foo {}
|
||||
// Comment
|
||||
-----
|
||||
array(
|
||||
0: Stmt_Namespace(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: Foo
|
||||
)
|
||||
)
|
||||
stmts: array(
|
||||
)
|
||||
)
|
||||
1: Stmt_Nop(
|
||||
comments: array(
|
||||
0: // Comment
|
||||
)
|
||||
)
|
||||
)
|
47
test/code/parser/stmt/namespace/groupUseTrailingComma.test
Normal file
47
test/code/parser/stmt/namespace/groupUseTrailingComma.test
Normal file
@@ -0,0 +1,47 @@
|
||||
Group use can have trailing comma
|
||||
-----
|
||||
<?php
|
||||
use A\{B,};
|
||||
use function A\{b,};
|
||||
-----
|
||||
!!php7
|
||||
array(
|
||||
0: Stmt_GroupUse(
|
||||
type: TYPE_UNKNOWN (0)
|
||||
prefix: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
)
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: TYPE_NORMAL (1)
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: B
|
||||
)
|
||||
)
|
||||
alias: B
|
||||
)
|
||||
)
|
||||
)
|
||||
1: Stmt_GroupUse(
|
||||
type: TYPE_FUNCTION (2)
|
||||
prefix: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
)
|
||||
)
|
||||
uses: array(
|
||||
0: Stmt_UseUse(
|
||||
type: TYPE_UNKNOWN (0)
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: b
|
||||
)
|
||||
)
|
||||
alias: b
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
53
test/code/prettyPrinter/commentsInCommaList.test
Normal file
53
test/code/prettyPrinter/commentsInCommaList.test
Normal file
@@ -0,0 +1,53 @@
|
||||
Comments in arrays and function calls
|
||||
-----
|
||||
<?php
|
||||
|
||||
$arr = [
|
||||
// Foo
|
||||
$foo,
|
||||
// Bar
|
||||
$bar,
|
||||
// Discarded
|
||||
];
|
||||
[
|
||||
// Foo
|
||||
$foo,
|
||||
,
|
||||
// Bar
|
||||
$bar,
|
||||
] = $arr;
|
||||
foo(
|
||||
// Foo
|
||||
$foo,
|
||||
// Bar
|
||||
$bar
|
||||
);
|
||||
new Foo(
|
||||
// Foo
|
||||
$foo
|
||||
);
|
||||
-----
|
||||
!!php7
|
||||
$arr = [
|
||||
// Foo
|
||||
$foo,
|
||||
// Bar
|
||||
$bar,
|
||||
];
|
||||
[
|
||||
// Foo
|
||||
$foo,
|
||||
,
|
||||
// Bar
|
||||
$bar,
|
||||
] = $arr;
|
||||
foo(
|
||||
// Foo
|
||||
$foo,
|
||||
// Bar
|
||||
$bar
|
||||
);
|
||||
new Foo(
|
||||
// Foo
|
||||
$foo
|
||||
);
|
Reference in New Issue
Block a user