Skip to content

Commit 7aabc84

Browse files
committed
[BCB] StaticType and ThisType - require ClassReflection in constructor
1 parent 36f197f commit 7aabc84

14 files changed

+161
-147
lines changed

src/Analyser/MutatingScope.php

+7-2
Original file line numberDiff line numberDiff line change
@@ -2631,7 +2631,9 @@ public function resolveTypeByName(Name $name): TypeWithClassName
26312631
{
26322632
if ($name->toLowerString() === 'static' && $this->isInClass()) {
26332633
if ($this->inClosureBindScopeClass !== null && $this->inClosureBindScopeClass !== 'static') {
2634-
return new StaticType($this->inClosureBindScopeClass);
2634+
if ($this->reflectionProvider->hasClass($this->inClosureBindScopeClass)) {
2635+
return new StaticType($this->reflectionProvider->getClass($this->inClosureBindScopeClass));
2636+
}
26352637
}
26362638

26372639
return new StaticType($this->getClassReflection());
@@ -2640,7 +2642,10 @@ public function resolveTypeByName(Name $name): TypeWithClassName
26402642
$originalClass = $this->resolveName($name);
26412643
if ($this->isInClass()) {
26422644
if ($this->inClosureBindScopeClass !== null && $this->inClosureBindScopeClass !== 'static') {
2643-
$thisType = new ThisType($this->inClosureBindScopeClass);
2645+
if ($this->reflectionProvider->hasClass($this->inClosureBindScopeClass)) {
2646+
return new ThisType($this->reflectionProvider->getClass($this->inClosureBindScopeClass));
2647+
}
2648+
$thisType = new ThisType($this->getClassReflection());
26442649
} else {
26452650
$thisType = new ThisType($this->getClassReflection());
26462651
}

src/PhpDoc/TypeNodeResolver.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,13 @@ private function resolveIdentifierTypeNode(IdentifierTypeNode $typeNode, NameSco
302302
return new ObjectType($nameScope->getClassName());
303303

304304
case 'static':
305-
return new StaticType($nameScope->getClassName());
305+
if ($this->getReflectionProvider()->hasClass($nameScope->getClassName())) {
306+
$classReflection = $this->getReflectionProvider()->getClass($nameScope->getClassName());
306307

308+
return new StaticType($classReflection);
309+
}
310+
311+
return new ErrorType();
307312
case 'parent':
308313
if ($this->getReflectionProvider()->hasClass($nameScope->getClassName())) {
309314
$classReflection = $this->getReflectionProvider()->getClass($nameScope->getClassName());

src/Type/ObjectType.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public function getReferencedClasses(): array
200200
public function accepts(Type $type, bool $strictTypes): TrinaryLogic
201201
{
202202
if ($type instanceof StaticType) {
203-
return $this->checkSubclassAcceptability($type->getBaseClass());
203+
return $this->checkSubclassAcceptability($type->getClassName());
204204
}
205205

206206
if ($type instanceof CompoundType) {

src/Type/ParserNodeTypeToPHPStanType.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ public static function resolve($type, ?ClassReflection $classReflection): Type
2323
$typeClassName = (string) $type;
2424
$lowercasedClassName = strtolower($typeClassName);
2525
if ($classReflection !== null && in_array($lowercasedClassName, ['self', 'static'], true)) {
26+
if ($lowercasedClassName === 'static') {
27+
return new StaticType($classReflection);
28+
}
2629
$typeClassName = $classReflection->getName();
2730
} elseif (
2831
$lowercasedClassName === 'parent'
@@ -32,10 +35,6 @@ public static function resolve($type, ?ClassReflection $classReflection): Type
3235
$typeClassName = $classReflection->getParentClass()->getName();
3336
}
3437

35-
if ($lowercasedClassName === 'static') {
36-
return new StaticType($typeClassName);
37-
}
38-
3938
return new ObjectType($typeClassName);
4039
} elseif ($type instanceof NullableType) {
4140
return TypeCombinator::addNull(self::resolve($type->type, $classReflection));

src/Type/StaticType.php

+19-35
Original file line numberDiff line numberDiff line change
@@ -25,32 +25,17 @@ class StaticType implements TypeWithClassName
2525
use NonGenericTypeTrait;
2626
use UndecidedComparisonTypeTrait;
2727

28-
private ?ClassReflection $classReflection;
28+
private ClassReflection $classReflection;
2929

3030
private ?\PHPStan\Type\ObjectType $staticObjectType = null;
3131

3232
private string $baseClass;
3333

3434
/**
3535
* @api
36-
* @param string|ClassReflection $classReflection
3736
*/
38-
public function __construct($classReflection)
39-
{
40-
if (is_string($classReflection)) {
41-
$broker = Broker::getInstance();
42-
if ($broker->hasClass($classReflection)) {
43-
$classReflection = $broker->getClass($classReflection);
44-
$this->classReflection = $classReflection;
45-
$this->baseClass = $classReflection->getName();
46-
return;
47-
}
48-
49-
$this->classReflection = null;
50-
$this->baseClass = $classReflection;
51-
return;
52-
}
53-
37+
public function __construct(ClassReflection $classReflection)
38+
{
5439
$this->classReflection = $classReflection;
5540
$this->baseClass = $classReflection->getName();
5641
}
@@ -72,13 +57,18 @@ public function getAncestorWithClassName(string $className): ?TypeWithClassName
7257
return null;
7358
}
7459

75-
return $this->changeBaseClass($ancestor->getClassReflection() ?? $ancestor->getClassName());
60+
$classReflection = $ancestor->getClassReflection();
61+
if ($classReflection !== null) {
62+
return $this->changeBaseClass($classReflection);
63+
}
64+
65+
return null;
7666
}
7767

7868
public function getStaticObjectType(): ObjectType
7969
{
8070
if ($this->staticObjectType === null) {
81-
if ($this->classReflection !== null && $this->classReflection->isGeneric()) {
71+
if ($this->classReflection->isGeneric()) {
8272
$typeMap = $this->classReflection->getActiveTemplateTypeMap()->map(static function (string $name, Type $type): Type {
8373
return TemplateTypeHelper::toArgument($type);
8474
});
@@ -88,7 +78,7 @@ public function getStaticObjectType(): ObjectType
8878
);
8979
}
9080

91-
return $this->staticObjectType = new ObjectType($this->baseClass, null, $this->classReflection);
81+
return $this->staticObjectType = new ObjectType($this->classReflection->getName(), null, $this->classReflection);
9282
}
9383

9484
return $this->staticObjectType;
@@ -102,11 +92,6 @@ public function getReferencedClasses(): array
10292
return $this->getStaticObjectType()->getReferencedClasses();
10393
}
10494

105-
public function getBaseClass(): string
106-
{
107-
return $this->baseClass;
108-
}
109-
11095
public function accepts(Type $type, bool $strictTypes): TrinaryLogic
11196
{
11297
if ($type instanceof CompoundType) {
@@ -247,9 +232,7 @@ private function transformStaticType(Type $type, ClassMemberAccessAnswerer $scop
247232
if ($type instanceof StaticType) {
248233
$classReflection = $this->classReflection;
249234
$isFinal = false;
250-
if ($classReflection === null) {
251-
$classReflection = $this->baseClass;
252-
} elseif ($scope->isInClass()) {
235+
if ($scope->isInClass()) {
253236
$classReflection = $scope->getClassReflection();
254237
$isFinal = $classReflection->isFinal();
255238
}
@@ -280,11 +263,7 @@ public function getConstant(string $constantName): ConstantReflection
280263
return $this->getStaticObjectType()->getConstant($constantName);
281264
}
282265

283-
/**
284-
* @param ClassReflection|string $classReflection
285-
* @return self
286-
*/
287-
public function changeBaseClass($classReflection): self
266+
public function changeBaseClass(ClassReflection $classReflection): self
288267
{
289268
return new self($classReflection);
290269
}
@@ -409,7 +388,12 @@ public function traverse(callable $cb): Type
409388
*/
410389
public static function __set_state(array $properties): Type
411390
{
412-
return new self($properties['baseClass']);
391+
$broker = Broker::getInstance();
392+
if ($broker->hasClass($properties['baseClass'])) {
393+
return new self($broker->getClass($properties['baseClass']));
394+
}
395+
396+
return new ErrorType();
413397
}
414398

415399
}

src/Type/ThisType.php

+17-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Type;
44

5+
use PHPStan\Broker\Broker;
56
use PHPStan\Reflection\ClassReflection;
67

78
/** @api */
@@ -10,18 +11,13 @@ class ThisType extends StaticType
1011

1112
/**
1213
* @api
13-
* @param string|ClassReflection $classReflection
1414
*/
15-
public function __construct($classReflection)
15+
public function __construct(ClassReflection $classReflection)
1616
{
1717
parent::__construct($classReflection);
1818
}
1919

20-
/**
21-
* @param ClassReflection|string $classReflection
22-
* @return self
23-
*/
24-
public function changeBaseClass($classReflection): StaticType
20+
public function changeBaseClass(ClassReflection $classReflection): StaticType
2521
{
2622
return new self($classReflection);
2723
}
@@ -31,4 +27,18 @@ public function describe(VerbosityLevel $level): string
3127
return sprintf('$this(%s)', $this->getClassName());
3228
}
3329

30+
/**
31+
* @param mixed[] $properties
32+
* @return Type
33+
*/
34+
public static function __set_state(array $properties): Type
35+
{
36+
$broker = Broker::getInstance();
37+
if ($broker->hasClass($properties['baseClass'])) {
38+
return new self($broker->getClass($properties['baseClass']));
39+
}
40+
41+
return new ErrorType();
42+
}
43+
3444
}

src/Type/TypehintHelper.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ private static function getTypeObjectFromTypehint(string $typeString, ?string $s
4949
}
5050
return new NonexistentParentClassType();
5151
case 'static':
52-
return $selfClass !== null ? new StaticType($selfClass) : new ErrorType();
52+
$broker = Broker::getInstance();
53+
if ($selfClass !== null && $broker->hasClass($selfClass)) {
54+
return new StaticType($broker->getClass($selfClass));
55+
}
56+
57+
return new ErrorType();
5358
case 'null':
5459
return new NullType();
5560
default:

tests/PHPStan/Reflection/SignatureMap/SignatureMapParserTest.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class SignatureMapParserTest extends \PHPStan\Testing\PHPStanTestCase
2323

2424
public function dataGetFunctions(): array
2525
{
26+
$reflectionProvider = $this->createReflectionProvider();
2627
return [
2728
[
2829
['int', 'fp' => 'resource', 'fields' => 'array', 'delimiter=' => 'string', 'enclosure=' => 'string', 'escape_char=' => 'string'],
@@ -323,7 +324,7 @@ public function dataGetFunctions(): array
323324
false
324325
),
325326
],
326-
new StaticType(\DateTime::class),
327+
new StaticType($reflectionProvider->getClass(\DateTime::class)),
327328
new MixedType(),
328329
false
329330
),

tests/PHPStan/Type/Constant/ConstantStringTypeTest.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class ConstantStringTypeTest extends PHPStanTestCase
1919

2020
public function dataIsSuperTypeOf(): array
2121
{
22+
$reflectionProvider = $this->createReflectionProvider();
2223
return [
2324
0 => [
2425
new ConstantStringType(\Exception::class),
@@ -112,17 +113,17 @@ public function dataIsSuperTypeOf(): array
112113
],
113114
13 => [
114115
new ConstantStringType(\Exception::class),
115-
new GenericClassStringType(new StaticType(\Exception::class)),
116+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\Exception::class))),
116117
TrinaryLogic::createMaybe(),
117118
],
118119
14 => [
119120
new ConstantStringType(\Exception::class),
120-
new GenericClassStringType(new StaticType(\InvalidArgumentException::class)),
121+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\InvalidArgumentException::class))),
121122
TrinaryLogic::createNo(),
122123
],
123124
15 => [
124125
new ConstantStringType(\Exception::class),
125-
new GenericClassStringType(new StaticType(\Throwable::class)),
126+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\Throwable::class))),
126127
TrinaryLogic::createMaybe(),
127128
],
128129
];

