Skip to content

Commit 20b0d55

Browse files
committed
Use multi-line attributes for params when targeting PHP <8.0
When the pretty printer targets a version older than PHP 8, print the attributes for parameters on a separate line, so that they are interpreted as comments. Fixes #1081.
1 parent c9d0b6c commit 20b0d55

File tree

5 files changed

+63
-12
lines changed

5 files changed

+63
-12
lines changed

lib/PhpParser/PhpVersion.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,11 @@ public function supportsYieldWithoutParentheses(): bool {
161161
public function supportsUnicodeEscapes(): bool {
162162
return $this->id >= 70000;
163163
}
164+
165+
/*
166+
* Whether this version supports attributes.
167+
*/
168+
public function supportsAttributes(): bool {
169+
return $this->id >= 80000;
170+
}
164171
}

lib/PhpParser/PrettyPrinter/Standard.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Standard extends PrettyPrinterAbstract {
1717
// Special nodes
1818

1919
protected function pParam(Node\Param $node): string {
20-
return $this->pAttrGroups($node->attrGroups, true)
20+
return $this->pAttrGroups($node->attrGroups, $this->phpVersion->supportsAttributes())
2121
. $this->pModifiers($node->flags)
2222
. ($node->type ? $this->p($node->type) . ' ' : '')
2323
. ($node->byRef ? '&' : '')
@@ -656,7 +656,7 @@ protected function pExpr_Closure(Expr\Closure $node): string {
656656
return $this->pAttrGroups($node->attrGroups, true)
657657
. $this->pStatic($node->static)
658658
. 'function ' . ($node->byRef ? '&' : '')
659-
. '(' . $this->pMaybeMultiline($node->params, $this->phpVersion->supportsTrailingCommaInParamList()) . ')'
659+
. '(' . $this->pParams($node->params) . ')'
660660
. (!empty($node->uses) ? ' use (' . $this->pCommaSeparated($node->uses) . ')' : '')
661661
. (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '')
662662
. ' {' . $this->pStmts($node->stmts) . $this->nl . '}';
@@ -688,7 +688,7 @@ protected function pExpr_ArrowFunction(Expr\ArrowFunction $node, int $precedence
688688
$this->pAttrGroups($node->attrGroups, true)
689689
. $this->pStatic($node->static)
690690
. 'fn' . ($node->byRef ? '&' : '')
691-
. '(' . $this->pMaybeMultiline($node->params, $this->phpVersion->supportsTrailingCommaInParamList()) . ')'
691+
. '(' . $this->pParams($node->params) . ')'
692692
. (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '')
693693
. ' => ',
694694
$node->expr, $precedence, $lhsPrecedence);
@@ -845,7 +845,7 @@ protected function pPropertyHook(Node\PropertyHook $node): string {
845845
return $this->pAttrGroups($node->attrGroups)
846846
. $this->pModifiers($node->flags)
847847
. ($node->byRef ? '&' : '') . $node->name
848-
. ($node->params ? '(' . $this->pMaybeMultiline($node->params, $this->phpVersion->supportsTrailingCommaInParamList()) . ')' : '')
848+
. ($node->params ? '(' . $this->pParams($node->params) . ')' : '')
849849
. (\is_array($node->body) ? ' {' . $this->pStmts($node->body) . $this->nl . '}'
850850
: ($node->body !== null ? ' => ' . $this->p($node->body) : '') . ';');
851851
}
@@ -854,7 +854,7 @@ protected function pStmt_ClassMethod(Stmt\ClassMethod $node): string {
854854
return $this->pAttrGroups($node->attrGroups)
855855
. $this->pModifiers($node->flags)
856856
. 'function ' . ($node->byRef ? '&' : '') . $node->name
857-
. '(' . $this->pMaybeMultiline($node->params, $this->phpVersion->supportsTrailingCommaInParamList()) . ')'
857+
. '(' . $this->pParams($node->params) . ')'
858858
. (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '')
859859
. (null !== $node->stmts
860860
? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'
@@ -872,7 +872,7 @@ protected function pStmt_ClassConst(Stmt\ClassConst $node): string {
872872
protected function pStmt_Function(Stmt\Function_ $node): string {
873873
return $this->pAttrGroups($node->attrGroups)
874874
. 'function ' . ($node->byRef ? '&' : '') . $node->name
875-
. '(' . $this->pMaybeMultiline($node->params, $this->phpVersion->supportsTrailingCommaInParamList()) . ')'
875+
. '(' . $this->pParams($node->params) . ')'
876876
. (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '')
877877
. $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
878878
}
@@ -1179,6 +1179,27 @@ protected function pMaybeMultiline(array $nodes, bool $trailingComma = false): s
11791179
}
11801180
}
11811181

1182+
/** @param Node\Param[] $params
1183+
*/
1184+
private function hasParamWithAttributes(array $params): bool {
1185+
foreach ($params as $param) {
1186+
if ($param->attrGroups) {
1187+
return true;
1188+
}
1189+
}
1190+
return false;
1191+
}
1192+
1193+
/** @param Node\Param[] $params */
1194+
protected function pParams(array $params): string {
1195+
if ($this->hasNodeWithComments($params) ||
1196+
($this->hasParamWithAttributes($params) && !$this->phpVersion->supportsAttributes())
1197+
) {
1198+
return $this->pCommaSeparatedMultiline($params, $this->phpVersion->supportsTrailingCommaInParamList()) . $this->nl;
1199+
}
1200+
return $this->pCommaSeparated($params);
1201+
}
1202+
11821203
/** @param Node\AttributeGroup[] $nodes */
11831204
protected function pAttrGroups(array $nodes, bool $inline = false): string {
11841205
$result = '';

test/PhpParser/BuilderFactoryTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,10 @@ function firstMethod()
365365
* @param SomeClass And takes a parameter
366366
*/
367367
abstract public function someMethod(SomeClass $someParam);
368-
protected function anotherMethod(#[TaggedIterator('app.handlers')] $someParam = 'test')
368+
protected function anotherMethod(
369+
#[TaggedIterator('app.handlers')]
370+
$someParam = 'test'
371+
)
369372
{
370373
print $someParam;
371374
}

test/PhpParser/NodeVisitor/NameResolverTest.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,18 @@ class A extends \NS\B implements \NS\C, \NS\D
283283
public const \X\Foo C = \X\Foo::Bar;
284284
public \NS\Foo $foo {
285285
#[\NS\X]
286-
set(#[\NS\X] \NS\Bar $v) {
286+
set(
287+
#[\NS\X]
288+
\NS\Bar $v
289+
) {
287290
}
288291
}
289292
public function __construct(public \NS\Foo $bar {
290293
#[\NS\X]
291-
set(#[\NS\X] \NS\Bar $v) {
294+
set(
295+
#[\NS\X]
296+
\NS\Bar $v
297+
) {
292298
}
293299
})
294300
{
@@ -312,7 +318,10 @@ trait A
312318
{
313319
}
314320
#[\NS\X]
315-
function f(#[\NS\X] \NS\A $a): \NS\A
321+
function f(
322+
#[\NS\X]
323+
\NS\A $a
324+
): \NS\A
316325
{
317326
}
318327
function f2(array $a): array

test/code/prettyPrinter/stmt/attributes.test

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ function a()
3838
class C
3939
{
4040
#[A6]
41-
public function m(#[A7] $param)
41+
public function m(
42+
#[A7]
43+
$param
44+
)
4245
{
4346
}
4447
#[A12]
@@ -57,4 +60,12 @@ $x = #[A10] function () {
5760
$y = #[A11] fn() => 0;
5861
new #[A13] class
5962
{
60-
};
63+
};
64+
-----
65+
<?php
66+
function test(#[A] $b) {}
67+
-----
68+
!!version=8.0
69+
function test(#[A] $b)
70+
{
71+
}

0 commit comments

Comments
 (0)