mirror of
https://github.com/nikic/PHP-Parser.git
synced 2025-04-20 22:12:25 +02:00
Properly handle static deref LHS
The rules for static and array/object deref are slightly different: The former does not allow constants. (cherry picked from commit 7b4a8c1ebd09fd6f6ccc33d7193df0f75e7e28d7)
This commit is contained in:
parent
8f8e47b6c1
commit
21a61ece15
@ -529,7 +529,7 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pExpr_StaticCall(Expr\StaticCall $node) {
|
||||
return $this->pDereferenceLhs($node->class) . '::'
|
||||
return $this->pStaticDereferenceLhs($node->class) . '::'
|
||||
. ($node->name instanceof Expr
|
||||
? ($node->name instanceof Expr\Variable
|
||||
? $this->p($node->name)
|
||||
@ -606,7 +606,7 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) {
|
||||
return $this->pDereferenceLhs($node->class) . '::' . $this->pObjectProperty($node->name);
|
||||
return $this->pStaticDereferenceLhs($node->class) . '::' . $this->pObjectProperty($node->name);
|
||||
}
|
||||
|
||||
protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) {
|
||||
@ -618,7 +618,7 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) {
|
||||
return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name);
|
||||
return $this->pStaticDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name);
|
||||
}
|
||||
|
||||
protected function pExpr_ShellExec(Expr\ShellExec $node) {
|
||||
@ -1069,6 +1069,14 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
}
|
||||
|
||||
protected function pStaticDereferenceLhs(Node $node) {
|
||||
if (!$this->staticDereferenceLhsRequiresParens($node)) {
|
||||
return $this->p($node);
|
||||
} else {
|
||||
return '(' . $this->p($node) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
protected function pCallLhs(Node $node) {
|
||||
if (!$this->callLhsRequiresParens($node)) {
|
||||
return $this->p($node);
|
||||
|
@ -22,6 +22,7 @@ abstract class PrettyPrinterAbstract
|
||||
const FIXUP_VAR_BRACED_NAME = 5; // Name operand that may require ${} bracing
|
||||
const FIXUP_ENCAPSED = 6; // Encapsed string part
|
||||
const FIXUP_NEW = 7; // New/instanceof operand
|
||||
const FIXUP_STATIC_DEREF_LHS = 8; // LHS of static dereferencing operation
|
||||
|
||||
protected $precedenceMap = [
|
||||
// [precedence, associativity]
|
||||
@ -978,6 +979,13 @@ abstract class PrettyPrinterAbstract
|
||||
return '(' . $this->p($subNode) . ')';
|
||||
}
|
||||
break;
|
||||
case self::FIXUP_STATIC_DEREF_LHS:
|
||||
if ($this->staticDereferenceLhsRequiresParens($subNode)
|
||||
&& !$this->origTokens->haveParens($subStartPos, $subEndPos)
|
||||
) {
|
||||
return '(' . $this->p($subNode) . ')';
|
||||
}
|
||||
break;
|
||||
case self::FIXUP_NEW:
|
||||
if ($this->newOperandRequiresParens($subNode)
|
||||
&& !$this->origTokens->haveParens($subStartPos, $subEndPos)) {
|
||||
@ -1054,13 +1062,26 @@ abstract class PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the LHS of a dereferencing operation must be wrapped in parenthesis.
|
||||
* Determines whether the LHS of an array/object operation must be wrapped in parentheses.
|
||||
*
|
||||
* @param Node $node LHS of dereferencing operation
|
||||
*
|
||||
* @return bool Whether parentheses are required
|
||||
*/
|
||||
protected function dereferenceLhsRequiresParens(Node $node) : bool {
|
||||
// A constant can occur on the LHS of an array/object deref, but not a static deref.
|
||||
return $this->staticDereferenceLhsRequiresParens($node)
|
||||
&& !$node instanceof Expr\ConstFetch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the LHS of a static operation must be wrapped in parentheses.
|
||||
*
|
||||
* @param Node $node LHS of dereferencing operation
|
||||
*
|
||||
* @return bool Whether parentheses are required
|
||||
*/
|
||||
protected function staticDereferenceLhsRequiresParens(Node $node): bool {
|
||||
return !($node instanceof Expr\Variable
|
||||
|| $node instanceof Node\Name
|
||||
|| $node instanceof Expr\ArrayDimFetch
|
||||
@ -1073,7 +1094,6 @@ abstract class PrettyPrinterAbstract
|
||||
|| $node instanceof Expr\StaticCall
|
||||
|| $node instanceof Expr\Array_
|
||||
|| $node instanceof Scalar\String_
|
||||
|| $node instanceof Expr\ConstFetch
|
||||
|| $node instanceof Expr\ClassConstFetch);
|
||||
}
|
||||
|
||||
@ -1208,9 +1228,9 @@ abstract class PrettyPrinterAbstract
|
||||
],
|
||||
|
||||
Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS],
|
||||
Expr\StaticCall::class => ['class' => self::FIXUP_DEREF_LHS],
|
||||
Expr\StaticCall::class => ['class' => self::FIXUP_STATIC_DEREF_LHS],
|
||||
Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS],
|
||||
Expr\ClassConstFetch::class => ['var' => self::FIXUP_DEREF_LHS],
|
||||
Expr\ClassConstFetch::class => ['class' => self::FIXUP_STATIC_DEREF_LHS],
|
||||
Expr\New_::class => ['class' => self::FIXUP_NEW],
|
||||
Expr\MethodCall::class => [
|
||||
'var' => self::FIXUP_DEREF_LHS,
|
||||
@ -1221,7 +1241,7 @@ abstract class PrettyPrinterAbstract
|
||||
'name' => self::FIXUP_BRACED_NAME,
|
||||
],
|
||||
Expr\StaticPropertyFetch::class => [
|
||||
'class' => self::FIXUP_DEREF_LHS,
|
||||
'class' => self::FIXUP_STATIC_DEREF_LHS,
|
||||
'name' => self::FIXUP_VAR_BRACED_NAME,
|
||||
],
|
||||
Expr\PropertyFetch::class => [
|
||||
|
@ -44,6 +44,9 @@ self :: $foo;
|
||||
self :: $foo;
|
||||
new Foo();
|
||||
$x instanceof Foo;
|
||||
Foo :: bar;
|
||||
Foo :: $bar;
|
||||
Foo :: bar();
|
||||
-----
|
||||
$stmts[0]->expr->name = new Expr\Variable('a');
|
||||
$stmts[1]->expr->name = new Expr\BinaryOp\Concat(new Expr\Variable('a'), new Expr\Variable('b'));
|
||||
@ -58,6 +61,9 @@ $stmts[7]->expr->name = new Node\VarLikeIdentifier('bar');
|
||||
$stmts[8]->expr->name = new Expr\BinaryOp\Concat(new Expr\Variable('a'), new Expr\Variable('b'));
|
||||
$stmts[9]->expr->class = new Scalar\String_('Foo');
|
||||
$stmts[10]->expr->class = new Scalar\String_('Foo');
|
||||
$stmts[11]->expr->class = new Expr\ConstFetch(new Node\Name('FOO'));
|
||||
$stmts[12]->expr->class = new Expr\ConstFetch(new Node\Name('FOO'));
|
||||
$stmts[13]->expr->class = new Expr\ConstFetch(new Node\Name('FOO'));
|
||||
-----
|
||||
<?php
|
||||
$a ();
|
||||
@ -71,3 +77,6 @@ self :: $bar;
|
||||
self :: ${$a . $b};
|
||||
new ('Foo')();
|
||||
$x instanceof ('Foo');
|
||||
(FOO) :: bar;
|
||||
(FOO) :: $bar;
|
||||
(FOO) :: bar();
|
||||
|
@ -18,6 +18,6 @@ new (foo())();
|
||||
new ('foo')();
|
||||
new (x[0])();
|
||||
new (x->y)();
|
||||
new (x::$y)();
|
||||
new ((x)::$y)();
|
||||
$x instanceof ('a' . 'b');
|
||||
$x instanceof ($y++);
|
||||
|
@ -11,6 +11,9 @@ A::$$b[$c]();
|
||||
($a->b)();
|
||||
(A::$b)();
|
||||
('a' . 'b')::X;
|
||||
(A)::X;
|
||||
(A)::$x;
|
||||
(A)::x();
|
||||
-----
|
||||
!!php7
|
||||
(function () {
|
||||
@ -22,4 +25,7 @@ $A::{$b[$c]}();
|
||||
A::${$b}[$c]();
|
||||
($a->b)();
|
||||
(A::$b)();
|
||||
('a' . 'b')::X;
|
||||
('a' . 'b')::X;
|
||||
(A)::X;
|
||||
(A)::$x;
|
||||
(A)::x();
|
||||
|
Loading…
x
Reference in New Issue
Block a user