Skip to content

Commit f18c7a9

Browse files
committed
Allow setting types for dynamic constants
1 parent 566cd60 commit f18c7a9

15 files changed

+81
-5
lines changed

src/Analyser/ConstantResolver.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,14 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type
302302

303303
public function resolveConstantType(string $constantName, Type $constantType): Type
304304
{
305-
if ($constantType->isConstantValue()->yes() && in_array($constantName, $this->dynamicConstantNames, true)) {
306-
return $constantType->generalize(GeneralizePrecision::lessSpecific());
305+
if ($constantType->isConstantValue()->yes()) {
306+
if (array_key_exists($constantName, $this->dynamicConstantNames)) {
307+
$phpdocTypes = $this->dynamicConstantNames[$constantName];
308+
return $this->reflectionProviderProvider->getReflectionProvider()->getSignatureMapProvider()->getTypeFromString($phpdocTypes, null);
309+
}
310+
if (in_array($constantName, $this->dynamicConstantNames, true)) {
311+
return $constantType->generalize(GeneralizePrecision::lessSpecific());
312+
}
307313
}
308314

309315
return $constantType;
@@ -312,6 +318,17 @@ public function resolveConstantType(string $constantName, Type $constantType): T
312318
public function resolveClassConstantType(string $className, string $constantName, Type $constantType, ?Type $nativeType): Type
313319
{
314320
$lookupConstantName = sprintf('%s::%s', $className, $constantName);
321+
if (array_key_exists($lookupConstantName, $this->dynamicConstantNames)) {
322+
if ($nativeType !== null) {
323+
return $nativeType;
324+
}
325+
326+
if ($constantType->isConstantValue()->yes()) {
327+
$phpdocTypes = $this->dynamicConstantNames[$lookupConstantName];
328+
return $this->getReflectionProvider()->getSignatureMapProvider()->getTypeFromString($phpdocTypes, $className);
329+
}
330+
}
331+
315332
if (in_array($lookupConstantName, $this->dynamicConstantNames, true)) {
316333
if ($nativeType !== null) {
317334
return $nativeType;

src/Analyser/MutatingScope.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5701,6 +5701,11 @@ public function getConstantReflection(Type $typeWithConstant, string $constantNa
57015701
return $typeWithConstant->getConstant($constantName);
57025702
}
57035703

5704+
public function getConstantExplicitTypeFromConfig(string $constantName, Type $constantType): ?Type
5705+
{
5706+
return $this->constantResolver->resolveConstantType($constantName, $constantType);
5707+
}
5708+
57045709
/**
57055710
* @return array<string, ExpressionTypeHolder>
57065711
*/

src/Analyser/Scope.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ public function getMethodReflection(Type $typeWithMethod, string $methodName): ?
8080

8181
public function getConstantReflection(Type $typeWithConstant, string $constantName): ?ClassConstantReflection;
8282

83+
public function getConstantExplicitTypeFromConfig(string $constantName, Type $constantType): ?Type;
84+
8385
public function getIterableKeyType(Type $iteratee): Type;
8486

8587
public function getIterableValueType(Type $iteratee): Type;

src/Reflection/BetterReflection/BetterReflectionProvider.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,4 +475,9 @@ private function resolveName(
475475
return null;
476476
}
477477

478+
public function getSignatureMapProvider(): SignatureMapProvider
479+
{
480+
return $this->signatureMapProvider;
481+
}
482+
478483
}

src/Reflection/ClassReflection.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ public function getNativeReflection(): ReflectionClass|ReflectionEnum
177177
return $this->reflection;
178178
}
179179

180+
public function getSignatureMapProvider(): SignatureMapProvider
181+
{
182+
return $this->signatureMapProvider;
183+
}
184+
180185
public function getFileName(): ?string
181186
{
182187
if (!is_bool($this->filename)) {

src/Reflection/ReflectionProvider.php

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

55
use PhpParser\Node;
66
use PHPStan\Analyser\Scope;
7+
use PHPStan\Reflection\SignatureMap\SignatureMapProvider;
78

89
/** @api */
910
interface ReflectionProvider
@@ -36,4 +37,6 @@ public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAn
3637

3738
public function resolveConstantName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): ?string;
3839

40+
public function getSignatureMapProvider(): SignatureMapProvider;
41+
3942
}

src/Reflection/ReflectionProvider/DummyReflectionProvider.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PHPStan\Reflection\FunctionReflection;
1010
use PHPStan\Reflection\NamespaceAnswerer;
1111
use PHPStan\Reflection\ReflectionProvider;
12+
use PHPStan\Reflection\SignatureMap\SignatureMapProvider;
1213
use PHPStan\ShouldNotHappenException;
1314

1415
final class DummyReflectionProvider implements ReflectionProvider
@@ -69,4 +70,8 @@ public function resolveConstantName(Node\Name $nameNode, ?NamespaceAnswerer $nam
6970
return null;
7071
}
7172

73+
public function getSignatureMapProvider(): SignatureMapProvider
74+
{
75+
throw new ShouldNotHappenException();
76+
}
7277
}

src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use PHPStan\Reflection\FunctionReflection;
1010
use PHPStan\Reflection\NamespaceAnswerer;
1111
use PHPStan\Reflection\ReflectionProvider;
12+
use PHPStan\Reflection\SignatureMap\SignatureMapProvider;
13+
1214
use function strtolower;
1315

1416
final class MemoizingReflectionProvider implements ReflectionProvider
@@ -96,4 +98,9 @@ public function resolveConstantName(Node\Name $nameNode, ?NamespaceAnswerer $nam
9698
return $this->provider->resolveConstantName($nameNode, $namespaceAnswerer);
9799
}
98100

101+
public function getSignatureMapProvider(): SignatureMapProvider
102+
{
103+
return $this->provider->getSignatureMapProvider();
104+
}
105+
99106
}

src/Reflection/SignatureMap/FunctionSignatureMapProvider.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PHPStan\Reflection\InitializerExprTypeResolver;
1010
use PHPStan\ShouldNotHappenException;
1111
use PHPStan\Type\MixedType;
12+
use PHPStan\Type\Type;
1213
use PHPStan\Type\TypehintHelper;
1314
use ReflectionFunctionAbstract;
1415
use function array_change_key_case;
@@ -259,4 +260,8 @@ public function getClassConstantMetadata(string $className, string $constantName
259260
throw new ShouldNotHappenException();
260261
}
261262

263+
public function getTypeFromString(string $typeString, ?string $className): Type
264+
{
265+
return $this->parser->getTypeFromString($typeString, $className);
266+
}
262267
}

src/Reflection/SignatureMap/Php8SignatureMapProvider.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,4 +499,8 @@ private function findConstantType(string $className, string $constantName): ?Typ
499499
return null;
500500
}
501501

502+
public function getTypeFromString(string $typeString, ?string $className): Type
503+
{
504+
return $this->functionSignatureMapProvider->getTypeFromString($typeString, $className);
505+
}
502506
}

0 commit comments

Comments
 (0)