diff --git a/composer.json b/composer.json index 3ec3d0a8ea6..282adb25185 100644 --- a/composer.json +++ b/composer.json @@ -56,7 +56,7 @@ "ondram/ci-detector": "^4.1", "phpunit/phpunit": "^9.5", "psr/log": "^1.1", - "rector/rector": "dev-main#e219401", + "rector/rector": "dev-main#307dfa2", "symfony/doctrine-bridge": "^5.3", "symfony/framework-bundle": "^5.3", "symfony/security-bundle": "^5.3", diff --git a/packages/coding-standard/src/Fixer/Annotation/DoctrineAnnotationNestedBracketsFixer.php b/packages/coding-standard/src/Fixer/Annotation/DoctrineAnnotationNestedBracketsFixer.php index ee7038f0498..6d085744749 100644 --- a/packages/coding-standard/src/Fixer/Annotation/DoctrineAnnotationNestedBracketsFixer.php +++ b/packages/coding-standard/src/Fixer/Annotation/DoctrineAnnotationNestedBracketsFixer.php @@ -5,12 +5,14 @@ namespace Symplify\CodingStandard\Fixer\Annotation; use Doctrine\Common\Annotations\DocLexer; -use PhpCsFixer\Doctrine\Annotation\Token; +use PhpCsFixer\Doctrine\Annotation\Token as DoctrineAnnotationToken; use PhpCsFixer\Doctrine\Annotation\Tokens as DoctrineAnnotationTokens; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; +use SplFileInfo; use Symplify\CodingStandard\Fixer\AbstractSymplifyFixer; use Symplify\CodingStandard\TokenAnalyzer\DoctrineAnnotationElementAnalyzer; use Symplify\CodingStandard\TokenAnalyzer\DoctrineAnnotationNameResolver; @@ -39,7 +41,7 @@ final class DoctrineAnnotationNestedBracketsFixer extends AbstractSymplifyFixer public function __construct( private DoctrineAnnotationElementAnalyzer $doctrineAnnotationElementAnalyzer, - private DoctrineAnnotationNameResolver $annotationNameResolver, + private DoctrineAnnotationNameResolver $doctrineAnnotationNameResolver, private NamespaceUsesAnalyzer $namespaceUsesAnalyzer ) { } @@ -90,18 +92,24 @@ public function configure(array $configuration): void $this->annotationClasses = $annotationsClasses; } + /** + * @param Tokens $tokens + */ public function isCandidate(Tokens $tokens): bool { return $tokens->isTokenKindFound(T_DOC_COMMENT); } - public function fix(\SplFileInfo $fileInfo, Tokens $tokens): void + /** + * @param Tokens $tokens + */ + public function fix(SplFileInfo $fileInfo, Tokens $tokens): void { $useDeclarations = $this->namespaceUsesAnalyzer->getDeclarationsFromTokens($tokens); // fetch indexes one time, this is safe as we never add or remove a token during fixing - /** @var \PhpCsFixer\Tokenizer\Token[] $docCommentTokens */ + /** @var Token[] $docCommentTokens */ $docCommentTokens = $tokens->findGivenKind(T_DOC_COMMENT); foreach ($docCommentTokens as $index => $docCommentToken) { if (! $this->doctrineAnnotationElementAnalyzer->detect($tokens, $index)) { @@ -111,22 +119,26 @@ public function fix(\SplFileInfo $fileInfo, Tokens $tokens): void $doctrineAnnotationTokens = DoctrineAnnotationTokens::createFromDocComment($docCommentToken, []); $this->fixAnnotations($doctrineAnnotationTokens, $useDeclarations); - $tokens[$index] = new \PhpCsFixer\Tokenizer\Token([T_DOC_COMMENT, $doctrineAnnotationTokens->getCode()]); + $tokens[$index] = new Token([T_DOC_COMMENT, $doctrineAnnotationTokens->getCode()]); } } /** - * @param DoctrineAnnotationTokens $tokens + * @param DoctrineAnnotationTokens $doctrineAnnotationTokens */ - private function fixAnnotations(DoctrineAnnotationTokens $tokens, $useDeclarations): void + private function fixAnnotations(DoctrineAnnotationTokens $doctrineAnnotationTokens, $useDeclarations): void { - foreach ($tokens as $index => $token) { - $isAtToken = $tokens[$index]->isType(DocLexer::T_AT); + foreach ($doctrineAnnotationTokens as $index => $token) { + $isAtToken = $doctrineAnnotationTokens[$index]->isType(DocLexer::T_AT); if (! $isAtToken) { continue; } - $annotationName = $this->annotationNameResolver->resolveName($tokens, $index, $useDeclarations); + $annotationName = $this->doctrineAnnotationNameResolver->resolveName( + $doctrineAnnotationTokens, + $index, + $useDeclarations + ); if ($annotationName === null) { continue; } @@ -135,31 +147,37 @@ private function fixAnnotations(DoctrineAnnotationTokens $tokens, $useDeclaratio continue; } - $closingBraceIndex = $tokens->getAnnotationEnd($index); + $closingBraceIndex = $doctrineAnnotationTokens->getAnnotationEnd($index); if ($closingBraceIndex === null) { continue; } - $braceIndex = $tokens->getNextMeaningfulToken($index + 1); + $braceIndex = $doctrineAnnotationTokens->getNextMeaningfulToken($index + 1); if ($braceIndex === null) { continue; } - /** @var Token $braceToken */ - $braceToken = $tokens[$braceIndex]; + /** @var DoctrineAnnotationToken $braceToken */ + $braceToken = $doctrineAnnotationTokens[$braceIndex]; if (! $this->doctrineAnnotationElementAnalyzer->isOpeningBracketFollowedByAnnotation( $braceToken, - $tokens, + $doctrineAnnotationTokens, $braceIndex )) { continue; } // add closing brace - $tokens->insertAt($closingBraceIndex, new Token(DocLexer::T_OPEN_CURLY_BRACES, '}')); + $doctrineAnnotationTokens->insertAt( + $closingBraceIndex, + new DoctrineAnnotationToken(DocLexer::T_OPEN_CURLY_BRACES, '}') + ); // add opening brace - $tokens->insertAt($braceIndex + 1, new Token(DocLexer::T_OPEN_CURLY_BRACES, '{')); + $doctrineAnnotationTokens->insertAt( + $braceIndex + 1, + new DoctrineAnnotationToken(DocLexer::T_OPEN_CURLY_BRACES, '{') + ); } } } diff --git a/packages/coding-standard/src/TokenAnalyzer/DoctrineAnnotationElementAnalyzer.php b/packages/coding-standard/src/TokenAnalyzer/DoctrineAnnotationElementAnalyzer.php index 6d51b46ed2c..754d498494f 100644 --- a/packages/coding-standard/src/TokenAnalyzer/DoctrineAnnotationElementAnalyzer.php +++ b/packages/coding-standard/src/TokenAnalyzer/DoctrineAnnotationElementAnalyzer.php @@ -17,10 +17,13 @@ */ final class DoctrineAnnotationElementAnalyzer { + /** + * @param Tokens<\PhpCsFixer\Tokenizer\Token> $tokens + */ public function detect(Tokens $tokens, int $index): bool { - $analyzer = new TokensAnalyzer($tokens); - $classyElements = $analyzer->getClassyElements(); + $tokensAnalyzer = new TokensAnalyzer($tokens); + $classyElements = $tokensAnalyzer->getClassyElements(); do { $index = $tokens->getNextMeaningfulToken($index); @@ -49,11 +52,11 @@ public function detect(Tokens $tokens, int $index): bool /** * We look for "(@SomeAnnotation" * - * @param DoctrineAnnotationTokens $tokens + * @param DoctrineAnnotationTokens $doctrineAnnotationTokens */ public function isOpeningBracketFollowedByAnnotation( Token $token, - DoctrineAnnotationTokens $tokens, + DoctrineAnnotationTokens $doctrineAnnotationTokens, int $braceIndex ): bool { // should be "(" @@ -62,13 +65,13 @@ public function isOpeningBracketFollowedByAnnotation( return false; } - $nextTokenIndex = $tokens->getNextMeaningfulToken($braceIndex + 1); + $nextTokenIndex = $doctrineAnnotationTokens->getNextMeaningfulToken($braceIndex); if ($nextTokenIndex === null) { return false; } /** @var Token $nextToken */ - $nextToken = $tokens[$nextTokenIndex]; + $nextToken = $doctrineAnnotationTokens[$nextTokenIndex]; // next token must be nested annotation, we don't care otherwise return $nextToken->isType(DocLexer::T_AT); diff --git a/packages/coding-standard/src/TokenAnalyzer/DoctrineAnnotationNameResolver.php b/packages/coding-standard/src/TokenAnalyzer/DoctrineAnnotationNameResolver.php index d3adec27d38..cfef4a9edd6 100644 --- a/packages/coding-standard/src/TokenAnalyzer/DoctrineAnnotationNameResolver.php +++ b/packages/coding-standard/src/TokenAnalyzer/DoctrineAnnotationNameResolver.php @@ -30,16 +30,16 @@ public function resolveName(Tokens $tokens, int $index, array $namespaceUseAnaly $annotationShortName .= $currentToken->getContent(); } - if ($annotationShortName) { - foreach ($namespaceUseAnalyses as $namespaceUseAnalysis) { - if ($namespaceUseAnalysis->getShortName() === $annotationShortName) { - return $namespaceUseAnalysis->getFullName(); - } - } + if ($annotationShortName === '') { + return null; + } - return $annotationShortName; + foreach ($namespaceUseAnalyses as $namespaceUseAnalysis) { + if ($namespaceUseAnalysis->getShortName() === $annotationShortName) { + return $namespaceUseAnalysis->getFullName(); + } } - return null; + return $annotationShortName; } } diff --git a/packages/phpstan-rules/src/PhpDoc/ClassReferencePhpDocNodeVisitor.php b/packages/phpstan-rules/src/PhpDoc/ClassReferencePhpDocNodeVisitor.php index 86f0f4ac3a7..5fec81c748b 100644 --- a/packages/phpstan-rules/src/PhpDoc/ClassReferencePhpDocNodeVisitor.php +++ b/packages/phpstan-rules/src/PhpDoc/ClassReferencePhpDocNodeVisitor.php @@ -46,10 +46,7 @@ public function configureClassName(string $className): void $this->className = $className; } - /** - * @return int|Node|null - */ - public function enterNode(Node $node) + public function enterNode(Node $node): Node { if ($node instanceof PhpDocTagNode) { $this->processPhpDocTagNode($node); diff --git a/rector.php b/rector.php index 74e1fe4aa57..57ba63e88b0 100644 --- a/rector.php +++ b/rector.php @@ -98,6 +98,11 @@ // many false postivies RenameForeachValueVariableToMatchExprVariableRector::class, + // buggy on array access object + \Rector\CodeQuality\Rector\Foreach_\UnusedForeachValueToArrayKeysRector::class => [ + __DIR__ . '/packages/coding-standard/src/Fixer/Annotation/DoctrineAnnotationNestedBracketsFixer.php', + ], + // buggy with parent interface contract ParamTypeDeclarationRector::class => [__DIR__ . '/packages/skipper/src/SkipVoter/*SkipVoter.php'], UnSpreadOperatorRector::class => [__DIR__ . '/packages/git-wrapper'],