From ae9490c577b16d24c2e0d8f04114f9185f7e0335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Wer=C5=82os?= Date: Mon, 14 Jul 2025 18:45:05 +0200 Subject: [PATCH 1/2] `PhpdocTagNoNamedArgumentsFixer` - do not add `@no-named-arguments` to attribute classes --- .dev-tools/psalm.xml | 4 ++ .dev-tools/psalm_stub.php | 18 +++++++ README.md | 2 +- src/Fixer/PhpdocTagNoNamedArgumentsFixer.php | 36 ++++++++++++++ .../PhpdocTagNoNamedArgumentsFixerTest.php | 49 +++++++++++++++++++ 5 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 .dev-tools/psalm_stub.php diff --git a/.dev-tools/psalm.xml b/.dev-tools/psalm.xml index 4fc196dd..8f096896 100644 --- a/.dev-tools/psalm.xml +++ b/.dev-tools/psalm.xml @@ -15,6 +15,10 @@ + + + + diff --git a/.dev-tools/psalm_stub.php b/.dev-tools/psalm_stub.php new file mode 100644 index 00000000..a1193101 --- /dev/null +++ b/.dev-tools/psalm_stub.php @@ -0,0 +1,18 @@ +getPrevMeaningfulToken($index); + \assert(\is_int($prevIndex)); + if ($tokens[$prevIndex]->isGivenKind(\T_NEW)) { continue; } + if (self::isAttributeClass($tokens, $prevIndex)) { + continue; + } + $this->ensureIsDocBlockWithNoNameArgumentsTag($tokens, $index); $docBlockIndex = $tokens->getPrevTokenOfKind($index + 2, [[\T_DOC_COMMENT]]); @@ -150,6 +161,31 @@ public function fix(\SplFileInfo $file, Tokens $tokens): void } } + private static function isAttributeClass(Tokens $tokens, int $index): bool + { + while ($tokens[$index]->isGivenKind([\T_ABSTRACT, \T_FINAL, FCT::T_READONLY])) { + $index = $tokens->getPrevMeaningfulToken($index); + \assert(\is_int($index)); + } + + if (!$tokens[$index]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { + return false; + } + + $fullyQualifiedNameAnalyzer = new FullyQualifiedNameAnalyzer($tokens); + + foreach (AttributeAnalyzer::collect($tokens, $tokens->findBlockStart(Tokens::BLOCK_TYPE_ATTRIBUTE, $index)) as $attributeAnalysis) { + foreach ($attributeAnalysis->getAttributes() as $attribute) { + $attributeName = \strtolower($fullyQualifiedNameAnalyzer->getFullyQualifiedName($attribute['name'], $attribute['start'], NamespaceUseAnalysis::TYPE_CLASS)); + if ($attributeName === 'attribute') { + return true; + } + } + } + + return false; + } + private function ensureIsDocBlockWithNoNameArgumentsTag(Tokens $tokens, int $index): void { /** @var null|callable(WhitespacesFixerConfig, Tokens, int): void $ensureIsDocBlockWithTagNoNameArguments */ diff --git a/tests/Fixer/PhpdocTagNoNamedArgumentsFixerTest.php b/tests/Fixer/PhpdocTagNoNamedArgumentsFixerTest.php index 314900db..6f86077a 100644 --- a/tests/Fixer/PhpdocTagNoNamedArgumentsFixerTest.php +++ b/tests/Fixer/PhpdocTagNoNamedArgumentsFixerTest.php @@ -224,5 +224,54 @@ class Foo {} [], new WhitespacesFixerConfig("\t", "\r\n"), ]; + + yield 'do not add for attribute class' => [ + <<<'PHP' + [ + <<<'PHP' + Date: Mon, 14 Jul 2025 21:11:11 +0200 Subject: [PATCH 2/2] Update --- README.md | 2 +- .../PhpdocTagNoNamedArgumentsFixerTest.php | 65 +++++++++++++++---- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index b2b1e0a0..3f5633d8 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Latest stable version](https://img.shields.io/packagist/v/kubawerlos/php-cs-fixer-custom-fixers.svg?label=current%20version)](https://packagist.org/packages/kubawerlos/php-cs-fixer-custom-fixers) [![PHP version](https://img.shields.io/packagist/php-v/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://php.net) [![License](https://img.shields.io/github/license/kubawerlos/php-cs-fixer-custom-fixers.svg)](LICENSE) -![Tests](https://img.shields.io/badge/tests-3804-brightgreen.svg) +![Tests](https://img.shields.io/badge/tests-3805-brightgreen.svg) [![Downloads](https://img.shields.io/packagist/dt/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://packagist.org/packages/kubawerlos/php-cs-fixer-custom-fixers) [![CI status](https://github.com/kubawerlos/php-cs-fixer-custom-fixers/actions/workflows/ci.yaml/badge.svg)](https://github.com/kubawerlos/php-cs-fixer-custom-fixers/actions/workflows/ci.yaml) diff --git a/tests/Fixer/PhpdocTagNoNamedArgumentsFixerTest.php b/tests/Fixer/PhpdocTagNoNamedArgumentsFixerTest.php index 6f86077a..772255e5 100644 --- a/tests/Fixer/PhpdocTagNoNamedArgumentsFixerTest.php +++ b/tests/Fixer/PhpdocTagNoNamedArgumentsFixerTest.php @@ -224,29 +224,69 @@ class Foo {} [], new WhitespacesFixerConfig("\t", "\r\n"), ]; + } + + /** + * @dataProvider provideFix80Cases + * + * @requires PHP >= 8.0 + */ + public function testFix80(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + /** + * @return iterable + */ + public static function provideFix80Cases(): iterable + { yield 'do not add for attribute class' => [ <<<'PHP' [ + yield 'do not add for attribute class (with alias)' => [ <<<'PHP' = 8.2 + */ + public function testFix82(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + /** + * @return iterable + */ + public static function provideFix82Cases(): iterable + { + yield 'do not add for attribute (readonly) class' => [ + <<<'PHP' +