From f10d3af254672948c9f2969ea5b18452c486fffa Mon Sep 17 00:00:00 2001 From: Kyle Anderson Date: Fri, 22 May 2026 08:41:40 -0400 Subject: [PATCH] [BetterPhpDocParser] Don't wrap first-position @method param union in extra parens --- ...port_method_with_first_param_union.php.inc | 27 +++++++++++++++++++ .../UnionTypeNodePhpDocNodeVisitor.php | 12 ++++----- 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 rules-tests/CodingStyle/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_method_with_first_param_union.php.inc diff --git a/rules-tests/CodingStyle/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_method_with_first_param_union.php.inc b/rules-tests/CodingStyle/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_method_with_first_param_union.php.inc new file mode 100644 index 00000000000..72a81738181 --- /dev/null +++ b/rules-tests/CodingStyle/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_method_with_first_param_union.php.inc @@ -0,0 +1,27 @@ + +----- + diff --git a/src/BetterPhpDocParser/PhpDocNodeVisitor/UnionTypeNodePhpDocNodeVisitor.php b/src/BetterPhpDocParser/PhpDocNodeVisitor/UnionTypeNodePhpDocNodeVisitor.php index a8cf43ee537..7b0aaec4cfd 100644 --- a/src/BetterPhpDocParser/PhpDocNodeVisitor/UnionTypeNodePhpDocNodeVisitor.php +++ b/src/BetterPhpDocParser/PhpDocNodeVisitor/UnionTypeNodePhpDocNodeVisitor.php @@ -58,13 +58,13 @@ public function enterNode(Node $node): ?Node private function isWrappedInCurlyBrackets(BetterTokenIterator $betterTokenProvider, StartAndEnd $startAndEnd): bool { $previousPosition = $startAndEnd->getStart() - 1; + $nextPosition = $startAndEnd->getEnd() + 1; - if ($betterTokenProvider->isTokenTypeOnPosition(Lexer::TOKEN_OPEN_PARENTHESES, $previousPosition)) { - return true; - } - - // there is no + 1, as end is right at the next token - return $betterTokenProvider->isTokenTypeOnPosition(Lexer::TOKEN_CLOSE_PARENTHESES, $startAndEnd->getEnd()); + // A union is wrapped only when BOTH parens flank it. Either alone may be unrelated — + // e.g. an `@method`'s parameter-list `(` before a first-position union, or the matching + // `)` after a last-position union — neither belongs to the union type itself. + return $betterTokenProvider->isTokenTypeOnPosition(Lexer::TOKEN_OPEN_PARENTHESES, $previousPosition) + && $betterTokenProvider->isTokenTypeOnPosition(Lexer::TOKEN_CLOSE_PARENTHESES, $nextPosition); } private function resolveStartAndEnd(UnionTypeNode $unionTypeNode): ?StartAndEnd