mirror of
https://github.com/phabelio/PHP-Parser.git
synced 2025-01-22 13:21:12 +01:00
Add support for first-class callables
I'm somewhat unsure about the AST structure here. VariadicPlaceholder is not a general expression. Maybe Arg->expr should be Expr|VariadicPlaceholder? Or possibly the call arguments should be an array of Arg|VariadicPlaceholder?
This commit is contained in:
parent
d2c645f163
commit
13549aa794
@ -5,6 +5,9 @@ Version 4.12.1-dev
|
||||
|
||||
* [PHP 8.1] Added support for intersection types using a new `IntersectionType` node.
|
||||
* [PHP 8.1] Added support for explicit octal literals.
|
||||
* [PHP 8.1] Added support for first-class callables. These are represented using a call whose first
|
||||
`Arg->expr` is an `Expr\VariadicPlaceholder`. The representation is intended to be
|
||||
forward-compatible with partial function application, just like the PHP feature itself.
|
||||
|
||||
Version 4.12.0 (2021-07-21)
|
||||
---------------------------
|
||||
|
@ -619,6 +619,12 @@ optional_return_type:
|
||||
argument_list:
|
||||
'(' ')' { $$ = array(); }
|
||||
| '(' non_empty_argument_list optional_comma ')' { $$ = $2; }
|
||||
| '(' variadic_placeholder ')' { init($2); }
|
||||
;
|
||||
|
||||
variadic_placeholder:
|
||||
T_ELLIPSIS
|
||||
{ $$ = Node\Arg[Node\VariadicPlaceholder[], false, false]; }
|
||||
;
|
||||
|
||||
non_empty_argument_list:
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace PhpParser\Node;
|
||||
|
||||
use PhpParser\Node\Expr\VariadicPlaceholder;
|
||||
use PhpParser\NodeAbstract;
|
||||
|
||||
class Arg extends NodeAbstract
|
||||
|
27
lib/PhpParser/Node/Expr/VariadicPlaceholder.php
Normal file
27
lib/PhpParser/Node/Expr/VariadicPlaceholder.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node\Expr;
|
||||
|
||||
use PhpParser\Node\Expr;
|
||||
|
||||
/**
|
||||
* Represents the "..." in "foo(...)" of the first-class callable syntax.
|
||||
*/
|
||||
class VariadicPlaceholder extends Expr {
|
||||
/**
|
||||
* Create a variadic argument placeholder (first-class callable syntax).
|
||||
*
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
public function getType(): string {
|
||||
return 'Expr_VariadicPlaceholder';
|
||||
}
|
||||
|
||||
public function getSubNodeNames(): array {
|
||||
return [];
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -692,6 +692,10 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
}
|
||||
|
||||
protected function pExpr_VariadicPlaceholder(Expr\VariadicPlaceholder $node) {
|
||||
return '...';
|
||||
}
|
||||
|
||||
// Declarations
|
||||
|
||||
protected function pStmt_Namespace(Stmt\Namespace_ $node) {
|
||||
|
131
test/code/parser/expr/firstClassCallables.test
Normal file
131
test/code/parser/expr/firstClassCallables.test
Normal file
@ -0,0 +1,131 @@
|
||||
First-class callables
|
||||
-----
|
||||
<?php
|
||||
foo(...);
|
||||
$this->foo(...);
|
||||
A::foo(...);
|
||||
|
||||
// These are invalid, but accepted on the parser level.
|
||||
new Foo(...);
|
||||
|
||||
#[Foo(...)]
|
||||
function foo() {}
|
||||
-----
|
||||
!!php7
|
||||
array(
|
||||
0: Stmt_Expression(
|
||||
expr: Expr_FuncCall(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: foo
|
||||
)
|
||||
)
|
||||
args: array(
|
||||
0: Arg(
|
||||
name: null
|
||||
value: Expr_VariadicPlaceholder(
|
||||
)
|
||||
byRef: false
|
||||
unpack: false
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
1: Stmt_Expression(
|
||||
expr: Expr_MethodCall(
|
||||
var: Expr_Variable(
|
||||
name: this
|
||||
)
|
||||
name: Identifier(
|
||||
name: foo
|
||||
)
|
||||
args: array(
|
||||
0: Arg(
|
||||
name: null
|
||||
value: Expr_VariadicPlaceholder(
|
||||
)
|
||||
byRef: false
|
||||
unpack: false
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
2: Stmt_Expression(
|
||||
expr: Expr_StaticCall(
|
||||
class: Name(
|
||||
parts: array(
|
||||
0: A
|
||||
)
|
||||
)
|
||||
name: Identifier(
|
||||
name: foo
|
||||
)
|
||||
args: array(
|
||||
0: Arg(
|
||||
name: null
|
||||
value: Expr_VariadicPlaceholder(
|
||||
)
|
||||
byRef: false
|
||||
unpack: false
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
3: Stmt_Expression(
|
||||
expr: Expr_New(
|
||||
class: Name(
|
||||
parts: array(
|
||||
0: Foo
|
||||
)
|
||||
)
|
||||
args: array(
|
||||
0: Arg(
|
||||
name: null
|
||||
value: Expr_VariadicPlaceholder(
|
||||
)
|
||||
byRef: false
|
||||
unpack: false
|
||||
)
|
||||
)
|
||||
comments: array(
|
||||
0: // These are invalid, but accepted on the parser level.
|
||||
)
|
||||
)
|
||||
comments: array(
|
||||
0: // These are invalid, but accepted on the parser level.
|
||||
)
|
||||
)
|
||||
4: Stmt_Function(
|
||||
attrGroups: array(
|
||||
0: AttributeGroup(
|
||||
attrs: array(
|
||||
0: Attribute(
|
||||
name: Name(
|
||||
parts: array(
|
||||
0: Foo
|
||||
)
|
||||
)
|
||||
args: array(
|
||||
0: Arg(
|
||||
name: null
|
||||
value: Expr_VariadicPlaceholder(
|
||||
)
|
||||
byRef: false
|
||||
unpack: false
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
byRef: false
|
||||
name: Identifier(
|
||||
name: foo
|
||||
)
|
||||
params: array(
|
||||
)
|
||||
returnType: null
|
||||
stmts: array(
|
||||
)
|
||||
)
|
||||
)
|
11
test/code/prettyPrinter/expr/firstClassCallables.test
Normal file
11
test/code/prettyPrinter/expr/firstClassCallables.test
Normal file
@ -0,0 +1,11 @@
|
||||
First-class callables
|
||||
-----
|
||||
<?php
|
||||
foo(...);
|
||||
$this->foo(...);
|
||||
A::foo(...);
|
||||
-----
|
||||
!!php7
|
||||
foo(...);
|
||||
$this->foo(...);
|
||||
A::foo(...);
|
Loading…
x
Reference in New Issue
Block a user