Skip to content

Commit ae9490c

Browse files
committed
PhpdocTagNoNamedArgumentsFixer - do not add @no-named-arguments to attribute classes
1 parent 636bbba commit ae9490c

File tree

5 files changed

+108
-1
lines changed

5 files changed

+108
-1
lines changed

.dev-tools/psalm.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
<directory name='../src' />
1616
</projectFiles>
1717

18+
<stubs>
19+
<file name='./psalm_stub.php' preloadClasses="true" />
20+
</stubs>
21+
1822
<issueHandlers>
1923
<DeprecatedClass errorLevel='suppress' />
2024
<InaccessibleMethod errorLevel='suppress' />

.dev-tools/psalm_stub.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of PHP CS Fixer: custom fixers.
5+
*
6+
* (c) 2018 Kuba Werłos
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
namespace PhpCsFixer\Tokenizer {
13+
final class FCT
14+
{
15+
public const int T_READONLY = \T_READONLY;
16+
}
17+
final class OtherClassSoTheNameOfClassAboveIsNotChanged {}
18+
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![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)
66
[![PHP version](https://img.shields.io/packagist/php-v/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://php.net)
77
[![License](https://img.shields.io/github/license/kubawerlos/php-cs-fixer-custom-fixers.svg)](LICENSE)
8-
![Tests](https://img.shields.io/badge/tests-3802-brightgreen.svg)
8+
![Tests](https://img.shields.io/badge/tests-3804-brightgreen.svg)
99
[![Downloads](https://img.shields.io/packagist/dt/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://packagist.org/packages/kubawerlos/php-cs-fixer-custom-fixers)
1010

1111
[![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)

src/Fixer/PhpdocTagNoNamedArgumentsFixer.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
use PhpCsFixer\FixerDefinition\FixerDefinition;
2323
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
2424
use PhpCsFixer\Preg;
25+
use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis;
26+
use PhpCsFixer\Tokenizer\Analyzer\AttributeAnalyzer;
27+
use PhpCsFixer\Tokenizer\Analyzer\FullyQualifiedNameAnalyzer;
28+
use PhpCsFixer\Tokenizer\CT;
29+
use PhpCsFixer\Tokenizer\FCT;
2530
use PhpCsFixer\Tokenizer\Token;
2631
use PhpCsFixer\Tokenizer\Tokens;
2732
use PhpCsFixer\WhitespacesFixerConfig;
@@ -131,10 +136,16 @@ public function fix(\SplFileInfo $file, Tokens $tokens): void
131136
}
132137

133138
$prevIndex = $tokens->getPrevMeaningfulToken($index);
139+
\assert(\is_int($prevIndex));
140+
134141
if ($tokens[$prevIndex]->isGivenKind(\T_NEW)) {
135142
continue;
136143
}
137144

145+
if (self::isAttributeClass($tokens, $prevIndex)) {
146+
continue;
147+
}
148+
138149
$this->ensureIsDocBlockWithNoNameArgumentsTag($tokens, $index);
139150

140151
$docBlockIndex = $tokens->getPrevTokenOfKind($index + 2, [[\T_DOC_COMMENT]]);
@@ -150,6 +161,31 @@ public function fix(\SplFileInfo $file, Tokens $tokens): void
150161
}
151162
}
152163

164+
private static function isAttributeClass(Tokens $tokens, int $index): bool
165+
{
166+
while ($tokens[$index]->isGivenKind([\T_ABSTRACT, \T_FINAL, FCT::T_READONLY])) {
167+
$index = $tokens->getPrevMeaningfulToken($index);
168+
\assert(\is_int($index));
169+
}
170+
171+
if (!$tokens[$index]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) {
172+
return false;
173+
}
174+
175+
$fullyQualifiedNameAnalyzer = new FullyQualifiedNameAnalyzer($tokens);
176+
177+
foreach (AttributeAnalyzer::collect($tokens, $tokens->findBlockStart(Tokens::BLOCK_TYPE_ATTRIBUTE, $index)) as $attributeAnalysis) {
178+
foreach ($attributeAnalysis->getAttributes() as $attribute) {
179+
$attributeName = \strtolower($fullyQualifiedNameAnalyzer->getFullyQualifiedName($attribute['name'], $attribute['start'], NamespaceUseAnalysis::TYPE_CLASS));
180+
if ($attributeName === 'attribute') {
181+
return true;
182+
}
183+
}
184+
}
185+
186+
return false;
187+
}
188+
153189
private function ensureIsDocBlockWithNoNameArgumentsTag(Tokens $tokens, int $index): void
154190
{
155191
/** @var null|callable(WhitespacesFixerConfig, Tokens, int): void $ensureIsDocBlockWithTagNoNameArguments */

tests/Fixer/PhpdocTagNoNamedArgumentsFixerTest.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,5 +224,54 @@ class Foo {}
224224
[],
225225
new WhitespacesFixerConfig("\t", "\r\n"),
226226
];
227+
228+
yield 'do not add for attribute class' => [
229+
<<<'PHP'
230+
<?php
231+
#[Attribute(flags: Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
232+
final readonly class MyAttributeClass {}
233+
PHP,
234+
];
235+
236+
yield 'do not add for attribute class (used with alias)' => [
237+
<<<'PHP'
238+
<?php
239+
namespace Foo;
240+
use Attribute as TheAttributeClass;
241+
242+
/**
243+
* @no-named-arguments
244+
*/
245+
#[FooAttribute]
246+
final class NotAttributeClass1 {}
247+
248+
#[TheAttributeClass(flags: Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
249+
abstract class MyAttributeClass {}
250+
251+
/**
252+
* @no-named-arguments
253+
*/
254+
#[FooAttribute]
255+
#[BarAttribute]
256+
#[BazAttribute]
257+
final class NotAttributeClass1 {}
258+
PHP,
259+
<<<'PHP'
260+
<?php
261+
namespace Foo;
262+
use Attribute as TheAttributeClass;
263+
264+
#[FooAttribute]
265+
final class NotAttributeClass1 {}
266+
267+
#[TheAttributeClass(flags: Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
268+
abstract class MyAttributeClass {}
269+
270+
#[FooAttribute]
271+
#[BarAttribute]
272+
#[BazAttribute]
273+
final class NotAttributeClass1 {}
274+
PHP,
275+
];
227276
}
228277
}

0 commit comments

Comments
 (0)