1010use PHPStan \Rules \RuleErrorBuilder ;
1111use PHPUnit \Framework \TestCase ;
1212use function sprintf ;
13- use function str_ends_with ;
13+ use function strlen ;
14+ use function substr_compare ;
1415
1516/**
1617 * @implements Rule<Node\Stmt\Class_>
@@ -36,8 +37,7 @@ public function processNode(Node $node, Scope $scope): array
3637 return [];
3738 }
3839
39- $ className = $ node ->namespacedName ->name ;
40- $ class = $ this ->reflectionProvider ->getClass ($ className );
40+ $ class = $ this ->reflectionProvider ->getClass ($ node ->namespacedName ->toString ());
4141
4242 if (!$ class ->isSubclassOf (TestCase::class)) {
4343 return [];
@@ -48,7 +48,7 @@ public function processNode(Node $node, Scope $scope): array
4848 if ($ class ->isAbstract ()) {
4949 $ this ->requireSuffix (
5050 $ errors ,
51- $ className ,
51+ $ class -> getName () ,
5252 'TestCase ' ,
5353 'Abstract test case class, \'%s \', should be named ending in \'%s \'. ' ,
5454 );
@@ -58,15 +58,15 @@ public function processNode(Node $node, Scope $scope): array
5858
5959 $ this ->requireSuffix (
6060 $ errors ,
61- $ className ,
61+ $ class -> getName () ,
6262 'Test ' ,
6363 'Concrete test class, \'%s \', should be named ending in \'%s \'. ' ,
6464 );
6565
6666 if (!$ class ->isFinal ()) {
6767 $ errors [] = RuleErrorBuilder::message (sprintf (
6868 'Concrete test class, \'%s \', should be declared final. ' ,
69- $ className ,
69+ $ class -> getName () ,
7070 ))->identifier ('phpunit.naming ' )->build ();
7171 }
7272
@@ -75,19 +75,37 @@ public function processNode(Node $node, Scope $scope): array
7575
7676 /**
7777 * @param list<IdentifierRuleError> $errors
78+ * @param class-string $className
79+ * @param non-empty-string $suffix
7880 */
7981 private function requireSuffix (array &$ errors , string $ className , string $ suffix , string $ messageFormat ): void
8082 {
81- if (str_ends_with ($ className , $ suffix )) {
83+ if ($ this -> hasSuffix ($ className , $ suffix )) {
8284 return ;
8385 }
8486
85- // @todo Case sensitivity??
8687 $ errors [] = RuleErrorBuilder::message (sprintf (
8788 $ messageFormat ,
8889 $ className ,
8990 $ suffix ,
9091 ))->identifier ('phpunit.naming ' )->build ();
9192 }
9293
94+ /**
95+ * Checks if class name has the given suffix.
96+ *
97+ * Comparison is case insensitive.
98+ *
99+ * @param class-string $className
100+ * @param non-empty-string $suffix
101+ */
102+ private function hasSuffix (string $ className , string $ suffix ): bool
103+ {
104+ $ classNameLen = strlen ($ className );
105+ $ suffixLen = strlen ($ suffix );
106+
107+ return $ suffixLen < $ classNameLen
108+ && substr_compare ($ className , $ suffix , -$ suffixLen , $ suffixLen , true ) === 0 ;
109+ }
110+
93111}
0 commit comments