diff --git a/src/Rules/Classes/ClassConstantRule.php b/src/Rules/Classes/ClassConstantRule.php index 5aac4239f5..a1a517c0d5 100644 --- a/src/Rules/Classes/ClassConstantRule.php +++ b/src/Rules/Classes/ClassConstantRule.php @@ -13,6 +13,7 @@ use PHPStan\Type\ErrorType; use PHPStan\Type\ObjectType; use PHPStan\Type\StringType; +use PHPStan\Type\ThisType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\VerbosityLevel; @@ -106,7 +107,11 @@ public function processNode(Node $node, Scope $scope): array $className = $this->reflectionProvider->getClass($className)->getName(); } - $classType = new ObjectType($className); + if ($scope->isInClass() && $scope->getClassReflection()->getName() === $className) { + $classType = new ThisType($scope->getClassReflection()); + } else { + $classType = new ObjectType($className); + } } else { $classTypeResult = $this->ruleLevelHelper->findTypeToCheck( $scope, @@ -127,6 +132,9 @@ static function (Type $type) use ($constantName): bool { } $typeForDescribe = $classType; + if ($classType instanceof ThisType) { + $typeForDescribe = $classType->getStaticObjectType(); + } $classType = TypeCombinator::remove($classType, new StringType()); if (!$classType->canAccessConstants()->yes()) { diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index ddf0a089a7..ffd596d16a 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -208,18 +208,22 @@ public function testBug2823(): void public function testTwoSameClassesInSingleFile(): void { $errors = $this->runAnalyse(__DIR__ . '/data/two-same-classes.php'); - $this->assertCount(3, $errors); + $this->assertCount(4, $errors); $error = $errors[0]; $this->assertSame('Property TwoSame\Foo::$prop (string) does not accept default value of type int.', $error->getMessage()); $this->assertSame(9, $error->getLine()); $error = $errors[1]; - $this->assertSame('Property TwoSame\Foo::$prop (int) does not accept default value of type string.', $error->getMessage()); - $this->assertSame(18, $error->getLine()); + $this->assertSame('Access to undefined constant TwoSame\Foo::FOO_CONST.', $error->getMessage()); + $this->assertSame(13, $error->getLine()); $error = $errors[2]; + $this->assertSame('Property TwoSame\Foo::$prop (int) does not accept default value of type string.', $error->getMessage()); + $this->assertSame(25, $error->getLine()); + + $error = $errors[3]; $this->assertSame('Property TwoSame\Foo::$prop2 (int) does not accept default value of type string.', $error->getMessage()); - $this->assertSame(21, $error->getLine()); + $this->assertSame(28, $error->getLine()); } public function testBug3405(): void diff --git a/tests/PHPStan/Analyser/data/two-same-classes.php b/tests/PHPStan/Analyser/data/two-same-classes.php index bd5043fcc5..a5cf574043 100644 --- a/tests/PHPStan/Analyser/data/two-same-classes.php +++ b/tests/PHPStan/Analyser/data/two-same-classes.php @@ -8,17 +8,29 @@ class Foo /** @var string */ private $prop = 1; + public function doFoo(): void + { + echo self::FOO_CONST; + } + } if (rand(0, 0)) { class Foo { + private const FOO_CONST = 'foo'; + /** @var int */ private $prop = 'str'; /** @var int */ private $prop2 = 'str'; + public function doFoo(): void + { + echo self::FOO_CONST; + } + } }