tests/PHPStan/Type/Generic/GenericClassStringTypeTest.php

+11-7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class GenericClassStringTypeTest extends \PHPStan\Testing\PHPStanTestCase
2020

2121
public function dataIsSuperTypeOf(): array
2222
{
23+
$reflectionProvider = $this->createReflectionProvider();
24+
2325
return [
2426
0 => [
2527
new GenericClassStringType(new ObjectType(\Exception::class)),
@@ -122,17 +124,17 @@ public function dataIsSuperTypeOf(): array
122124
TrinaryLogic::createNo(),
123125
],
124126
15 => [
125-
new GenericClassStringType(new StaticType(\Exception::class)),
127+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\Exception::class))),
126128
new ConstantStringType(\Exception::class),
127129
TrinaryLogic::createYes(),
128130
],
129131
16 => [
130-
new GenericClassStringType(new StaticType(\InvalidArgumentException::class)),
132+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\InvalidArgumentException::class))),
131133
new ConstantStringType(\Exception::class),
132134
TrinaryLogic::createNo(),
133135
],
134136
17 => [
135-
new GenericClassStringType(new StaticType(\Throwable::class)),
137+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\Throwable::class))),
136138
new ConstantStringType(\Exception::class),
137139
TrinaryLogic::createYes(),
138140
],
@@ -275,6 +277,8 @@ public function testAccepts(
275277

276278
public function dataEquals(): array
277279
{
280+
$reflectionProvider = $this->createReflectionProvider();
281+
278282
return [
279283
[
280284
new GenericClassStringType(new ObjectType(\Exception::class)),
@@ -287,13 +291,13 @@ public function dataEquals(): array
287291
false,
288292
],
289293
[
290-
new GenericClassStringType(new StaticType(\Exception::class)),
291-
new GenericClassStringType(new StaticType(\Exception::class)),
294+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\Exception::class))),
295+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\Exception::class))),
292296
true,
293297
],
294298
[
295-
new GenericClassStringType(new StaticType(\Exception::class)),
296-
new GenericClassStringType(new StaticType(\stdClass::class)),
299+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\Exception::class))),
300+
new GenericClassStringType(new StaticType($reflectionProvider->getClass(\stdClass::class))),
297301
false,
298302
],
299303
];

0 commit comments

Comments
 (0)