Skip to content

Commit 2944cd7

Browse files
committed
Deprecated instanceof GenericClassStringType, introduce Type::getClassStringObjectType()
1 parent 0531236 commit 2944cd7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+484
-178
lines changed

phpstan-baseline.neon

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,6 @@ parameters:
5656
count: 3
5757
path: src/Analyser/NodeScopeResolver.php
5858

59-
-
60-
message: "#^Parameter \\#11 \\$reflection of class PHPStan\\\\Reflection\\\\ClassReflection constructor expects PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionClass\\|PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum, object given\\.$#"
61-
count: 1
62-
path: src/Analyser/NodeScopeResolver.php
63-
6459
-
6560
message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#"
6661
count: 1
@@ -274,11 +269,6 @@ parameters:
274269
count: 1
275270
path: src/Reflection/BetterReflection/BetterReflectionProvider.php
276271

277-
-
278-
message: "#^Parameter \\#11 \\$reflection of class PHPStan\\\\Reflection\\\\ClassReflection constructor expects PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionClass\\|PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum, object given\\.$#"
279-
count: 1
280-
path: src/Reflection/BetterReflection/BetterReflectionProvider.php
281-
282272
-
283273
message: """
284274
#^Call to deprecated method getTypeFromValue\\(\\) of class PHPStan\\\\Type\\\\ConstantTypeHelper\\:
@@ -332,6 +322,11 @@ parameters:
332322
count: 1
333323
path: src/Reflection/BetterReflection/SourceLocator/SkipClassAliasSourceLocator.php
334324

325+
-
326+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#"
327+
count: 3
328+
path: src/Reflection/ClassReflection.php
329+
335330
-
336331
message: "#^Method PHPStan\\\\Reflection\\\\ClassReflection\\:\\:getCacheKey\\(\\) should return string but returns string\\|null\\.$#"
337332
count: 1
@@ -533,11 +528,6 @@ parameters:
533528
count: 1
534529
path: src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php
535530

536-
-
537-
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#"
538-
count: 1
539-
path: src/Rules/DeadCode/UnusedPrivateMethodRule.php
540-
541531
-
542532
message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#"
543533
count: 1
@@ -563,6 +553,11 @@ parameters:
563553
count: 1
564554
path: src/Rules/DirectRegistry.php
565555

556+
-
557+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#"
558+
count: 1
559+
path: src/Rules/Generics/GenericAncestorsCheck.php
560+
566561
-
567562
message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#"
568563
count: 1
@@ -598,6 +593,16 @@ parameters:
598593
count: 1
599594
path: src/Rules/Methods/MethodParameterComparisonHelper.php
600595

596+
-
597+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#"
598+
count: 1
599+
path: src/Rules/Methods/StaticMethodCallCheck.php
600+
601+
-
602+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#"
603+
count: 1
604+
path: src/Rules/PhpDoc/VarTagTypeRuleHelper.php
605+
601606
-
602607
message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#"
603608
count: 2
@@ -690,7 +695,7 @@ parameters:
690695

691696
-
692697
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#"
693-
count: 7
698+
count: 4
694699
path: src/Type/Constant/ConstantArrayType.php
695700

696701
-
@@ -743,6 +748,11 @@ parameters:
743748
count: 4
744749
path: src/Type/Constant/ConstantStringType.php
745750

751+
-
752+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#"
753+
count: 1
754+
path: src/Type/Constant/ConstantStringType.php
755+
746756
-
747757
message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#"
748758
count: 1
@@ -763,6 +773,11 @@ parameters:
763773
count: 2
764774
path: src/Type/Enum/EnumCaseObjectType.php
765775

776+
-
777+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#"
778+
count: 1
779+
path: src/Type/FileTypeMapper.php
780+
766781
-
767782
message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#"
768783
count: 2
@@ -778,11 +793,21 @@ parameters:
778793
count: 4
779794
path: src/Type/Generic/GenericClassStringType.php
780795

796+
-
797+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#"
798+
count: 4
799+
path: src/Type/Generic/GenericClassStringType.php
800+
781801
-
782802
message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#"
783803
count: 2
784804
path: src/Type/Generic/GenericClassStringType.php
785805

806+
-
807+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#"
808+
count: 2
809+
path: src/Type/Generic/GenericObjectType.php
810+
786811
-
787812
message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#"
788813
count: 1
@@ -823,6 +848,11 @@ parameters:
823848
count: 1
824849
path: src/Type/Generic/TemplateTypeFactory.php
825850

851+
-
852+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#"
853+
count: 1
854+
path: src/Type/Generic/TemplateTypeFactory.php
855+
826856
-
827857
message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#"
828858
count: 1
@@ -904,6 +934,11 @@ parameters:
904934
count: 1
905935
path: src/Type/ObjectType.php
906936

937+
-
938+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#"
939+
count: 1
940+
path: src/Type/ObjectType.php
941+
907942
-
908943
message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#"
909944
count: 6
@@ -999,6 +1034,11 @@ parameters:
9991034
count: 1
10001035
path: src/Type/Php/IsAFunctionTypeSpecifyingExtension.php
10011036

1037+
-
1038+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#"
1039+
count: 2
1040+
path: src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php
1041+
10021042
-
10031043
message: """
10041044
#^Call to deprecated method getTypeFromValue\\(\\) of class PHPStan\\\\Type\\\\ConstantTypeHelper\\:
@@ -1060,10 +1100,10 @@ parameters:
10601100
-
10611101
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#"
10621102
count: 1
1063-
path: src/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.php
1103+
path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php
10641104

