Compare commits

..

5 Commits

Author SHA1 Message Date
Nikita Popov
c346bbfafe Release PHP-Parser 4.6.0 2020-07-02 19:12:47 +02:00
Nikita Popov
4abc531213 Canonicalize to PHP 8 comment token format
The trailing newline is no longer part of the comment token.
2020-06-27 18:53:09 +02:00
TomasVotruba
b58b19ed1d Add constructor promotion support 2020-06-27 17:57:47 +02:00
Nikita Popov
0d2d8f95a1 FPPP: Support catch without variable 2020-06-27 17:42:46 +02:00
TomasVotruba
244db65dd1 [PHP 8.0] Add trailing comma in parameter list 2020-06-12 20:24:25 +02:00
33 changed files with 1327 additions and 938 deletions

View File

@@ -1,8 +1,25 @@
Version 4.5.1-dev Version 4.6.1-dev
----------------- -----------------
Nothing yet. Nothing yet.
Version 4.6.0 (2020-07-02)
--------------------------
### Added
* [PHP 8.0] Added support for trailing commas in parameter lists.
* [PHP 8.0] Added support for constructor promotion. The parameter visibility is stored in
`Node\Param::$flags`.
### Fixed
* Comment tokens now always follow the PHP 8 interpretation, and do not include trailing
whitespace.
* As a result of the previous change, some whitespace issues when inserting a statement into a
method containing only a comment, and using the formatting-preserving pretty printer, have been
resolved.
Version 4.5.0 (2020-06-03) Version 4.5.0 (2020-06-03)
-------------------------- --------------------------

View File

@@ -440,7 +440,7 @@ foreach_variable:
; ;
parameter_list: parameter_list:
non_empty_parameter_list no_comma { $$ = $1; } non_empty_parameter_list optional_comma { $$ = $1; }
| /* empty */ { $$ = array(); } | /* empty */ { $$ = array(); }
; ;
@@ -449,13 +449,22 @@ non_empty_parameter_list:
| non_empty_parameter_list ',' parameter { push($1, $3); } | non_empty_parameter_list ',' parameter { push($1, $3); }
; ;
optional_visibility_modifier:
/* empty */ { $$ = 0; }
| T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
| T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; }
| T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; }
;
parameter: parameter:
optional_type optional_ref optional_ellipsis plain_variable optional_visibility_modifier optional_type optional_ref optional_ellipsis plain_variable
{ $$ = Node\Param[$4, null, $1, $2, $3]; $this->checkParam($$); } { $$ = new Node\Param($5, null, $2, $3, $4, attributes(), $1);
| optional_type optional_ref optional_ellipsis plain_variable '=' expr $this->checkParam($$); }
{ $$ = Node\Param[$4, $6, $1, $2, $3]; $this->checkParam($$); } | optional_visibility_modifier optional_type optional_ref optional_ellipsis plain_variable '=' expr
| optional_type optional_ref optional_ellipsis error { $$ = new Node\Param($5, $7, $2, $3, $4, attributes(), $1);
{ $$ = Node\Param[Expr\Error[], null, $1, $2, $3]; } $this->checkParam($$); }
| optional_visibility_modifier optional_type optional_ref optional_ellipsis error
{ $$ = new Node\Param(Expr\Error[], null, $2, $3, $4, attributes(), $1); }
; ;
type_expr: type_expr:

View File

