From 4bcdf74b8b65b172417ea40b99320faacff94a24 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 21 Sep 2022 18:56:09 +0200 Subject: [PATCH] Add support for perserving formatting for static modifier change Closes GH-891. --- lib/PhpParser/PrettyPrinter/Standard.php | 4 +- lib/PhpParser/PrettyPrinterAbstract.php | 44 +++++++++---------- .../formatPreservation/arrow_function.test | 9 ++-- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/lib/PhpParser/PrettyPrinter/Standard.php b/lib/PhpParser/PrettyPrinter/Standard.php index 1f0b9074b9..dbe30a7111 100644 --- a/lib/PhpParser/PrettyPrinter/Standard.php +++ b/lib/PhpParser/PrettyPrinter/Standard.php @@ -632,7 +632,7 @@ protected function pExpr_ShellExec(Expr\ShellExec $node): string { protected function pExpr_Closure(Expr\Closure $node): string { return $this->pAttrGroups($node->attrGroups, true) - . ($node->static ? 'static ' : '') + . $this->pStatic($node->static) . 'function ' . ($node->byRef ? '&' : '') . '(' . $this->pMaybeMultiline($node->params, $this->phpVersion->supportsTrailingCommaInParamList()) . ')' . (!empty($node->uses) ? ' use (' . $this->pCommaSeparated($node->uses) . ')' : '') @@ -654,7 +654,7 @@ protected function pMatchArm(Node\MatchArm $node): string { protected function pExpr_ArrowFunction(Expr\ArrowFunction $node): string { return $this->pAttrGroups($node->attrGroups, true) - . ($node->static ? 'static ' : '') + . $this->pStatic($node->static) . 'fn' . ($node->byRef ? '&' : '') . '(' . $this->pMaybeMultiline($node->params, $this->phpVersion->supportsTrailingCommaInParamList()) . ')' . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') diff --git a/lib/PhpParser/PrettyPrinterAbstract.php b/lib/PhpParser/PrettyPrinterAbstract.php index 643801dd3f..9a513d82a4 100644 --- a/lib/PhpParser/PrettyPrinterAbstract.php +++ b/lib/PhpParser/PrettyPrinterAbstract.php @@ -139,8 +139,9 @@ abstract class PrettyPrinterAbstract { * @var array */ protected $emptyListInsertionMap; - /** @var array Map from "{$class}->{$subNode}" to token before which the modifiers - * should be reprinted. */ + /** @var array Map from "{$class}->{$subNode}" to [$printFn, $token] + * where $printFn is the function to print the modifiers and $token is the token before which + * the modifiers should be reprinted. */ protected $modifierChangeMap; /** @@ -587,23 +588,16 @@ protected function p(Node $node, bool $parentFormatPreserved = false): string { continue; } - if (is_int($subNode) && is_int($origSubNode)) { - // Check if this is a modifier change - $key = $class . '->' . $subNodeName; - if (!isset($this->modifierChangeMap[$key])) { - return $this->pFallback($fallbackNode); - } - - $findToken = $this->modifierChangeMap[$key]; - $result .= $this->pModifiers($subNode); - $pos = $this->origTokens->findRight($pos, $findToken); - continue; + // Check if this is a modifier change + $key = $class . '->' . $subNodeName; + if (!isset($this->modifierChangeMap[$key])) { + return $this->pFallback($fallbackNode); } - // If a non-node, non-array subnode changed, we don't be able to do a partial - // reconstructions, as we don't have enough offset information. Pretty print the - // whole node instead. - return $this->pFallback($fallbackNode); + [$printFn, $findToken] = $this->modifierChangeMap[$key]; + $result .= $this->$printFn($subNode); + $pos = $this->origTokens->findRight($pos, $findToken); + continue; } $extraLeft = ''; @@ -1098,6 +1092,10 @@ protected function pModifiers(int $modifiers): string { . ($modifiers & Modifiers::READONLY ? 'readonly ' : ''); } + protected function pStatic(bool $static): string { + return $static ? 'static ' : ''; + } + /** * Determine whether a list of nodes uses multiline formatting. * @@ -1520,11 +1518,13 @@ protected function initializeModifierChangeMap(): void { } $this->modifierChangeMap = [ - Stmt\ClassConst::class . '->flags' => \T_CONST, - Stmt\ClassMethod::class . '->flags' => \T_FUNCTION, - Stmt\Class_::class . '->flags' => \T_CLASS, - Stmt\Property::class . '->flags' => \T_VARIABLE, - Param::class . '->flags' => \T_VARIABLE, + Stmt\ClassConst::class . '->flags' => ['pModifiers', \T_CONST], + Stmt\ClassMethod::class . '->flags' => ['pModifiers', \T_FUNCTION], + Stmt\Class_::class . '->flags' => ['pModifiers', \T_CLASS], + Stmt\Property::class . '->flags' => ['pModifiers', \T_VARIABLE], + Param::class . '->flags' => ['pModifiers', \T_VARIABLE], + Expr\Closure::class . '->static' => ['pStatic', \T_FUNCTION], + Expr\ArrowFunction::class . '->static' => ['pStatic', \T_FN], //Stmt\TraitUseAdaptation\Alias::class . '->newModifier' => 0, // TODO ]; diff --git a/test/code/formatPreservation/arrow_function.test b/test/code/formatPreservation/arrow_function.test index eeff36f7bb..0b81e1b2e6 100644 --- a/test/code/formatPreservation/arrow_function.test +++ b/test/code/formatPreservation/arrow_function.test @@ -69,14 +69,17 @@ static fn($a) : int => $a; ----- -// TODO: Format preserving currently not supported $stmts[0]->expr->static = true; $stmts[1]->expr->static = false; ----- $a; +static fn($a) +: int +=> $a; -fn($a): int => $a; +fn($a) +: int +=> $a; -----