10651105
-
1066-
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#"
1106+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#"
10671107
count: 1
10681108
path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php
10691109

@@ -1142,6 +1182,11 @@ parameters:
11421182
count: 1
11431183
path: src/Type/TypeCombinator.php
11441184

1185+
-
1186+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#"
1187+
count: 2
1188+
path: src/Type/TypeCombinator.php
1189+
11451190
-
11461191
message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#"
11471192
count: 1
@@ -1197,6 +1242,11 @@ parameters:
11971242
count: 1
11981243
path: src/Type/UnionType.php
11991244

1245+
-
1246+
message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#"
1247+
count: 1
1248+
path: src/Type/UnionType.php
1249+
12001250
-
12011251
message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#"
12021252
count: 1

src/Analyser/MutatingScope.php

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@
9595
use PHPStan\Type\NonexistentParentClassType;
9696
use PHPStan\Type\NullType;
9797
use PHPStan\Type\ObjectType;
98-
use PHPStan\Type\ObjectWithoutClassType;
9998
use PHPStan\Type\ParserNodeTypeToPHPStanType;
10099
use PHPStan\Type\StaticType;
101100
use PHPStan\Type\StringType;
@@ -1353,7 +1352,7 @@ private function resolveType(string $exprString, Expr $node): Type
13531352
}
13541353

13551354
$exprType = $this->getType($node->class);
1356-
return $this->getTypeToInstantiateForNew($exprType);
1355+
return $exprType->getObjectTypeOrClassStringObjectType();
13571356