@@ -89,7 +89,7 @@ class Lexer
error_clear_last(); error_clear_last();
$this->tokens = @token_get_all($code); $this->tokens = @token_get_all($code);
$this->handleErrors($errorHandler); $this->postprocessTokens($errorHandler);
if (false !== $scream) { if (false !== $scream) {
ini_set('xdebug.scream', $scream); ini_set('xdebug.scream', $scream);
@@ -131,40 +131,14 @@ class Lexer
&& substr($token[1], -2) !== '*/'; && substr($token[1], -2) !== '*/';
} }
/** protected function postprocessTokens(ErrorHandler $errorHandler) {
* Check whether an error *may* have occurred during tokenization.
*
* @return bool
*/
private function errorMayHaveOccurred() : bool {
if (defined('HHVM_VERSION')) {
// In HHVM token_get_all() does not throw warnings, so we need to conservatively
// assume that an error occurred
return true;
}
if (PHP_VERSION_ID >= 80000) {
// PHP 8 converts the "bad character" case into a parse error, rather than treating
// it as a lexing warning. To preserve previous behavior, we need to assume that an
// error occurred.
// TODO: We should handle this the same way as PHP 8: Only generate T_BAD_CHARACTER
// token here (for older PHP versions) and leave generationg of the actual parse error
// to the parser. This will also save the full token scan on PHP 8 here.
return true;
}
return null !== error_get_last();
}
protected function handleErrors(ErrorHandler $errorHandler) {
if (!$this->errorMayHaveOccurred()) {
return;
}
// PHP's error handling for token_get_all() is rather bad, so if we want detailed // PHP's error handling for token_get_all() is rather bad, so if we want detailed
// error information we need to compute it ourselves. Invalid character errors are // error information we need to compute it ourselves. Invalid character errors are
// detected by finding "gaps" in the token array. Unterminated comments are detected // detected by finding "gaps" in the token array. Unterminated comments are detected
// by checking if a trailing comment has a "*/" at the end. // by checking if a trailing comment has a "*/" at the end.
//
// Additionally, we canonicalize to the PHP 8 comment format here, which does not include
// the trailing whitespace anymore
$filePos = 0; $filePos = 0;
$line = 1; $line = 1;
@@ -178,6 +152,23 @@ class Lexer
$this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler); $this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler);
} }
if ($token[0] === \T_COMMENT && preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) {
$trailingNewline = $matches[0];
$token[1] = substr($token[1], 0, -strlen($trailingNewline));
$this->tokens[$i] = $token;
if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) {
// Move trailing newline into following T_WHITESPACE token, if it already exists.
$this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1];
$this->tokens[$i + 1][2]--;
} else {
// Otherwise, we need to create a new T_WHITESPACE token.
array_splice($this->tokens, $i + 1, 0, [
[\T_WHITESPACE, $trailingNewline, $line],
]);
$numTokens++;
}
}
$tokenValue = \is_string($token) ? $token : $token[1]; $tokenValue = \is_string($token) ? $token : $token[1];
$tokenLen = \strlen($tokenValue); $tokenLen = \strlen($tokenValue);

View File

