Skip to content

Commit 71ee6b4

Browse files
committed
Report Foo::class of a restricted class with the class name usage message
Since Foo::class is passed to restricted class constant usage extensions as a constant named "class", the internal class rules reported it as "Access to constant class of internal class X from outside its root namespace NS." Report it again as "Access to constant on internal class X." from the class name usage extension, and use the same wording in ClassNameUsageLocation for other extensions, such as deprecation rules. The ClassNameConstantReflection passed to the extensions is unchanged, so the API extensions still see Foo::class. Amp-Thread-ID: https://ampcode.com/threads/T-01a19770-5331-74b2-963f-e324ae0f7635
1 parent a2428cc commit 71ee6b4

6 files changed

Lines changed: 22 additions & 12 deletions

‎phpstan-baseline.neon‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,19 +1784,19 @@ parameters:
17841784
path: tests/PHPStan/Node/FileNodeTest.php
17851785

17861786
-
1787-
rawMessage: Access to constant class of internal class InternalAnnotations\InternalFoo from outside its root namespace InternalAnnotations.
1787+
rawMessage: Access to constant on internal class InternalAnnotations\InternalFoo.
17881788
identifier: classConstant.internalClass
17891789
count: 1
17901790
path: tests/PHPStan/Reflection/Annotations/InternalAnnotationsTest.php
17911791

17921792
-
1793-
rawMessage: Access to constant class of internal interface InternalAnnotations\InternalFooInterface from outside its root namespace InternalAnnotations.
1793+
rawMessage: Access to constant on internal interface InternalAnnotations\InternalFooInterface.
17941794
identifier: classConstant.internalInterface
17951795
count: 1
17961796
path: tests/PHPStan/Reflection/Annotations/InternalAnnotationsTest.php
17971797

17981798
-
1799-
rawMessage: Access to constant class of internal trait InternalAnnotations\InternalFooTrait from outside its root namespace InternalAnnotations.
1799+
rawMessage: Access to constant on internal trait InternalAnnotations\InternalFooTrait.
18001800
identifier: classConstant.internalTrait
18011801
count: 1
18021802
path: tests/PHPStan/Reflection/Annotations/InternalAnnotationsTest.php
@@ -1820,7 +1820,7 @@ parameters:
18201820
path: tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php
18211821

18221822
-
1823-
rawMessage: Access to constant class of internal class PHPUnit\Framework\AssertionFailedError from outside its root namespace PHPUnit.
1823+
rawMessage: Access to constant on internal class PHPUnit\Framework\AssertionFailedError.
18241824
identifier: classConstant.internalClass
18251825
count: 2
18261826
path: tests/PHPStan/Testing/TypeInferenceTestCaseTest.php

‎src/Rules/ClassNameUsageLocation.php‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use PHPStan\Reflection\ExtendedMethodReflection;
77
use PHPStan\Reflection\ExtendedPropertyReflection;
88
use PHPStan\Reflection\FunctionReflection;
9+
use PHPStan\Rules\RestrictedUsage\ClassNameConstantReflection;
910
use function sprintf;
1011
use function ucfirst;
1112

@@ -153,7 +154,8 @@ public function createMessage(string $part): string
153154
case self::EXCEPTION_CATCH:
154155
return sprintf('Catching %s.', $part);
155156
case self::CLASS_CONSTANT_ACCESS:
156-
if ($this->getClassConstant() !== null) {
157+
// Foo::class is reported as a usage of the class name, as before it was passed to the extensions
158+
if ($this->getClassConstant() !== null && !$this->getClassConstant() instanceof ClassNameConstantReflection) {
157159
return sprintf('Access to constant %s on %s.', $this->getClassConstant()->getName(), $part);
158160
}
159161
return sprintf('Access to constant on %s.', $part);

‎src/Rules/InternalTag/RestrictedInternalClassConstantUsageExtension.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPStan\Analyser\Scope;
66
use PHPStan\Reflection\ClassConstantReflection;
7+
use PHPStan\Rules\RestrictedUsage\ClassNameConstantReflection;
78
use PHPStan\Rules\RestrictedUsage\RestrictedClassConstantUsageExtension;
89
use PHPStan\Rules\RestrictedUsage\RestrictedUsage;
910
use function sprintf;
@@ -21,6 +22,11 @@ public function isRestrictedClassConstantUsage(
2122
Scope $scope,
2223
): ?RestrictedUsage
2324
{
25+
// Foo::class is reported as an internal class name usage
26+
if ($constantReflection instanceof ClassNameConstantReflection) {
27+
return null;
28+
}
29+
2430
$isConstantInternal = $constantReflection->isInternal()->yes();
2531
$declaringClass = $constantReflection->getDeclaringClass();
2632
$isDeclaringClassInternal = $declaringClass->isInternal();

‎src/Rules/InternalTag/RestrictedInternalClassNameUsageExtension.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPStan\Analyser\Scope;
66
use PHPStan\Reflection\ClassReflection;
77
use PHPStan\Rules\ClassNameUsageLocation;
8+
use PHPStan\Rules\RestrictedUsage\ClassNameConstantReflection;
89
use PHPStan\Rules\RestrictedUsage\RestrictedClassNameUsageExtension;
910
use PHPStan\Rules\RestrictedUsage\RestrictedUsage;
1011
use function sprintf;
@@ -53,7 +54,7 @@ public function isRestrictedClassNameUsage(
5354

5455
if ($location->value === ClassNameUsageLocation::CLASS_CONSTANT_ACCESS) {
5556
$constant = $location->getClassConstant();
56-
if ($constant !== null) {
57+
if ($constant !== null && !$constant instanceof ClassNameConstantReflection) {
5758
if ($constant->isInternal()->yes() || $constant->getDeclaringClass()->isInternal()) {
5859
return null;
5960
}

‎tests/PHPStan/Rules/Classes/ClassConstantRuleTest.php‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,8 +638,13 @@ public function testClosureAttributeArguments(): void
638638

639639
public function testInternalClassConstantAccessIsReportedOnce(): void
640640
{
641-
// reported by RestrictedClassConstantUsageRule, including Foo::class
642-
$this->analyse([__DIR__ . '/../InternalTag/data/class-constant-internal-tag.php'], []);
641+
// constants are reported by RestrictedClassConstantUsageRule, Foo::class as an internal class name usage here
642+
$this->analyse([__DIR__ . '/../InternalTag/data/class-constant-internal-tag.php'], [
643+
[
644+
'Access to constant on internal class ClassConstantInternalTagOne\\FooInternal.',
645+
115,
646+
],
647+
]);
643648
}
644649

645650
}

‎tests/PHPStan/Rules/InternalTag/RestrictedInternalClassConstantUsageExtensionTest.php‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ public function testRule(): void
5353
'Access to constant FOO of internal class FooInternalWithClassConstantWithoutNamespace.',
5454
107,
5555
],
56-
[
57-
'Access to constant class of internal class ClassConstantInternalTagOne\\FooInternal from outside its root namespace ClassConstantInternalTagOne.',
58-
115,
59-
],
6056
]);
6157
}
6258

0 commit comments

Comments
 (0)