13581357
} elseif ($node instanceof Array_) {
13591358
return $this->initializerExprTypeResolver->getArrayType($node, fn (Expr $expr): Type => $this->getType($expr));
@@ -1718,21 +1717,7 @@ private function resolveType(string $exprString, Expr $node): Type
17181717
if ($node->class instanceof Name) {
17191718
$staticMethodCalledOnType = $this->resolveTypeByName($node->class);
17201719
} else {
1721-
$staticMethodCalledOnType = TypeTraverser::map($this->getType($node->class), static function (Type $type, callable $traverse): Type {
1722-
if ($type instanceof UnionType) {
1723-
return $traverse($type);
1724-
}
1725-
1726-
if ($type instanceof GenericClassStringType) {
1727-
return $type->getGenericType();
1728-
}
1729-
1730-
if ($type instanceof ConstantStringType && $type->isClassStringType()->yes()) {
1731-
return new ObjectType($type->getValue());
1732-
}
1733-
1734-
return $type;
1735-
});
1720+
$staticMethodCalledOnType = $this->getType($node->class)->getObjectTypeOrClassStringObjectType();
17361721
}
17371722

17381723
$returnType = $this->methodCallReturnType(
@@ -1821,10 +1806,7 @@ private function resolveType(string $exprString, Expr $node): Type
18211806
if ($node->class instanceof Name) {
18221807
$staticPropertyFetchedOnType = $this->resolveTypeByName($node->class);
18231808
} else {
1824-
$staticPropertyFetchedOnType = $this->getType($node->class);
1825-
if ($staticPropertyFetchedOnType instanceof GenericClassStringType) {
1826-
$staticPropertyFetchedOnType = $staticPropertyFetchedOnType->getGenericType();
1827-
}
1809+
$staticPropertyFetchedOnType = $this->getType($node->class)->getObjectTypeOrClassStringObjectType();
18281810
}
18291811

18301812
$returnType = $this->propertyFetchType(
@@ -4806,38 +4788,6 @@ private function exactInstantiation(New_ $node, string $className): ?Type
48064788
);
48074789
}
48084790

4809-
private function getTypeToInstantiateForNew(Type $type): Type
4810-
{
4811-
if ($type instanceof UnionType) {
4812-
$types = array_map(fn (Type $type) => $this->getTypeToInstantiateForNew($type), $type->getTypes());
4813-
return TypeCombinator::union(...$types);
4814-
}
4815-
4816-
if ($type instanceof IntersectionType) {
4817-
$types = array_map(fn (Type $type) => $this->getTypeToInstantiateForNew($type), $type->getTypes());
4818-
return TypeCombinator::intersect(...$types);
4819-
}
4820-
4821-
if (count($type->getConstantStrings()) > 0) {
4822-
$types = [];
4823-
foreach ($type->getConstantStrings() as $constantString) {
4824-
$types[] = new ObjectType($constantString->getValue());
4825-
}
4826-
4827-
return TypeCombinator::union(...$types);
4828-
}
4829-
4830-
if ($type instanceof GenericClassStringType) {
4831-
return $type->getGenericType();
4832-
}
4833-
4834-
if ($type->isObject()->yes()) {
4835-
return $type;
4836-
}
4837-
4838-
return new ObjectWithoutClassType();
4839-
}
4840-
48414791
/** @api */
48424792
public function getMethodReflection(Type $typeWithMethod, string $methodName): ?ExtendedMethodReflection
48434793
{

src/Analyser/NodeScopeResolver.php

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@
135135
use PHPStan\Type\ErrorType;
136136
use PHPStan\Type\FileTypeMapper;
137137
use PHPStan\Type\GeneralizePrecision;
138-
use PHPStan\Type\Generic\GenericClassStringType;
139138
use PHPStan\Type\Generic\TemplateTypeHelper;
140139
use PHPStan\Type\Generic\TemplateTypeMap;
141140
use PHPStan\Type\IntegerType;
@@ -2217,20 +2216,9 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra
22172216
$thisTypes[] = new ObjectType($directClassName);
22182217
}
22192218
$thisType = TypeCombinator::union(...$thisTypes);
2220-
} elseif (count($argValueType->getConstantStrings()) > 0) {
2221-
$thisTypes = [];
2222-
foreach ($argValueType->getConstantStrings() as $constantString) {
2223-
$scopeClasses[] = $constantString->getValue();
2224-
$thisTypes[] = new ObjectType($constantString->getValue());
2225-
}
2226-
2227-
$thisType = TypeCombinator::union(...$thisTypes);
2228-
} elseif ($argValueType instanceof GenericClassStringType) {
2229-
$genericClassNames = $argValueType->getGenericType()->getObjectClassNames();
2230-
if (count($genericClassNames) > 0) {
2231-
$scopeClasses = $genericClassNames;
2232-
$thisType = $argValueType->getGenericType();
2233-
}
2219+
} else {
2220+
$thisType = $argValueType->getClassStringObjectType();
2221+
$scopeClasses = $thisType->getObjectClassNames();
22342222
}
22352223
}
22362224
$closureBindScope = $scope->enterClosureBind($thisType, $nativeThisType, $scopeClasses);

src/Rules/Api/ApiInstanceofTypeRule.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
use PHPStan\Type\Constant\ConstantStringType;
3030
use PHPStan\Type\Enum\EnumCaseObjectType;
3131
use PHPStan\Type\FloatType;
32+
use PHPStan\Type\Generic\GenericClassStringType;
33+
use PHPStan\Type\Generic\GenericObjectType;
3234
use PHPStan\Type\IntegerType;
3335
use PHPStan\Type\IterableType;
3436
use PHPStan\Type\NullType;
@@ -65,6 +67,8 @@ class ApiInstanceofTypeRule implements Rule
6567
IterableType::class => 'Type::isIterable()',
6668
ObjectWithoutClassType::class => 'Type::isObject()',
6769
ObjectType::class => 'Type::isObject() or Type::getObjectClassNames()',
70+
GenericClassStringType::class => 'Type::getClassStringObjectType()',
71+
GenericObjectType::class => null,
6872

6973
// accessory types
7074
NonEmptyArrayType::class => 'Type::isIterableAtLeastOnce()',
@@ -127,14 +131,22 @@ public function processNode(Node $node, Scope $scope): array
127131
}
128132
}
129133

134+
$tip = 'Learn more: <fg=cyan>https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated</>';
135+
if ($lowerMap[$lowerClassName] === null) {
136+
return [
137+
RuleErrorBuilder::message(sprintf(
138+
'Doing instanceof %s is error-prone and deprecated.',
139+
$className,
140+
))->tip($tip)->build(),
141+
];
142+
}
143+
130144
return [
131145
RuleErrorBuilder::message(sprintf(
132146
'Doing instanceof %s is error-prone and deprecated. Use %s instead.',
133147
$className,
134148
$lowerMap[$lowerClassName],
135-
))->tip(
136-
'Learn more: <fg=cyan>https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated</>',
137-
)->build(),
149+
))->tip($tip)->build(),
138150
];
139151
}
140152

0 commit comments

Comments
 (0)