currentTokenIteratorProvider = $currentTokenIteratorProvider; $this->attributeMirrorer = $attributeMirrorer; } public function enterNode(\PHPStan\PhpDocParser\Ast\Node $node) : ?\PHPStan\PhpDocParser\Ast\Node { if (!$node instanceof \PHPStan\PhpDocParser\Ast\Type\UnionTypeNode) { return null; } if ($node instanceof \Rector\BetterPhpDocParser\ValueObject\Type\BracketsAwareUnionTypeNode) { return null; } // unwrap with parent array type... $startAndEnd = $node->getAttribute(\Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey::START_AND_END); if (!$startAndEnd instanceof \Rector\BetterPhpDocParser\ValueObject\StartAndEnd) { throw new \Rector\Core\Exception\ShouldNotHappenException(); } $betterTokenProvider = $this->currentTokenIteratorProvider->provide(); $isWrappedInCurlyBrackets = $this->isWrappedInCurlyBrackets($betterTokenProvider, $startAndEnd); $bracketsAwareUnionTypeNode = new \Rector\BetterPhpDocParser\ValueObject\Type\BracketsAwareUnionTypeNode($node->types, $isWrappedInCurlyBrackets); $this->attributeMirrorer->mirror($node, $bracketsAwareUnionTypeNode); return $bracketsAwareUnionTypeNode; } private function isWrappedInCurlyBrackets(\Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator $betterTokenProvider, \Rector\BetterPhpDocParser\ValueObject\StartAndEnd $startAndEnd) : bool { $previousPosition = $startAndEnd->getStart() - 1; if ($betterTokenProvider->isTokenTypeOnPosition(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_OPEN_PARENTHESES, $previousPosition)) { return \true; } // there is no + 1, as end is right at the next token return $betterTokenProvider->isTokenTypeOnPosition(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_CLOSE_PARENTHESES, $startAndEnd->getEnd()); } }