Skip to content

Commit

Permalink
Properly handle new/instanceof operand restrictions
Browse files Browse the repository at this point in the history
Fixes #912.
  • Loading branch information
nikic committed Feb 26, 2023
1 parent d24745d commit 1eb6b56
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
13 changes: 8 additions & 5 deletions lib/PhpParser/PrettyPrinter/Standard.php
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ protected function pExpr_Instanceof(Expr\Instanceof_ $node): string {
list($precedence, $associativity) = $this->precedenceMap[Expr\Instanceof_::class];
return $this->pPrec($node->expr, $precedence, $associativity, -1)
. ' instanceof '
. $this->pNewVariable($node->class);
. $this->pNewOperand($node->class);
}

// Unary expressions
Expand Down Expand Up @@ -671,7 +671,7 @@ protected function pExpr_New(Expr\New_ $node): string {
$args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : '';
return 'new ' . $this->pClassCommon($node->class, $args);
}
return 'new ' . $this->pNewVariable($node->class)
return 'new ' . $this->pNewOperand($node->class)
. '(' . $this->pMaybeMultiline($node->args) . ')';
}

Expand Down Expand Up @@ -1086,9 +1086,12 @@ protected function pCallLhs(Node $node): string {
}
}

protected function pNewVariable(Node $node): string {
// TODO: This is not fully accurate.
return $this->pDereferenceLhs($node);
protected function pNewOperand(Node $node): string {
if (!$this->newOperandRequiresParens($node)) {
return $this->p($node);
} else {
return '(' . $this->p($node) . ')';
}
}

/**
Expand Down
16 changes: 16 additions & 0 deletions lib/PhpParser/PrettyPrinterAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,22 @@ protected function dereferenceLhsRequiresParens(Node $node): bool {
|| $node instanceof Expr\ClassConstFetch);
}

/**
* Determines whether an expression used in "new" or "instanceof" requires parentheses.
*
* @param Node $node New or instanceof operand
*
* @return bool Whether parentheses are required
*/
protected function newOperandRequiresParens(Node $node): bool {
return !($node instanceof Node\Name
|| $node instanceof Expr\Variable
|| $node instanceof Expr\ArrayDimFetch
|| $node instanceof Expr\PropertyFetch
|| $node instanceof Expr\NullsafePropertyFetch
|| $node instanceof Expr\StaticPropertyFetch);
}

/**
* Print modifiers, including trailing whitespace.
*
Expand Down
8 changes: 7 additions & 1 deletion test/code/prettyPrinter/expr/newVariable.test
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ Parentheses for complex new/instanceof expressions
-----
<?php
new ('a' . 'b');
new (x);
new (foo());
new ('foo');
$x instanceof ('a' . 'b');
$x instanceof ($y++);
-----
new ('a' . 'b')();
new (x)();
new (foo())();
new ('foo')();
$x instanceof ('a' . 'b');
$x instanceof ($y++);
$x instanceof ($y++);

0 comments on commit 1eb6b56

Please sign in to comment.