From b4315e898c4f015afeaabc8110cb15f2d03933a2 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Tue, 10 Mar 2026 12:36:34 +0000 Subject: [PATCH 1/6] Fix phpstan/phpstan#14250: Report trait.duplicateMethod for duplicate methods in traits - Created DuplicateTraitDeclarationRule that listens for InTraitNode to detect duplicate methods, properties, and constants within trait declarations - The existing DuplicateDeclarationRule only handles InClassNode, which is never emitted for traits (NodeScopeResolver skips trait declarations at line 967-968) - InTraitNode is emitted when a trait is used by a class, allowing the new rule to check trait bodies for duplicates - Added regression test in tests/PHPStan/Rules/Classes/data/bug-14250.php --- .../Classes/DuplicateTraitDeclarationRule.php | 120 ++++++++++++++++++ .../DuplicateTraitDeclarationRuleTest.php | 29 +++++ .../PHPStan/Rules/Classes/data/bug-14250.php | 19 +++ 3 files changed, 168 insertions(+) create mode 100644 src/Rules/Classes/DuplicateTraitDeclarationRule.php create mode 100644 tests/PHPStan/Rules/Classes/DuplicateTraitDeclarationRuleTest.php create mode 100644 tests/PHPStan/Rules/Classes/data/bug-14250.php diff --git a/src/Rules/Classes/DuplicateTraitDeclarationRule.php b/src/Rules/Classes/DuplicateTraitDeclarationRule.php new file mode 100644 index 0000000000..a4165c0796 --- /dev/null +++ b/src/Rules/Classes/DuplicateTraitDeclarationRule.php @@ -0,0 +1,120 @@ + + */ +#[RegisteredRule(level: 0)] +final class DuplicateTraitDeclarationRule implements Rule +{ + + public function getNodeType(): string + { + return InTraitNode::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $traitReflection = $node->getTraitReflection(); + + $errors = []; + + $declaredClassConstants = []; + foreach ($node->getOriginalNode()->stmts as $stmtNode) { + if (!($stmtNode instanceof ClassConst)) { + continue; + } + foreach ($stmtNode->consts as $classConstNode) { + if (array_key_exists($classConstNode->name->name, $declaredClassConstants)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'Cannot redeclare constant %s::%s.', + $traitReflection->getDisplayName(), + $classConstNode->name->name, + ))->identifier('trait.duplicateConstant') + ->line($classConstNode->getStartLine()) + ->nonIgnorable() + ->build(); + } else { + $declaredClassConstants[$classConstNode->name->name] = true; + } + } + } + + $declaredProperties = []; + foreach ($node->getOriginalNode()->getProperties() as $propertyDecl) { + foreach ($propertyDecl->props as $property) { + if (array_key_exists($property->name->name, $declaredProperties)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'Cannot redeclare property %s::$%s.', + $traitReflection->getDisplayName(), + $property->name->name, + ))->identifier('trait.duplicateProperty') + ->line($property->getStartLine()) + ->nonIgnorable() + ->build(); + } else { + $declaredProperties[$property->name->name] = true; + } + } + } + + $declaredFunctions = []; + foreach ($node->getOriginalNode()->getMethods() as $method) { + if ($method->name->toLowerString() === '__construct') { + foreach ($method->params as $param) { + if ($param->flags === 0) { + continue; + } + + if (!$param->var instanceof Node\Expr\Variable || !is_string($param->var->name)) { + throw new ShouldNotHappenException(); + } + + $propertyName = $param->var->name; + + if (array_key_exists($propertyName, $declaredProperties)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'Cannot redeclare property %s::$%s.', + $traitReflection->getDisplayName(), + $propertyName, + ))->identifier('trait.duplicateProperty') + ->line($param->getStartLine()) + ->nonIgnorable() + ->build(); + } else { + $declaredProperties[$propertyName] = true; + } + } + } + if (array_key_exists(strtolower($method->name->name), $declaredFunctions)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'Cannot redeclare method %s::%s().', + $traitReflection->getDisplayName(), + $method->name->name, + ))->identifier('trait.duplicateMethod') + ->line($method->getStartLine()) + ->nonIgnorable() + ->build(); + } else { + $declaredFunctions[strtolower($method->name->name)] = true; + } + } + + return $errors; + } + +} diff --git a/tests/PHPStan/Rules/Classes/DuplicateTraitDeclarationRuleTest.php b/tests/PHPStan/Rules/Classes/DuplicateTraitDeclarationRuleTest.php new file mode 100644 index 0000000000..b3cdd5f197 --- /dev/null +++ b/tests/PHPStan/Rules/Classes/DuplicateTraitDeclarationRuleTest.php @@ -0,0 +1,29 @@ + + */ +class DuplicateTraitDeclarationRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new DuplicateTraitDeclarationRule(); + } + + public function testBug14250(): void + { + $this->analyse([__DIR__ . '/data/bug-14250.php'], [ + [ + 'Cannot redeclare method Bug14250\MyTrait::doSomething().', + 11, + ], + ]); + } + +} diff --git a/tests/PHPStan/Rules/Classes/data/bug-14250.php b/tests/PHPStan/Rules/Classes/data/bug-14250.php new file mode 100644 index 0000000000..9a23ef836b --- /dev/null +++ b/tests/PHPStan/Rules/Classes/data/bug-14250.php @@ -0,0 +1,19 @@ + Date: Wed, 18 Mar 2026 22:46:04 +0000 Subject: [PATCH 2/6] Extract DuplicateDeclarationHelper to share logic between DuplicateDeclarationRule and DuplicateTraitDeclarationRule Co-Authored-By: Claude Opus 4.6 --- .../Classes/DuplicateDeclarationHelper.php | 122 ++++++++++++++++++ .../Classes/DuplicateDeclarationRule.php | 110 +--------------- .../Classes/DuplicateTraitDeclarationRule.php | 98 +------------- 3 files changed, 132 insertions(+), 198 deletions(-) create mode 100644 src/Rules/Classes/DuplicateDeclarationHelper.php diff --git a/src/Rules/Classes/DuplicateDeclarationHelper.php b/src/Rules/Classes/DuplicateDeclarationHelper.php new file mode 100644 index 0000000000..4aa8f05f89 --- /dev/null +++ b/src/Rules/Classes/DuplicateDeclarationHelper.php @@ -0,0 +1,122 @@ + + */ + public static function checkClassLike(ClassLike $classLike, string $displayName, string $identifierType): array + { + $errors = []; + + $declaredClassConstantsOrEnumCases = []; + foreach ($classLike->stmts as $stmtNode) { + if ($stmtNode instanceof EnumCase) { + if (array_key_exists($stmtNode->name->name, $declaredClassConstantsOrEnumCases)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'Cannot redeclare enum case %s::%s.', + $displayName, + $stmtNode->name->name, + ))->identifier(sprintf('%s.duplicateEnumCase', $identifierType)) + ->line($stmtNode->getStartLine()) + ->nonIgnorable() + ->build(); + } else { + $declaredClassConstantsOrEnumCases[$stmtNode->name->name] = true; + } + } elseif ($stmtNode instanceof ClassConst) { + foreach ($stmtNode->consts as $classConstNode) { + if (array_key_exists($classConstNode->name->name, $declaredClassConstantsOrEnumCases)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'Cannot redeclare constant %s::%s.', + $displayName, + $classConstNode->name->name, + ))->identifier(sprintf('%s.duplicateConstant', $identifierType)) + ->line($classConstNode->getStartLine()) + ->nonIgnorable() + ->build(); + } else { + $declaredClassConstantsOrEnumCases[$classConstNode->name->name] = true; + } + } + } + } + + $declaredProperties = []; + foreach ($classLike->getProperties() as $propertyDecl) { + foreach ($propertyDecl->props as $property) { + if (array_key_exists($property->name->name, $declaredProperties)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'Cannot redeclare property %s::$%s.', + $displayName, + $property->name->name, + ))->identifier(sprintf('%s.duplicateProperty', $identifierType)) + ->line($property->getStartLine()) + ->nonIgnorable() + ->build(); + } else { + $declaredProperties[$property->name->name] = true; + } + } + } + + $declaredFunctions = []; + foreach ($classLike->getMethods() as $method) { + if ($method->name->toLowerString() === '__construct') { + foreach ($method->params as $param) { + if ($param->flags === 0) { + continue; + } + + if (!$param->var instanceof Node\Expr\Variable || !is_string($param->var->name)) { + throw new ShouldNotHappenException(); + } + + $propertyName = $param->var->name; + + if (array_key_exists($propertyName, $declaredProperties)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'Cannot redeclare property %s::$%s.', + $displayName, + $propertyName, + ))->identifier(sprintf('%s.duplicateProperty', $identifierType)) + ->line($param->getStartLine()) + ->nonIgnorable() + ->build(); + } else { + $declaredProperties[$propertyName] = true; + } + } + } + if (array_key_exists(strtolower($method->name->name), $declaredFunctions)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'Cannot redeclare method %s::%s().', + $displayName, + $method->name->name, + ))->identifier(sprintf('%s.duplicateMethod', $identifierType)) + ->line($method->getStartLine()) + ->nonIgnorable() + ->build(); + } else { + $declaredFunctions[strtolower($method->name->name)] = true; + } + } + + return $errors; + } + +} diff --git a/src/Rules/Classes/DuplicateDeclarationRule.php b/src/Rules/Classes/DuplicateDeclarationRule.php index 6fe86ed9bc..2ef84a169a 100644 --- a/src/Rules/Classes/DuplicateDeclarationRule.php +++ b/src/Rules/Classes/DuplicateDeclarationRule.php @@ -3,17 +3,10 @@ namespace PHPStan\Rules\Classes; use PhpParser\Node; -use PhpParser\Node\Stmt\ClassConst; -use PhpParser\Node\Stmt\EnumCase; use PHPStan\Analyser\Scope; use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\InClassNode; use PHPStan\Rules\Rule; -use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; -use function array_key_exists; -use function is_string; -use function sprintf; use function strtolower; /** @@ -32,104 +25,11 @@ public function processNode(Node $node, Scope $scope): array { $classReflection = $node->getClassReflection(); - $identifierType = strtolower($classReflection->getClassTypeDescription()); - - $errors = []; - - $declaredClassConstantsOrEnumCases = []; - foreach ($node->getOriginalNode()->stmts as $stmtNode) { - if ($stmtNode instanceof EnumCase) { - if (array_key_exists($stmtNode->name->name, $declaredClassConstantsOrEnumCases)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'Cannot redeclare enum case %s::%s.', - $classReflection->getDisplayName(), - $stmtNode->name->name, - ))->identifier(sprintf('%s.duplicateEnumCase', $identifierType)) - ->line($stmtNode->getStartLine()) - ->nonIgnorable() - ->build(); - } else { - $declaredClassConstantsOrEnumCases[$stmtNode->name->name] = true; - } - } elseif ($stmtNode instanceof ClassConst) { - foreach ($stmtNode->consts as $classConstNode) { - if (array_key_exists($classConstNode->name->name, $declaredClassConstantsOrEnumCases)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'Cannot redeclare constant %s::%s.', - $classReflection->getDisplayName(), - $classConstNode->name->name, - ))->identifier(sprintf('%s.duplicateConstant', $identifierType)) - ->line($classConstNode->getStartLine()) - ->nonIgnorable() - ->build(); - } else { - $declaredClassConstantsOrEnumCases[$classConstNode->name->name] = true; - } - } - } - } - - $declaredProperties = []; - foreach ($node->getOriginalNode()->getProperties() as $propertyDecl) { - foreach ($propertyDecl->props as $property) { - if (array_key_exists($property->name->name, $declaredProperties)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'Cannot redeclare property %s::$%s.', - $classReflection->getDisplayName(), - $property->name->name, - ))->identifier(sprintf('%s.duplicateProperty', $identifierType)) - ->line($property->getStartLine()) - ->nonIgnorable() - ->build(); - } else { - $declaredProperties[$property->name->name] = true; - } - } - } - - $declaredFunctions = []; - foreach ($node->getOriginalNode()->getMethods() as $method) { - if ($method->name->toLowerString() === '__construct') { - foreach ($method->params as $param) { - if ($param->flags === 0) { - continue; - } - - if (!$param->var instanceof Node\Expr\Variable || !is_string($param->var->name)) { - throw new ShouldNotHappenException(); - } - - $propertyName = $param->var->name; - - if (array_key_exists($propertyName, $declaredProperties)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'Cannot redeclare property %s::$%s.', - $classReflection->getDisplayName(), - $propertyName, - ))->identifier(sprintf('%s.duplicateProperty', $identifierType)) - ->line($param->getStartLine()) - ->nonIgnorable() - ->build(); - } else { - $declaredProperties[$propertyName] = true; - } - } - } - if (array_key_exists(strtolower($method->name->name), $declaredFunctions)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'Cannot redeclare method %s::%s().', - $classReflection->getDisplayName(), - $method->name->name, - ))->identifier(sprintf('%s.duplicateMethod', $identifierType)) - ->line($method->getStartLine()) - ->nonIgnorable() - ->build(); - } else { - $declaredFunctions[strtolower($method->name->name)] = true; - } - } - - return $errors; + return DuplicateDeclarationHelper::checkClassLike( + $node->getOriginalNode(), + $classReflection->getDisplayName(), + strtolower($classReflection->getClassTypeDescription()), + ); } } diff --git a/src/Rules/Classes/DuplicateTraitDeclarationRule.php b/src/Rules/Classes/DuplicateTraitDeclarationRule.php index a4165c0796..e8847611e5 100644 --- a/src/Rules/Classes/DuplicateTraitDeclarationRule.php +++ b/src/Rules/Classes/DuplicateTraitDeclarationRule.php @@ -3,17 +3,10 @@ namespace PHPStan\Rules\Classes; use PhpParser\Node; -use PhpParser\Node\Stmt\ClassConst; use PHPStan\Analyser\Scope; use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\InTraitNode; use PHPStan\Rules\Rule; -use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; -use function array_key_exists; -use function is_string; -use function sprintf; -use function strtolower; /** * @implements Rule @@ -29,92 +22,11 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - $traitReflection = $node->getTraitReflection(); - - $errors = []; - - $declaredClassConstants = []; - foreach ($node->getOriginalNode()->stmts as $stmtNode) { - if (!($stmtNode instanceof ClassConst)) { - continue; - } - foreach ($stmtNode->consts as $classConstNode) { - if (array_key_exists($classConstNode->name->name, $declaredClassConstants)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'Cannot redeclare constant %s::%s.', - $traitReflection->getDisplayName(), - $classConstNode->name->name, - ))->identifier('trait.duplicateConstant') - ->line($classConstNode->getStartLine()) - ->nonIgnorable() - ->build(); - } else { - $declaredClassConstants[$classConstNode->name->name] = true; - } - } - } - - $declaredProperties = []; - foreach ($node->getOriginalNode()->getProperties() as $propertyDecl) { - foreach ($propertyDecl->props as $property) { - if (array_key_exists($property->name->name, $declaredProperties)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'Cannot redeclare property %s::$%s.', - $traitReflection->getDisplayName(), - $property->name->name, - ))->identifier('trait.duplicateProperty') - ->line($property->getStartLine()) - ->nonIgnorable() - ->build(); - } else { - $declaredProperties[$property->name->name] = true; - } - } - } - - $declaredFunctions = []; - foreach ($node->getOriginalNode()->getMethods() as $method) { - if ($method->name->toLowerString() === '__construct') { - foreach ($method->params as $param) { - if ($param->flags === 0) { - continue; - } - - if (!$param->var instanceof Node\Expr\Variable || !is_string($param->var->name)) { - throw new ShouldNotHappenException(); - } - - $propertyName = $param->var->name; - - if (array_key_exists($propertyName, $declaredProperties)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'Cannot redeclare property %s::$%s.', - $traitReflection->getDisplayName(), - $propertyName, - ))->identifier('trait.duplicateProperty') - ->line($param->getStartLine()) - ->nonIgnorable() - ->build(); - } else { - $declaredProperties[$propertyName] = true; - } - } - } - if (array_key_exists(strtolower($method->name->name), $declaredFunctions)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'Cannot redeclare method %s::%s().', - $traitReflection->getDisplayName(), - $method->name->name, - ))->identifier('trait.duplicateMethod') - ->line($method->getStartLine()) - ->nonIgnorable() - ->build(); - } else { - $declaredFunctions[strtolower($method->name->name)] = true; - } - } - - return $errors; + return DuplicateDeclarationHelper::checkClassLike( + $node->getOriginalNode(), + $node->getTraitReflection()->getDisplayName(), + 'trait', + ); } } From 33eb3090bbccdb7a345971949a7528c4a14ef821 Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Wed, 18 Mar 2026 22:46:11 +0000 Subject: [PATCH 3/6] Add comprehensive tests for duplicate declarations in traits (constants, properties, promoted properties, methods) Co-Authored-By: Claude Opus 4.6 --- .../DuplicateTraitDeclarationRuleTest.php | 38 +++++++++++++ .../data/bug-14250-promoted-properties.php | 22 ++++++++ .../PHPStan/Rules/Classes/data/bug-14250.php | 56 +++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 tests/PHPStan/Rules/Classes/data/bug-14250-promoted-properties.php diff --git a/tests/PHPStan/Rules/Classes/DuplicateTraitDeclarationRuleTest.php b/tests/PHPStan/Rules/Classes/DuplicateTraitDeclarationRuleTest.php index b3cdd5f197..6090b37060 100644 --- a/tests/PHPStan/Rules/Classes/DuplicateTraitDeclarationRuleTest.php +++ b/tests/PHPStan/Rules/Classes/DuplicateTraitDeclarationRuleTest.php @@ -23,6 +23,44 @@ public function testBug14250(): void 'Cannot redeclare method Bug14250\MyTrait::doSomething().', 11, ], + [ + 'Cannot redeclare constant Bug14250\TraitWithDuplicateConstants::CONST1.', + 24, + ], + [ + 'Cannot redeclare constant Bug14250\TraitWithDuplicateConstants::CONST2.', + 26, + ], + [ + 'Cannot redeclare property Bug14250\TraitWithDuplicateProperties::$prop1.', + 41, + ], + [ + 'Cannot redeclare property Bug14250\TraitWithDuplicateProperties::$prop2.', + 44, + ], + [ + 'Cannot redeclare method Bug14250\TraitWithDuplicateMethods::func1().', + 59, + ], + [ + 'Cannot redeclare method Bug14250\TraitWithDuplicateMethods::Func1().', + 69, + ], + ]); + } + + public function testDuplicatePromotedProperty(): void + { + $this->analyse([__DIR__ . '/data/bug-14250-promoted-properties.php'], [ + [ + 'Cannot redeclare property Bug14250PromotedProperties\TraitWithDuplicatePromotedProperties::$foo.', + 10, + ], + [ + 'Cannot redeclare property Bug14250PromotedProperties\TraitWithDuplicatePromotedProperties::$bar.', + 12, + ], ]); } diff --git a/tests/PHPStan/Rules/Classes/data/bug-14250-promoted-properties.php b/tests/PHPStan/Rules/Classes/data/bug-14250-promoted-properties.php new file mode 100644 index 0000000000..efff2fb7b9 --- /dev/null +++ b/tests/PHPStan/Rules/Classes/data/bug-14250-promoted-properties.php @@ -0,0 +1,22 @@ += 8.0 + +namespace Bug14250PromotedProperties; + +trait TraitWithDuplicatePromotedProperties +{ + private $foo; + + public function __construct( + private $foo, + private $bar, + private $bar + ) + { + + } +} + +class Foo +{ + use TraitWithDuplicatePromotedProperties; +} diff --git a/tests/PHPStan/Rules/Classes/data/bug-14250.php b/tests/PHPStan/Rules/Classes/data/bug-14250.php index 9a23ef836b..12af916ad4 100644 --- a/tests/PHPStan/Rules/Classes/data/bug-14250.php +++ b/tests/PHPStan/Rules/Classes/data/bug-14250.php @@ -17,3 +17,59 @@ class Foo { use MyTrait; } + +trait TraitWithDuplicateConstants +{ + public const CONST1 = 1; + public const CONST1 = 2; + + public const CONST2 = 2, CONST2 = 1; + + public const CONST3 = 1; +} + +class Bar +{ + use TraitWithDuplicateConstants; +} + +trait TraitWithDuplicateProperties +{ + /** @var int */ + public $prop1; + /** @var int */ + public $prop1; + + /** @var int */ + public $prop2, $prop2; + + /** @var int */ + public $prop3; +} + +class Baz +{ + use TraitWithDuplicateProperties; +} + +trait TraitWithDuplicateMethods +{ + public function func1(): void {} + + public function func1(): int + { + return 1; + } + + public function func2(): int + { + return 2; + } + + public function Func1(): void {} +} + +class Qux +{ + use TraitWithDuplicateMethods; +} From c9ac61cf9e3619a1189e5c79937e663ad728007b Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Thu, 19 Mar 2026 09:26:36 +0100 Subject: [PATCH 4/6] Fix lint --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 97eb28b467..463db1ca8d 100644 --- a/Makefile +++ b/Makefile @@ -126,6 +126,8 @@ lint: --exclude tests/PHPStan/Rules/Properties/data/property-override-attr-missing.php \ --exclude tests/PHPStan/Rules/Properties/data/override-attr-on-property.php \ --exclude tests/PHPStan/Rules/Properties/data/property-override-attr.php \ + --exclude tests/PHPStan/Rules/Classes/data/bug-14250.php \ + --exclude tests/PHPStan/Rules/Classes/data/bug-14250-promoted-properties.php \ --exclude tests/PHPStan/Rules/Operators/data/bug-3585.php \ src tests From d0974e2abb1c9f80396302bbc72e938b033f293a Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Thu, 19 Mar 2026 09:16:34 +0000 Subject: [PATCH 5/6] Add test case for multiple conflicting traits (no false positive) Co-Authored-By: Claude Opus 4.6 --- .../PHPStan/Rules/Classes/data/bug-14250.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/PHPStan/Rules/Classes/data/bug-14250.php b/tests/PHPStan/Rules/Classes/data/bug-14250.php index 12af916ad4..2138c97305 100644 --- a/tests/PHPStan/Rules/Classes/data/bug-14250.php +++ b/tests/PHPStan/Rules/Classes/data/bug-14250.php @@ -73,3 +73,22 @@ class Qux { use TraitWithDuplicateMethods; } + +trait MyTrait1 +{ + public function doSomething(): void + { + } +} + +trait MyTrait2 +{ + public function doSomething(): void + { + } +} + +class FooWithMultipleConflictingTraits +{ + use MyTrait1, MyTrait2; +} From 77ef26e1eb61456d10f2345de66d2c7c30d88565 Mon Sep 17 00:00:00 2001 From: phpstan-bot Date: Thu, 19 Mar 2026 22:36:50 +0000 Subject: [PATCH 6/6] Fix lint: use import statement for IdentifierRuleError Co-Authored-By: Claude Opus 4.6 --- src/Rules/Classes/DuplicateDeclarationHelper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Rules/Classes/DuplicateDeclarationHelper.php b/src/Rules/Classes/DuplicateDeclarationHelper.php index 4aa8f05f89..04840164bf 100644 --- a/src/Rules/Classes/DuplicateDeclarationHelper.php +++ b/src/Rules/Classes/DuplicateDeclarationHelper.php @@ -6,6 +6,7 @@ use PhpParser\Node\Stmt\ClassConst; use PhpParser\Node\Stmt\ClassLike; use PhpParser\Node\Stmt\EnumCase; +use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\ShouldNotHappenException; use function array_key_exists; @@ -17,7 +18,7 @@ final class DuplicateDeclarationHelper { /** - * @return list<\PHPStan\Rules\IdentifierRuleError> + * @return list */ public static function checkClassLike(ClassLike $classLike, string $displayName, string $identifierType): array {