Skip to content

Commit b798d26

Browse files
authored
Merge pull request #160 from alies-dev/fix/158-test-attribute-detection-via-declaring-class-aliases
Fix #[Test] attribute detection for inherited and fully-qualified attributes
2 parents 44c270b + 0bed8b1 commit b798d26

2 files changed

Lines changed: 94 additions & 2 deletions

File tree

src/Hooks/TestCaseHandler.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ public static function afterStatementAnalysis(AfterClassLikeAnalysisEvent $event
159159
continue;
160160
}
161161

162-
$specials = self::getSpecials($stmt_method, $aliases);
162+
// Use the declaring class's aliases so trait-declared attributes resolve via the trait's imports.
163+
$method_aliases = $declaring_class_storage->aliases ?? $aliases;
164+
$specials = self::getSpecials($stmt_method, $method_aliases);
163165

164166
$is_test = 0 === strpos($method_name_lc, 'test') || isset($specials['test']);
165167
if (!$is_test) {
@@ -561,7 +563,8 @@ private static function attributeValue(ClassMethod $method, Aliases $aliases, st
561563
$attributesInGroupMatchingRequestedAttributeName = static fn(AttributeGroup $group): array => array_filter(
562564
$group->attrs,
563565
static fn(Attribute $attribute): bool => $attributeClass === Type::getFQCLNFromString(
564-
$attribute->name->toString(),
566+
// toCodeString() keeps the leading backslash toString() strips, so fully-qualified attributes resolve.
567+
$attribute->name->toCodeString(),
565568
$aliases,
566569
),
567570
);

tests/acceptance/TestCase.feature

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,95 @@ Feature: TestCase
909909
When I run Psalm with dead code detection
910910
Then I see no errors
911911

912+
Scenario: Test methods marked with #[Test] in a trait are not marked as unused when the consuming class does not import the Test attribute
913+
Given I have the following code in "MyTestTrait.php"
914+
"""
915+
<?php
916+
namespace NS;
917+
use PHPUnit\Framework\Attributes\Test;
918+
trait MyTestTrait {
919+
#[Test]
920+
public function itDoesSomething(): void {}
921+
}
922+
"""
923+
And I have the following code in "code.php"
924+
"""
925+
<?php
926+
namespace NS;
927+
use PHPUnit\Framework\TestCase;
928+
final class MyTestCase extends TestCase {
929+
use MyTestTrait;
930+
}
931+
"""
932+
When I run Psalm with dead code detection
933+
Then I see no errors
934+
935+
Scenario: Test methods marked with a partially-imported #[Attributes\Test] in a trait are not marked as unused when the consuming class does not import the namespace
936+
Given I have the following code in "MyTestTrait.php"
937+
"""
938+
<?php
939+
namespace NS;
940+
use PHPUnit\Framework\Attributes;
941+
trait MyTestTrait {
942+
#[Attributes\Test]
943+
public function itDoesSomething(): void {}
944+
}
945+
"""
946+
And I have the following code in "code.php"
947+
"""
948+
<?php
949+
namespace NS;
950+
use PHPUnit\Framework\TestCase;
951+
final class MyTestCase extends TestCase {
952+
use MyTestTrait;
953+
}
954+
"""
955+
When I run Psalm with dead code detection
956+
Then I see no errors
957+
958+
Scenario: Test methods marked with an aliased #[Test] attribute in a trait are not marked as unused when the consuming class does not import the alias
959+
Given I have the following code in "MyTestTrait.php"
960+
"""
961+
<?php
962+
namespace NS;
963+
use PHPUnit\Framework\Attributes\Test as PHPUnitTest;
964+
trait MyTestTrait {
965+
#[PHPUnitTest]
966+
public function itDoesSomething(): void {}
967+
}
968+
"""
969+
And I have the following code in "code.php"
970+
"""
971+
<?php
972+
namespace NS;
973+
use PHPUnit\Framework\TestCase;
974+
final class MyTestCase extends TestCase {
975+
use MyTestTrait;
976+
}
977+
"""
978+
When I run Psalm with dead code detection
979+
Then I see no errors
980+
981+
Scenario: Test methods marked with a fully-qualified #[Test] attribute are not marked as unused
982+
Given I have the following code in "BaseTestCase.php"
983+
"""
984+
<?php
985+
namespace NS;
986+
use PHPUnit\Framework\TestCase;
987+
abstract class BaseTestCase extends TestCase {}
988+
"""
989+
And I have the following code in "code.php"
990+
"""
991+
<?php
992+
namespace NS;
993+
final class MyTestCase extends BaseTestCase {
994+
#[\PHPUnit\Framework\Attributes\Test]
995+
public function itDoesSomething(): void {}
996+
}
997+
"""
998+
When I run Psalm with dead code detection
999+
Then I see no errors
1000+
9121001
Scenario: Inherited test methods are not marked as unused
9131002
Given I have the following code
9141003
"""

0 commit comments

Comments
 (0)