mirror of
https://github.com/phabelio/PHP-Parser.git
synced 2024-11-30 04:29:15 +01:00
Add support for nullsafe operator
This commit is contained in:
parent
31be7b4ed9
commit
23d9c17770
@ -943,6 +943,8 @@ callable_variable:
|
||||
| function_call { $$ = $1; }
|
||||
| array_object_dereferencable T_OBJECT_OPERATOR property_name argument_list
|
||||
{ $$ = Expr\MethodCall[$1, $3, $4]; }
|
||||
| array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list
|
||||
{ $$ = Expr\NullsafeMethodCall[$1, $3, $4]; }
|
||||
;
|
||||
|
||||
optional_plain_variable:
|
||||
@ -955,6 +957,8 @@ variable:
|
||||
| static_member { $$ = $1; }
|
||||
| array_object_dereferencable T_OBJECT_OPERATOR property_name
|
||||
{ $$ = Expr\PropertyFetch[$1, $3]; }
|
||||
| array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name
|
||||
{ $$ = Expr\NullsafePropertyFetch[$1, $3]; }
|
||||
;
|
||||
|
||||
simple_variable:
|
||||
@ -979,6 +983,7 @@ new_variable:
|
||||
| new_variable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||
| new_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||
| new_variable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; }
|
||||
| new_variable T_NULLSAFE_OBJECT_OPERATOR property_name { $$ = Expr\NullsafePropertyFetch[$1, $3]; }
|
||||
| class_name T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name
|
||||
{ $$ = Expr\StaticPropertyFetch[$1, $3]; }
|
||||
| new_variable T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name
|
||||
@ -1048,6 +1053,7 @@ encaps_var:
|
||||
plain_variable { $$ = $1; }
|
||||
| plain_variable '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; }
|
||||
| plain_variable T_OBJECT_OPERATOR identifier { $$ = Expr\PropertyFetch[$1, $3]; }
|
||||
| plain_variable T_NULLSAFE_OBJECT_OPERATOR identifier { $$ = Expr\NullsafePropertyFetch[$1, $3]; }
|
||||
| T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; }
|
||||
| T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; }
|
||||
| T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}'
|
||||
|
@ -85,6 +85,7 @@
|
||||
%token T_EXTENDS
|
||||
%token T_IMPLEMENTS
|
||||
%token T_OBJECT_OPERATOR
|
||||
%token T_NULLSAFE_OBJECT_OPERATOR
|
||||
%token T_DOUBLE_ARROW
|
||||
%token T_LIST
|
||||
%token T_ARRAY
|
||||
|
@ -428,6 +428,9 @@ class Lexer
|
||||
if (!defined('T_MATCH')) {
|
||||
\define('T_MATCH', -7);
|
||||
}
|
||||
if (!defined('T_NULLSAFE_OBJECT_OPERATOR')) {
|
||||
\define('T_NULLSAFE_OBJECT_OPERATOR', -8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -481,6 +484,7 @@ class Lexer
|
||||
$tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED;
|
||||
$tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE;
|
||||
$tokenMap[\T_MATCH] = Tokens::T_MATCH;
|
||||
$tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR;
|
||||
|
||||
return $tokenMap;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use PhpParser\Lexer;
|
||||
use PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\MatchTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\TokenEmulatorInterface;
|
||||
use PhpParser\Parser\Tokens;
|
||||
@ -49,6 +50,7 @@ REGEX;
|
||||
$this->tokenEmulators[] = new MatchTokenEmulator();
|
||||
$this->tokenEmulators[] = new CoaleseEqualTokenEmulator();
|
||||
$this->tokenEmulators[] = new NumericLiteralSeparatorEmulator();
|
||||
$this->tokenEmulators[] = new NullsafeTokenEmulator();
|
||||
}
|
||||
|
||||
public function startLexing(string $code, ErrorHandler $errorHandler = null) {
|
||||
|
47
lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php
Normal file
47
lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class NullsafeTokenEmulator implements TokenEmulatorInterface
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_8_0;
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code): bool
|
||||
{
|
||||
return strpos($code, '?->') !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
// We need to manually iterate and manage a count because we'll change
|
||||
// the tokens array on the way
|
||||
$line = 1;
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
if (isset($tokens[$i + 1])) {
|
||||
if ($tokens[$i] === '?' && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) {
|
||||
array_splice($tokens, $i, 2, [
|
||||
[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line]
|
||||
]);
|
||||
$c--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (\is_array($tokens[$i])) {
|
||||
$line += substr_count($tokens[$i][1], "\n");
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
// ?-> was not valid code previously, don't bother.
|
||||
return $tokens;
|
||||
}
|
||||
}
|
40
lib/PhpParser/Node/Expr/NullsafeMethodCall.php
Normal file
40
lib/PhpParser/Node/Expr/NullsafeMethodCall.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node\Expr;
|
||||
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Identifier;
|
||||
|
||||
class NullsafeMethodCall extends Expr
|
||||
{
|
||||
/** @var Expr Variable holding object */
|
||||
public $var;
|
||||
/** @var Identifier|Expr Method name */
|
||||
public $name;
|
||||
/** @var Arg[] Arguments */
|
||||
public $args;
|
||||
|
||||
/**
|
||||
* Constructs a nullsafe method call node.
|
||||
*
|
||||
* @param Expr $var Variable holding object
|
||||
* @param string|Identifier|Expr $name Method name
|
||||
* @param Arg[] $args Arguments
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, $name, array $args = [], array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['var', 'name', 'args'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_NullsafeMethodCall';
|
||||
}
|
||||
}
|
35
lib/PhpParser/Node/Expr/NullsafePropertyFetch.php
Normal file
35
lib/PhpParser/Node/Expr/NullsafePropertyFetch.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node\Expr;
|
||||
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Identifier;
|
||||
|
||||
class NullsafePropertyFetch extends Expr
|
||||
{
|
||||
/** @var Expr Variable holding object */
|
||||
public $var;
|
||||
/** @var Identifier|Expr Property name */
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* Constructs a nullsafe property fetch node.
|
||||
*
|
||||
* @param Expr $var Variable holding object
|
||||
* @param string|Identifier|Expr $name Property name
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, $name, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['var', 'name'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_NullsafePropertyFetch';
|
||||
}
|
||||
}
|
@ -17,11 +17,11 @@ use PhpParser\Node\Stmt;
|
||||
*/
|
||||
class Php5 extends \PhpParser\ParserAbstract
|
||||
{
|
||||
protected $tokenToSymbolMapSize = 390;
|
||||
protected $tokenToSymbolMapSize = 391;
|
||||
protected $actionTableSize = 1061;
|
||||
protected $gotoTableSize = 580;
|
||||
|
||||
protected $invalidSymbol = 163;
|
||||
protected $invalidSymbol = 164;
|
||||
protected $errorSymbol = 1;
|
||||
protected $defaultAction = -32766;
|
||||
protected $unexpectedTokenRule = 32767;
|
||||
@ -192,36 +192,37 @@ class Php5 extends \PhpParser\ParserAbstract
|
||||
"'$'",
|
||||
"'`'",
|
||||
"']'",
|
||||
"'\"'"
|
||||
"'\"'",
|
||||
"T_NULLSAFE_OBJECT_OPERATOR"
|
||||
);
|
||||
|
||||
protected $tokenToSymbol = array(
|
||||
0, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 54, 162, 163, 159, 53, 36, 163,
|
||||
157, 158, 51, 48, 7, 49, 50, 52, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 30, 154,
|
||||
42, 15, 44, 29, 66, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 68, 163, 161, 35, 163, 160, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 155, 34, 156, 56, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
|
||||
163, 163, 163, 163, 163, 163, 1, 2, 3, 4,
|
||||
0, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 54, 162, 164, 159, 53, 36, 164,
|
||||
157, 158, 51, 48, 7, 49, 50, 52, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 30, 154,
|
||||
42, 15, 44, 29, 66, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 68, 164, 161, 35, 164, 160, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 155, 34, 156, 56, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
|
||||
164, 164, 164, 164, 164, 164, 1, 2, 3, 4,
|
||||
5, 6, 8, 9, 10, 11, 12, 13, 14, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
|
||||
27, 28, 31, 32, 33, 37, 38, 39, 40, 41,
|
||||
@ -232,9 +233,10 @@ class Php5 extends \PhpParser\ParserAbstract
|
||||
94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
|
||||
104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
|
||||
114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
|
||||
124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
|
||||
134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153
|
||||
124, 125, 126, 127, 128, 129, 130, 131, 163, 132,
|
||||
133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
|
||||
143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
|
||||
153
|
||||
);
|
||||
|
||||
protected $action = array(
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -117,26 +117,27 @@ final class Tokens
|
||||
const T_EXTENDS = 365;
|
||||
const T_IMPLEMENTS = 366;
|
||||
const T_OBJECT_OPERATOR = 367;
|
||||
const T_LIST = 368;
|
||||
const T_ARRAY = 369;
|
||||
const T_CALLABLE = 370;
|
||||
const T_CLASS_C = 371;
|
||||
const T_TRAIT_C = 372;
|
||||
const T_METHOD_C = 373;
|
||||
const T_FUNC_C = 374;
|
||||
const T_LINE = 375;
|
||||
const T_FILE = 376;
|
||||
const T_START_HEREDOC = 377;
|
||||
const T_END_HEREDOC = 378;
|
||||
const T_DOLLAR_OPEN_CURLY_BRACES = 379;
|
||||
const T_CURLY_OPEN = 380;
|
||||
const T_PAAMAYIM_NEKUDOTAYIM = 381;
|
||||
const T_NAMESPACE = 382;
|
||||
const T_NS_C = 383;
|
||||
const T_DIR = 384;
|
||||
const T_NS_SEPARATOR = 385;
|
||||
const T_ELLIPSIS = 386;
|
||||
const T_NAME_FULLY_QUALIFIED = 387;
|
||||
const T_NAME_QUALIFIED = 388;
|
||||
const T_NAME_RELATIVE = 389;
|
||||
const T_NULLSAFE_OBJECT_OPERATOR = 368;
|
||||
const T_LIST = 369;
|
||||
const T_ARRAY = 370;
|
||||
const T_CALLABLE = 371;
|
||||
const T_CLASS_C = 372;
|
||||
const T_TRAIT_C = 373;
|
||||
const T_METHOD_C = 374;
|
||||
const T_FUNC_C = 375;
|
||||
const T_LINE = 376;
|
||||
const T_FILE = 377;
|
||||
const T_START_HEREDOC = 378;
|
||||
const T_END_HEREDOC = 379;
|
||||
const T_DOLLAR_OPEN_CURLY_BRACES = 380;
|
||||
const T_CURLY_OPEN = 381;
|
||||
const T_PAAMAYIM_NEKUDOTAYIM = 382;
|
||||
const T_NAMESPACE = 383;
|
||||
const T_NS_C = 384;
|
||||
const T_DIR = 385;
|
||||
const T_NS_SEPARATOR = 386;
|
||||
const T_ELLIPSIS = 387;
|
||||
const T_NAME_FULLY_QUALIFIED = 388;
|
||||
const T_NAME_QUALIFIED = 389;
|
||||
const T_NAME_RELATIVE = 390;
|
||||
}
|
||||
|
@ -492,6 +492,11 @@ class Standard extends PrettyPrinterAbstract
|
||||
. '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
}
|
||||
|
||||
protected function pExpr_NullsafeMethodCall(Expr\NUllsafeMethodCall $node) {
|
||||
return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name)
|
||||
. '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
}
|
||||
|
||||
protected function pExpr_StaticCall(Expr\StaticCall $node) {
|
||||
return $this->pDereferenceLhs($node->class) . '::'
|
||||
. ($node->name instanceof Expr
|
||||
@ -577,6 +582,10 @@ class Standard extends PrettyPrinterAbstract
|
||||
return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name);
|
||||
}
|
||||
|
||||
protected function pExpr_NullsafePropertyFetch(Expr\NullsafePropertyFetch $node) {
|
||||
return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name);
|
||||
}
|
||||
|
||||
protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) {
|
||||
return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name);
|
||||
}
|
||||
|
@ -999,6 +999,7 @@ abstract class PrettyPrinterAbstract
|
||||
|| $node instanceof Expr\ArrayDimFetch
|
||||
|| $node instanceof Expr\FuncCall
|
||||
|| $node instanceof Expr\MethodCall
|
||||
|| $node instanceof Expr\NullsafeMethodCall
|
||||
|| $node instanceof Expr\StaticCall
|
||||
|| $node instanceof Expr\Array_);
|
||||
}
|
||||
@ -1015,9 +1016,11 @@ abstract class PrettyPrinterAbstract
|
||||
|| $node instanceof Node\Name
|
||||
|| $node instanceof Expr\ArrayDimFetch
|
||||
|| $node instanceof Expr\PropertyFetch
|
||||
|| $node instanceof Expr\NullsafePropertyFetch
|
||||
|| $node instanceof Expr\StaticPropertyFetch
|
||||
|| $node instanceof Expr\FuncCall
|
||||
|| $node instanceof Expr\MethodCall
|
||||
|| $node instanceof Expr\NullsafeMethodCall
|
||||
|| $node instanceof Expr\StaticCall
|
||||
|| $node instanceof Expr\Array_
|
||||
|| $node instanceof Scalar\String_
|
||||
@ -1138,6 +1141,10 @@ abstract class PrettyPrinterAbstract
|
||||
'var' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_BRACED_NAME,
|
||||
],
|
||||
Expr\NullsafeMethodCall::class => [
|
||||
'var' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_BRACED_NAME,
|
||||
],
|
||||
Expr\StaticPropertyFetch::class => [
|
||||
'class' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_VAR_BRACED_NAME,
|
||||
@ -1146,6 +1153,10 @@ abstract class PrettyPrinterAbstract
|
||||
'var' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_BRACED_NAME,
|
||||
],
|
||||
Expr\NullsafePropertyFetch::class => [
|
||||
'var' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_BRACED_NAME,
|
||||
],
|
||||
Scalar\Encapsed::class => [
|
||||
'parts' => self::FIXUP_ENCAPSED,
|
||||
],
|
||||
@ -1303,6 +1314,7 @@ abstract class PrettyPrinterAbstract
|
||||
'Expr_Isset->vars' => ', ',
|
||||
'Expr_List->items' => ', ',
|
||||
'Expr_MethodCall->args' => ', ',
|
||||
'Expr_NullsafeMethodCall->args' => ', ',
|
||||
'Expr_New->args' => ', ',
|
||||
'Expr_PrintableNewAnonClass->args' => ', ',
|
||||
'Expr_StaticCall->args' => ', ',
|
||||
@ -1370,6 +1382,7 @@ abstract class PrettyPrinterAbstract
|
||||
'Expr_Closure->params' => ['(', '', ''],
|
||||
'Expr_FuncCall->args' => ['(', '', ''],
|
||||
'Expr_MethodCall->args' => ['(', '', ''],
|
||||
'Expr_NullsafeMethodCall->args' => ['(', '', ''],
|
||||
'Expr_New->args' => ['(', '', ''],
|
||||
'Expr_PrintableNewAnonClass->args' => ['(', '', ''],
|
||||
'Expr_PrintableNewAnonClass->implements' => [null, ' implements ', ''],
|
||||
|
@ -48,6 +48,18 @@ class EmulativeTest extends LexerTest
|
||||
$this->assertSame(0, $lexer->getNextToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideTestReplaceKeywords
|
||||
*/
|
||||
public function testNoReplaceKeywordsAfterNullsafeObjectOperator(string $keyword) {
|
||||
$lexer = $this->getLexer();
|
||||
$lexer->startLexing('<?php ?->' . $keyword);
|
||||
|
||||
$this->assertSame(Tokens::T_NULLSAFE_OBJECT_OPERATOR, $lexer->getNextToken());
|
||||
$this->assertSame(Tokens::T_STRING, $lexer->getNextToken());
|
||||
$this->assertSame(0, $lexer->getNextToken());
|
||||
}
|
||||
|
||||
public function provideTestReplaceKeywords() {
|
||||
return [
|
||||
// PHP 8.0
|
||||
@ -260,6 +272,9 @@ class EmulativeTest extends LexerTest
|
||||
[Tokens::T_LNUMBER, '1_0'],
|
||||
[Tokens::T_STRING, 'abc'],
|
||||
]],
|
||||
['?->', [
|
||||
[Tokens::T_NULLSAFE_OBJECT_OPERATOR, '?->'],
|
||||
]],
|
||||
];
|
||||
}
|
||||
|
||||
|
82
test/code/parser/expr/nullsafe.test
Normal file
82
test/code/parser/expr/nullsafe.test
Normal file
@ -0,0 +1,82 @@
|
||||
Nullsafe operator
|
||||
-----
|
||||
<?php
|
||||
|
||||
$a?->b;
|
||||
$a?->b($c);
|
||||
new $a?->b;
|
||||
"{$a?->b}";
|
||||
"$a?->b";
|
||||
-----
|
||||
!!php7
|
||||
array(
|
||||
0: Stmt_Expression(
|
||||
expr: Expr_NullsafePropertyFetch(
|
||||
var: Expr_Variable(
|
||||
name: a
|
||||
)
|
||||
name: Identifier(
|
||||
name: b
|
||||
)
|
||||
)
|
||||
)
|
||||
1: Stmt_Expression(
|
||||
expr: Expr_NullsafeMethodCall(
|
||||
var: Expr_Variable(
|
||||
name: a
|
||||
)
|
||||
name: Identifier(
|
||||
name: b
|
||||
)
|
||||
args: array(
|
||||
0: Arg(
|
||||
value: Expr_Variable(
|
||||
name: c
|
||||
)
|
||||
byRef: false
|
||||
unpack: false
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
2: Stmt_Expression(
|
||||
expr: Expr_New(
|
||||
class: Expr_NullsafePropertyFetch(
|
||||
var: Expr_Variable(
|
||||
name: a
|
||||
)
|
||||
name: Identifier(
|
||||
name: b
|
||||
)
|
||||
)
|
||||
args: array(
|
||||
)
|
||||
)
|
||||
)
|
||||
3: Stmt_Expression(
|
||||
expr: Scalar_Encapsed(
|
||||
parts: array(
|
||||
0: Expr_NullsafePropertyFetch(
|
||||
var: Expr_Variable(
|
||||
name: a
|
||||
)
|
||||
name: Identifier(
|
||||
name: b
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
4: Stmt_Expression(
|
||||
expr: Scalar_Encapsed(
|
||||
parts: array(
|
||||
0: Expr_Variable(
|
||||
name: a
|
||||
)
|
||||
1: Scalar_EncapsedStringPart(
|
||||
value: ?->b
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
22
test/code/prettyPrinter/expr/nullsafe.test
Normal file
22
test/code/prettyPrinter/expr/nullsafe.test
Normal file
@ -0,0 +1,22 @@
|
||||
Nullsafe operator
|
||||
-----
|
||||
<?php
|
||||
|
||||
$a?->b;
|
||||
$a?->b($c);
|
||||
$a?->b?->c;
|
||||
$a?->b($c)?->d;
|
||||
$a?->b($c)();
|
||||
new $a?->b;
|
||||
"{$a?->b}";
|
||||
"$a?->b";
|
||||
-----
|
||||
!!php7
|
||||
$a?->b;
|
||||
$a?->b($c);
|
||||
$a?->b?->c;
|
||||
$a?->b($c)?->d;
|
||||
$a?->b($c)();
|
||||
new $a?->b();
|
||||
"{$a?->b}";
|
||||
"{$a}?->b";
|
Loading…
Reference in New Issue
Block a user