@@ -16,6 +16,8 @@ class Param extends NodeAbstract
public $var; public $var;
/** @var null|Expr Default value */ /** @var null|Expr Default value */
public $default; public $default;
/** @var int */
public $flags;
/** /**
* Constructs a parameter node. * Constructs a parameter node.
@@ -25,11 +27,14 @@ class Param extends NodeAbstract
* @param null|string|Identifier|Name|NullableType|UnionType $type Type declaration * @param null|string|Identifier|Name|NullableType|UnionType $type Type declaration
* @param bool $byRef Whether is passed by reference * @param bool $byRef Whether is passed by reference
* @param bool $variadic Whether this is a variadic argument * @param bool $variadic Whether this is a variadic argument
* @param array $flags Optional visibility flags
* @param array $attributes Additional attributes * @param array $attributes Additional attributes
*/ */
public function __construct( public function __construct(
$var, Expr $default = null, $type = null, $var, Expr $default = null, $type = null,
bool $byRef = false, bool $variadic = false, array $attributes = [] bool $byRef = false, bool $variadic = false,
array $attributes = [],
int $flags = 0
) { ) {
$this->attributes = $attributes; $this->attributes = $attributes;
$this->type = \is_string($type) ? new Identifier($type) : $type; $this->type = \is_string($type) ? new Identifier($type) : $type;
@@ -37,10 +42,11 @@ class Param extends NodeAbstract
$this->variadic = $variadic; $this->variadic = $variadic;
$this->var = $var; $this->var = $var;
$this->default = $default; $this->default = $default;
$this->flags = $flags;
} }
public function getSubNodeNames() : array { public function getSubNodeNames() : array {
return ['type', 'byRef', 'variadic', 'var', 'default']; return ['flags', 'type', 'byRef', 'variadic', 'var', 'default'];
} }
public function getType() : string { public function getType() : string {

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,8 @@ class Standard extends PrettyPrinterAbstract
// Special nodes // Special nodes
protected function pParam(Node\Param $node) { protected function pParam(Node\Param $node) {
return ($node->type ? $this->p($node->type) . ' ' : '') return ($this->pModifiers($node->flags))
. ($node->type ? $this->p($node->type) . ' ' : '')
. ($node->byRef ? '&' : '') . ($node->byRef ? '&' : '')
. ($node->variadic ? '...' : '') . ($node->variadic ? '...' : '')
. $this->p($node->var) . $this->p($node->var)
@@ -725,7 +726,7 @@ class Standard extends PrettyPrinterAbstract
protected function pStmt_ClassMethod(Stmt\ClassMethod $node) { protected function pStmt_ClassMethod(Stmt\ClassMethod $node) {
return $this->pModifiers($node->flags) return $this->pModifiers($node->flags)
. 'function ' . ($node->byRef ? '&' : '') . $node->name . 'function ' . ($node->byRef ? '&' : '') . $node->name
. '(' . $this->pCommaSeparated($node->params) . ')' . '(' . $this->pMaybeMultiline($node->params) . ')'
. (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '')
. (null !== $node->stmts . (null !== $node->stmts
? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}' ? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'

View File

@@ -1220,6 +1220,7 @@ abstract class PrettyPrinterAbstract
'Param->type' => $stripRight, 'Param->type' => $stripRight,
'Param->default' => $stripEquals, 'Param->default' => $stripEquals,
'Stmt_Break->num' => $stripBoth, 'Stmt_Break->num' => $stripBoth,
'Stmt_Catch->var' => $stripLeft,
'Stmt_ClassMethod->returnType' => $stripColon, 'Stmt_ClassMethod->returnType' => $stripColon,
'Stmt_Class->extends' => ['left' => \T_EXTENDS], 'Stmt_Class->extends' => ['left' => \T_EXTENDS],
'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS], 'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS],
@@ -1257,6 +1258,7 @@ abstract class PrettyPrinterAbstract
'Param->type' => [null, false, null, ' '], 'Param->type' => [null, false, null, ' '],
'Param->default' => [null, false, ' = ', null], 'Param->default' => [null, false, ' = ', null],
'Stmt_Break->num' => [\T_BREAK, false, ' ', null], 'Stmt_Break->num' => [\T_BREAK, false, ' ', null],
'Stmt_Catch->var' => [null, false, ' ', null],
'Stmt_ClassMethod->returnType' => [')', false, ' : ', null], 'Stmt_ClassMethod->returnType' => [')', false, ' : ', null],
'Stmt_Class->extends' => [null, false, ' extends ', null], 'Stmt_Class->extends' => [null, false, ' extends ', null],
'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null], 'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null],
@@ -1413,6 +1415,7 @@ abstract class PrettyPrinterAbstract
'Stmt_ClassMethod->flags' => \T_FUNCTION, 'Stmt_ClassMethod->flags' => \T_FUNCTION,
'Stmt_Class->flags' => \T_CLASS, 'Stmt_Class->flags' => \T_CLASS,
'Stmt_Property->flags' => \T_VARIABLE, 'Stmt_Property->flags' => \T_VARIABLE,
'Param->flags' => \T_VARIABLE,
//'Stmt_TraitUseAdaptation_Alias->newModifier' => 0, // TODO //'Stmt_TraitUseAdaptation_Alias->newModifier' => 0, // TODO
]; ];

View File

@@ -124,12 +124,12 @@ class LexerTest extends \PHPUnit\Framework\TestCase
'comments' => [ 'comments' => [
new Comment('/* comment */', new Comment('/* comment */',
1, 6, 1, 1, 18, 1), 1, 6, 1, 1, 18, 1),
new Comment('// comment' . "\n", new Comment('// comment',
1, 20, 3, 2, 30, 3), 1, 20, 3, 1, 29, 3),
new Comment\Doc('/** docComment 1 */', new Comment\Doc('/** docComment 1 */',
2, 31, 4, 2, 49, 4), 2, 31, 5, 2, 49, 5),
new Comment\Doc('/** docComment 2 */', new Comment\Doc('/** docComment 2 */',
2, 50, 5, 2, 68, 5), 2, 50, 6, 2, 68, 6),
], ],
], ],
['endLine' => 2] ['endLine' => 2]
@@ -185,11 +185,11 @@ class LexerTest extends \PHPUnit\Framework\TestCase
], ],
[ [
Tokens::T_CONSTANT_ENCAPSED_STRING, '"b"', Tokens::T_CONSTANT_ENCAPSED_STRING, '"b"',
['startTokenPos' => 5], ['endTokenPos' => 5] ['startTokenPos' => 6], ['endTokenPos' => 6]
], ],
[ [
ord(';'), ';', ord(';'), ';',
['startTokenPos' => 6], ['endTokenPos' => 6] ['startTokenPos' => 7], ['endTokenPos' => 7]
], ],
] ]
], ],
@@ -251,14 +251,17 @@ class LexerTest extends \PHPUnit\Framework\TestCase
} }
public function testGetTokens() { public function testGetTokens() {
$code = '<?php "a";' . "\n" . '// foo' . "\n" . '"b";'; $code = '<?php "a";' . "\n" . '// foo' . "\n" . '// bar' . "\n\n" . '"b";';
$expectedTokens = [ $expectedTokens = [
[T_OPEN_TAG, '<?php ', 1], [T_OPEN_TAG, '<?php ', 1],
[T_CONSTANT_ENCAPSED_STRING, '"a"', 1], [T_CONSTANT_ENCAPSED_STRING, '"a"', 1],
';', ';',
[T_WHITESPACE, "\n", 1], [T_WHITESPACE, "\n", 1],
[T_COMMENT, '// foo' . "\n", 2], [T_COMMENT, '// foo', 2],
[T_CONSTANT_ENCAPSED_STRING, '"b"', 3], [T_WHITESPACE, "\n", 2],
[T_COMMENT, '// bar', 3],
[T_WHITESPACE, "\n\n", 3],
[T_CONSTANT_ENCAPSED_STRING, '"b"', 5],
';', ';',
]; ];

View File

@@ -247,6 +247,7 @@ PHP;
"kind": 10 "kind": 10
} }
}, },
"flags": 0,
"attributes": { "attributes": {
"startLine": 4, "startLine": 4,
"endLine": 4 "endLine": 4
@@ -273,6 +274,7 @@ PHP;
"endLine": 4 "endLine": 4
} }
}, },
"flags": 0,
"attributes": { "attributes": {
"startLine": 4, "startLine": 4,
"endLine": 4 "endLine": 4
@@ -305,12 +307,12 @@ PHP;
"comments": [ "comments": [
{ {
"nodeType": "Comment", "nodeType": "Comment",
"text": "\/\/ comment\n", "text": "\/\/ comment",
"line": 2, "line": 2,
"filePos": 6, "filePos": 6,
"tokenPos": 1, "tokenPos": 1,
"endLine": 3, "endLine": 2,
"endFilePos": 16, "endFilePos": 15,
"endTokenPos": 1 "endTokenPos": 1
}, },
{ {
@@ -318,10 +320,10 @@ PHP;
"text": "\/** doc comment *\/", "text": "\/** doc comment *\/",
"line": 3, "line": 3,
"filePos": 17, "filePos": 17,
"tokenPos": 2, "tokenPos": 3,
"endLine": 3, "endLine": 3,
"endFilePos": 34, "endFilePos": 34,
"endTokenPos": 2 "endTokenPos": 3
} }
], ],
"endLine": 6 "endLine": 6

View File

@@ -83,10 +83,10 @@ EOC;
$this->assertInstanceOf(Stmt\Echo_::class, $echo); $this->assertInstanceOf(Stmt\Echo_::class, $echo);
$this->assertEquals([ $this->assertEquals([
'comments' => [ 'comments' => [
new Comment("// Line\n", new Comment("// Line",
4, 49, 12, 5, 56, 12), 4, 49, 12, 4, 55, 12),
new Comment("// Comments\n", new Comment("// Comments",
5, 61, 14, 6, 72, 14), 5, 61, 14, 5, 71, 14),
], ],
'startLine' => 6, 'startLine' => 6,
'endLine' => 6, 'endLine' => 6,

View File

@@ -15,8 +15,8 @@ class Foo {
public function __construct() public function __construct()
{ {
// I'm just a comment // I'm just a comment
$foo;
$foo; } }
} }
----- -----
<?php <?php
@@ -72,5 +72,6 @@ class Foo {
public function __construct() public function __construct()
{ {
// I'm a new comment // I'm a new comment
} }
} }

View File

@@ -174,3 +174,21 @@ $stmts[0]->name = new Node\Name('Foo');
namespace Foo namespace Foo
{ echo 42; } { echo 42; }
-----
<?php
try
{
}
catch (Exception)
{
}
-----
$stmts[0]->catches[0]->var = new Expr\Variable('e');
-----
<?php
try
{
}
catch (Exception $e)
{
}

View File

@@ -31,3 +31,27 @@ class Bar {
public final function public final function
foo() {} foo() {}
} }
-----
<?php
function test(
public T1 $x
= 'y',
private T2 $y
= 'z',
T3 $z
= 'x',
) {}
-----
$stmts[0]->params[0]->flags = Stmt\Class_::MODIFIER_PRIVATE;
$stmts[0]->params[1]->flags = 0;
$stmts[0]->params[2]->flags = Stmt\Class_::MODIFIER_PUBLIC;
-----
<?php
function test(
private T1 $x
= 'y',
T2 $y
= 'z',
public T3 $z
= 'x',
) {}

View File

@@ -192,3 +192,21 @@ $stmts[0]->name = null;
namespace namespace
{ {
} }
-----
<?php
try
{
}
catch (Exception $e)
{
}
-----
$stmts[0]->catches[0]->var = null;
-----
<?php
try
{
}
catch (Exception)
{
}

View File

@@ -594,14 +594,13 @@ isset($x, );
declare(a=42, ); declare(a=42, );
function foo($a, ) {}
foo($a, ); foo($a, );
global $a, ; global $a, ;
static $a, ; static $a, ;
echo $a, ; echo $a, ;
for ($a, ; $b, ; $c, ); for ($a, ; $b, ; $c, );
function ($a, ) use ($b, ) {}; function ($a) use ($b, ) {};
----- -----
!!php7 !!php7
A trailing comma is not allowed here from 5:6 to 5:6 A trailing comma is not allowed here from 5:6 to 5:6
@@ -614,15 +613,13 @@ A trailing comma is not allowed here from 13:17 to 13:17
A trailing comma is not allowed here from 14:14 to 14:14 A trailing comma is not allowed here from 14:14 to 14:14
A trailing comma is not allowed here from 16:22 to 16:22 A trailing comma is not allowed here from 16:22 to 16:22
A trailing comma is not allowed here from 21:13 to 21:13 A trailing comma is not allowed here from 21:13 to 21:13
A trailing comma is not allowed here from 23:16 to 23:16 A trailing comma is not allowed here from 24:10 to 24:10
A trailing comma is not allowed here from 25:10 to 25:10 A trailing comma is not allowed here from 25:10 to 25:10
A trailing comma is not allowed here from 26:10 to 26:10 A trailing comma is not allowed here from 26:8 to 26:8
A trailing comma is not allowed here from 27:8 to 27:8 A trailing comma is not allowed here from 28:8 to 28:8
A trailing comma is not allowed here from 29:8 to 29:8 A trailing comma is not allowed here from 28:14 to 28:14
A trailing comma is not allowed here from 29:14 to 29:14 A trailing comma is not allowed here from 28:20 to 28:20
A trailing comma is not allowed here from 29:20 to 29:20 A trailing comma is not allowed here from 29:22 to 29:22
A trailing comma is not allowed here from 30:13 to 30:13
A trailing comma is not allowed here from 30:24 to 30:24
array( array(
0: Stmt_GroupUse( 0: Stmt_GroupUse(
type: TYPE_UNKNOWN (0) type: TYPE_UNKNOWN (0)
@@ -811,27 +808,7 @@ array(
) )
stmts: null stmts: null
) )
9: Stmt_Function( 9: Stmt_Expression(
byRef: false
name: Identifier(
name: foo
)
params: array(
0: Param(
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: a
)
default: null
)
)
returnType: null
stmts: array(
)
)
10: Stmt_Expression(
expr: Expr_FuncCall( expr: Expr_FuncCall(
name: Name( name: Name(
parts: array( parts: array(
@@ -849,14 +826,14 @@ array(
) )
) )
) )
11: Stmt_Global( 10: Stmt_Global(
vars: array( vars: array(
0: Expr_Variable( 0: Expr_Variable(
name: a name: a
) )
) )
) )
12: Stmt_Static( 11: Stmt_Static(
vars: array( vars: array(
0: Stmt_StaticVar( 0: Stmt_StaticVar(
var: Expr_Variable( var: Expr_Variable(
@@ -866,14 +843,14 @@ array(
) )
) )
) )
13: Stmt_Echo( 12: Stmt_Echo(
exprs: array( exprs: array(
0: Expr_Variable( 0: Expr_Variable(
name: a name: a
) )
) )
) )
14: Stmt_For( 13: Stmt_For(
init: array( init: array(
0: Expr_Variable( 0: Expr_Variable(
name: a name: a
@@ -892,12 +869,13 @@ array(
stmts: array( stmts: array(
) )
) )
15: Stmt_Expression( 14: Stmt_Expression(
expr: Expr_Closure( expr: Expr_Closure(
static: false static: false
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -1075,6 +1053,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: Name( type: Name(
parts: array( parts: array(
0: Type 0: Type
@@ -1103,6 +1082,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: Name( type: Name(
parts: array( parts: array(
0: Type1 0: Type1
@@ -1116,6 +1096,7 @@ array(
default: null default: null
) )
1: Param( 1: Param(
flags: 0
type: Name( type: Name(
parts: array( parts: array(
0: Type2 0: Type2
@@ -1144,6 +1125,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: true variadic: true
@@ -1168,6 +1150,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: true byRef: true
variadic: false variadic: false
@@ -1192,6 +1175,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: Name( type: Name(
parts: array( parts: array(
0: Bar 0: Bar
@@ -1225,6 +1209,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: Name( type: Name(
parts: array( parts: array(
0: Baz 0: Baz
@@ -1249,6 +1234,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: Name( type: Name(
parts: array( parts: array(
0: Foo 0: Foo

View File

@@ -16,6 +16,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: Identifier( type: Identifier(
name: bool name: bool
) )
@@ -39,6 +40,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -62,6 +64,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: true byRef: true
variadic: false variadic: false
@@ -83,6 +86,7 @@ array(
byRef: true byRef: true
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -104,6 +108,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -113,6 +118,7 @@ array(
default: null default: null
) )
1: Param( 1: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: true variadic: true

View File

@@ -16,6 +16,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -43,6 +44,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -96,6 +98,7 @@ array(
byRef: true byRef: true
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -131,6 +134,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false

View File

@@ -198,6 +198,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -264,6 +265,7 @@ array(
byRef: false byRef: false
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false

View File

@@ -0,0 +1,81 @@
Property promotion
-----
<?php
class Point {
public function __construct(
public float $x = 0.0,
protected array $y = [],
private string $z = 'hello'
) {}
}
-----
!!php7
array(
0: Stmt_Class(
flags: 0
name: Identifier(
name: Point
)
extends: null
implements: array(
)
stmts: array(
0: Stmt_ClassMethod(
flags: MODIFIER_PUBLIC (1)
byRef: false
name: Identifier(
name: __construct
)
params: array(
0: Param(
flags: MODIFIER_PUBLIC (1)
type: Identifier(
name: float
)
byRef: false
variadic: false
var: Expr_Variable(
name: x
)
default: Scalar_DNumber(
value: 0
)
)
1: Param(
flags: MODIFIER_PROTECTED (2)
type: Identifier(
name: array
)
byRef: false
variadic: false
var: Expr_Variable(
name: y
)
default: Expr_Array(
items: array(
)
)
)
2: Param(
flags: MODIFIER_PRIVATE (4)
type: Identifier(
name: string
)
byRef: false
variadic: false
var: Expr_Variable(
name: z
)
default: Scalar_String(
value: hello
)
)
)
returnType: null
stmts: array(
)
)
)
)
)

View File

@@ -127,6 +127,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false

View File

@@ -12,6 +12,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: Identifier( type: Identifier(
name: bool name: bool
) )
@@ -23,6 +24,7 @@ array(
default: null default: null
) )
1: Param( 1: Param(
flags: 0
type: Identifier( type: Identifier(
name: int name: int
) )
@@ -34,6 +36,7 @@ array(
default: null default: null
) )
2: Param( 2: Param(
flags: 0
type: Identifier( type: Identifier(
name: float name: float
) )
@@ -45,6 +48,7 @@ array(
default: null default: null
) )
3: Param( 3: Param(
flags: 0
type: Identifier( type: Identifier(
name: string name: string
) )
@@ -56,6 +60,7 @@ array(
default: null default: null
) )
4: Param( 4: Param(
flags: 0
type: Identifier( type: Identifier(
name: iterable name: iterable
) )
@@ -67,6 +72,7 @@ array(
default: null default: null
) )
5: Param( 5: Param(
flags: 0
type: Identifier( type: Identifier(
name: object name: object
) )
@@ -78,6 +84,7 @@ array(
default: null default: null
) )
6: Param( 6: Param(
flags: 0
type: Identifier( type: Identifier(
name: mixed name: mixed
) )

View File

@@ -13,6 +13,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: true byRef: true
variadic: false variadic: false
@@ -33,6 +34,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false

View File

@@ -22,6 +22,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -37,6 +38,7 @@ array(
) )
) )
1: Param( 1: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -48,6 +50,7 @@ array(
) )
) )
2: Param( 2: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -66,6 +69,7 @@ array(
) )
) )
3: Param( 3: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -79,6 +83,7 @@ array(
) )
) )
4: Param( 4: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -92,6 +97,7 @@ array(
) )
) )
5: Param( 5: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -104,6 +110,7 @@ array(
) )
) )
6: Param( 6: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -116,6 +123,7 @@ array(
) )
) )
7: Param( 7: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -136,6 +144,7 @@ array(
) )
) )
8: Param( 8: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false

View File

@@ -14,6 +14,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: NullableType( type: NullableType(
type: Name( type: Name(
parts: array( parts: array(
@@ -29,6 +30,7 @@ array(
default: null default: null
) )
1: Param( 1: Param(
flags: 0
type: NullableType( type: NullableType(
type: Identifier( type: Identifier(
name: string name: string

View File

@@ -0,0 +1,116 @@
Trailing comma in parameter list
-----
<?php
function foo($bar, ) {
}
-----
!!php7
array(
0: Stmt_Function(
byRef: false
name: Identifier(
name: foo
)
params: array(
0: Param(
flags: 0
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: bar
)
default: null
)
)
returnType: null
stmts: array(
)
)
)
-----
<?php
class Foo
{
function __construct($name, $value, )
{
}
}
-----
!!php7
array(
0: Stmt_Class(
flags: 0
name: Identifier(
name: Foo
)
extends: null
implements: array(
)
stmts: array(
0: Stmt_ClassMethod(
flags: 0
byRef: false
name: Identifier(
name: __construct
)
params: array(
0: Param(
flags: 0
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: name
)
default: null
)
1: Param(
flags: 0
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: value
)
default: null
)
)
returnType: null
stmts: array(
)
)
)
)
)
-----
<?php
fn($foo, ) => $bar;
-----
!!php7
array(
0: Stmt_Expression(
expr: Expr_ArrowFunction(
static: false
byRef: false
params: array(
0: Param(
flags: 0
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: foo
)
default: null
)
)
returnType: null
expr: Expr_Variable(
name: bar
)
)
)
)

View File

@@ -12,6 +12,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -21,6 +22,7 @@ array(
default: null default: null
) )
1: Param( 1: Param(
flags: 0
type: Identifier( type: Identifier(
name: array name: array
) )
@@ -32,6 +34,7 @@ array(
default: null default: null
) )
2: Param( 2: Param(
flags: 0
type: Identifier( type: Identifier(
name: callable name: callable
) )
@@ -43,6 +46,7 @@ array(
default: null default: null
) )
3: Param( 3: Param(
flags: 0
type: Name( type: Name(
parts: array( parts: array(
0: E 0: E

View File

@@ -54,6 +54,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: UnionType( type: UnionType(
types: array( types: array(
0: Name( 0: Name(

View File

@@ -14,6 +14,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -23,6 +24,7 @@ array(
default: null default: null
) )
1: Param( 1: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: true variadic: true
@@ -43,6 +45,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -52,6 +55,7 @@ array(
default: null default: null
) )
1: Param( 1: Param(
flags: 0
type: null type: null
byRef: true byRef: true
variadic: true variadic: true
@@ -72,6 +76,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -81,6 +86,7 @@ array(
default: null default: null
) )
1: Param( 1: Param(
flags: 0
type: Name( type: Name(
parts: array( parts: array(
0: Type 0: Type
@@ -105,6 +111,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: false variadic: false
@@ -114,6 +121,7 @@ array(
default: null default: null
) )
1: Param( 1: Param(
flags: 0
type: Name( type: Name(
parts: array( parts: array(
0: Type 0: Type

View File

@@ -12,6 +12,7 @@ array(
) )
params: array( params: array(
0: Param( 0: Param(
flags: 0
type: null type: null
byRef: false byRef: false
variadic: true variadic: true

View File

@@ -2,7 +2,10 @@ Closures
----- -----
<?php <?php
$closureWithArgs = function ($arg1, $arg2) { $closureWithArgs = function (
$arg1,
$arg2
) {
$comment = 'closure body'; $comment = 'closure body';
}; };

View File

@@ -0,0 +1,49 @@
Property promotion
-----
<?php
class Point
{
public function __construct(
public float $x = 0.0,
protected array $y = [],
private string $z = 'hello',
) {
}
}
-----
!!php7
class Point
{
public function __construct(public float $x = 0.0, protected array $y = [], private string $z = 'hello')
{
}
}
-----
<?php
class Test
{
public $z;
public function __construct(
public int $x,
/** @SomeAnnotation() */
public string $y = "123",
string $z = "abc"
)
{
}
}
-----
!!php7
class Test
{
public $z;
public function __construct(
public int $x,
/** @SomeAnnotation() */
public string $y = "123",
string $z = "abc"
)
{
}
}