Skip to content

Commit

Permalink
Do not trigger PhpDocInheritanceResolver if we do not need the PHPDoc…
Browse files Browse the repository at this point in the history
… type when resolving the type of ClassConstFetch
  • Loading branch information
VincentLanglet authored and ondrejmirtes committed Sep 29, 2023
1 parent 25f4e5e commit dcfa3b1
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 10 deletions.
1 change: 1 addition & 0 deletions build/phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ parameters:
count: 1
path: ../src/Command/CommandHelper.php
- '#^Parameter \#1 \$offsetType of class PHPStan\\Type\\Accessory\\HasOffsetType constructor expects PHPStan\\Type\\Constant\\ConstantIntegerType\|PHPStan\\Type\\Constant\\ConstantStringType#'
- '#^Short ternary operator is not allowed#'
reportStaticMethodSignatures: true
tmpDir: %rootDir%/tmp
stubFiles:
Expand Down
8 changes: 6 additions & 2 deletions src/PhpDoc/TypeNodeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -1046,9 +1046,13 @@ private function resolveConstTypeNode(ConstTypeNode $typeNode, NameScope $nameSc
return new EnumCaseObjectType($classReflection->getName(), $constantName);
}

$reflectionConstant = $classReflection->getConstant($constantName);
$reflectionConstant = $classReflection->getNativeReflection()->getReflectionConstant($constantName);
if ($reflectionConstant === false) {
return new ErrorType();
}
$declaringClass = $reflectionConstant->getDeclaringClass();

return $this->initializerExprTypeResolver->getType($reflectionConstant->getValueExpr(), InitializerExprContext::fromClassReflection($reflectionConstant->getDeclaringClass()));
return $this->initializerExprTypeResolver->getType($reflectionConstant->getValueExpression(), InitializerExprContext::fromClass($declaringClass->getName(), $declaringClass->getFileName() ?: null));
}

if ($constExpr instanceof ConstExprFloatNode) {
Expand Down
7 changes: 5 additions & 2 deletions src/Reflection/InitializerExprContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,13 @@ private static function parseNamespace(string $name): ?string

public static function fromClassReflection(ClassReflection $classReflection): self
{
$className = $classReflection->getName();
return self::fromClass($classReflection->getName(), $classReflection->getFileName());
}

public static function fromClass(string $className, ?string $fileName): self
{
return new self(
$classReflection->getFileName(),
$fileName,
self::parseNamespace($className),
$className,
null,
Expand Down
22 changes: 16 additions & 6 deletions src/Reflection/InitializerExprTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -1876,22 +1876,32 @@ function (Type $type, callable $traverse): Type {
continue;
}

if (!$isObject) {
$reflectionConstant = $constantClassReflection->getNativeReflection()->getReflectionConstant($constantName);
if ($reflectionConstant === false) {
continue;
}
$reflectionConstantDeclaringClass = $reflectionConstant->getDeclaringClass();

Check failure on line 1884 in src/Reflection/InitializerExprTypeResolver.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, ubuntu-latest)

Call to method getReflectionConstant() on an unknown class PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum.

Check failure on line 1884 in src/Reflection/InitializerExprTypeResolver.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, windows-latest)

Call to method getReflectionConstant() on an unknown class PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum.
$constantType = $this->getType($reflectionConstant->getValueExpression(), InitializerExprContext::fromClass($reflectionConstantDeclaringClass->getName(), $reflectionConstantDeclaringClass->getFileName() ?: null));
$types[] = $this->constantResolver->resolveConstantType(
sprintf('%s::%s', $constantClassReflection->getName(), $constantName),
$constantType,
);
continue;
}

$constantReflection = $constantClassReflection->getConstant($constantName);
if (
$constantReflection instanceof ClassConstantReflection
&& $isObject
&& !$constantClassReflection->isFinal()
&& !$constantReflection->hasPhpDocType()
) {
return new MixedType();
}

if (
$isObject
&& (
!$constantReflection instanceof ClassConstantReflection
|| !$constantClassReflection->isFinal()
)
!$constantReflection instanceof ClassConstantReflection
|| !$constantClassReflection->isFinal()
) {
$constantType = $constantReflection->getValueType();
} else {
Expand Down
7 changes: 7 additions & 0 deletions tests/PHPStan/Analyser/AnalyserIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,13 @@ public function testBug9459(): void
$this->assertSame(10, $errors[0]->getLine());
}

public function testBug9039(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9039.php');
$this->assertCount(1, $errors);
$this->assertSame('Constant Bug9039\Test::RULES is unused.', $errors[0]->getMessage());
}

public function testDiscussion9053(): void
{
if (PHP_VERSION_ID < 80000) {
Expand Down
19 changes: 19 additions & 0 deletions tests/PHPStan/Analyser/data/bug-9039.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php declare(strict_types = 1);

namespace Bug9039;

/**
* @template T
*/
class Voter
{
}

/**
* @template-extends Voter<self::*>
*/
class Test extends Voter
{
public const FOO = 'Foo';
private const RULES = [self::FOO];
}

0 comments on commit dcfa3b1

Please sign in to comment.