Skip to content

Commit e799fc2

Browse files
committed
Fixes - use methods on Type
1 parent 32d7550 commit e799fc2

27 files changed

+187
-162
lines changed

build/PHPStan/Build/ServiceLocatorDynamicReturnTypeExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method
3636

3737
if ($methodReflection->getName() === 'getByType' && count($methodCall->getArgs()) >= 2) {
3838
$argType = $scope->getType($methodCall->getArgs()[1]->value);
39-
if ($argType instanceof ConstantBooleanType && $argType->getValue()) {
39+
if ($argType->isTrue()->yes()) {
4040
$returnType = TypeCombinator::addNull($returnType);
4141
}
4242
}

src/Analyser/MutatingScope.php

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,7 @@ private function resolveType(string $exprString, Expr $node): Type
10711071
}
10721072

10731073
$resultType = $this->initializerExprTypeResolver->resolveConcatType($resultType, $partType);
1074-
if (! $resultType instanceof ConstantStringType && ! $resultType instanceof UnionType) {
1074+
if (count($resultType->getConstantStrings()) === 0) {
10751075
return $resultType;
10761076
}
10771077
}
@@ -1604,25 +1604,26 @@ private function resolveType(string $exprString, Expr $node): Type
16041604
if ($node->if === null) {
16051605
$conditionType = $this->getType($node->cond);
16061606
$booleanConditionType = $conditionType->toBoolean();
1607-
if ($booleanConditionType instanceof ConstantBooleanType) {
1608-
if ($booleanConditionType->getValue()) {
1609-
return $this->filterByTruthyValue($node->cond)->getType($node->cond);
1610-
}
1607+
if ($booleanConditionType->isTrue()->yes()) {
1608+
return $this->filterByTruthyValue($node->cond)->getType($node->cond);
1609+
}
16111610

1611+
if ($booleanConditionType->isFalse()->yes()) {
16121612
return $this->filterByFalseyValue($node->cond)->getType($node->else);
16131613
}
1614+
16141615
return TypeCombinator::union(
16151616
TypeCombinator::removeFalsey($this->filterByTruthyValue($node->cond)->getType($node->cond)),
16161617
$this->filterByFalseyValue($node->cond)->getType($node->else),
16171618
);
16181619
}
16191620

16201621
$booleanConditionType = $this->getType($node->cond)->toBoolean();
1621-
if ($booleanConditionType instanceof ConstantBooleanType) {
1622-
if ($booleanConditionType->getValue()) {
1623-
return $this->filterByTruthyValue($node->cond)->getType($node->if);
1624-
}
1622+
if ($booleanConditionType->isTrue()->yes()) {
1623+
return $this->filterByTruthyValue($node->cond)->getType($node->if);
1624+
}
16251625

1626+
if ($booleanConditionType->isFalse()->yes()) {
16261627
return $this->filterByFalseyValue($node->cond)->getType($node->else);
16271628
}
16281629

@@ -2681,7 +2682,10 @@ public function enterNamespace(string $namespaceName): self
26812682
);
26822683
}
26832684

2684-
public function enterClosureBind(?Type $thisType, ?Type $nativeThisType, string $scopeClass): self
2685+
/**
2686+
* @param list<string> $scopeClasses
2687+
*/
2688+
public function enterClosureBind(?Type $thisType, ?Type $nativeThisType, array $scopeClasses): self
26852689
{
26862690
$expressionTypes = $this->expressionTypes;
26872691
if ($thisType !== null) {
@@ -2697,8 +2701,8 @@ public function enterClosureBind(?Type $thisType, ?Type $nativeThisType, string
26972701
unset($nativeExpressionTypes['$this']);
26982702
}
26992703

2700-
if ($scopeClass === 'static' && $this->isInClass()) {
2701-
$scopeClass = $this->getClassReflection()->getName();
2704+
if ($scopeClasses === ['static'] && $this->isInClass()) {
2705+
$scopeClasses = [$this->getClassReflection()->getName()];
27022706
}
27032707

27042708
return $this->scopeFactory->create(
@@ -2709,7 +2713,7 @@ public function enterClosureBind(?Type $thisType, ?Type $nativeThisType, string
27092713
$expressionTypes,
27102714
$nativeExpressionTypes,
27112715
$this->conditionalExpressions,
2712-
[$scopeClass],
2716+
$scopeClasses,
27132717
$this->anonymousFunctionReflection,
27142718
);
27152719
}
@@ -3354,7 +3358,7 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType):
33543358
}
33553359
}
33563360

3357-
if ($expr instanceof FuncCall && $expr->name instanceof Name && $type instanceof ConstantBooleanType && !$type->getValue()) {
3361+
if ($expr instanceof FuncCall && $expr->name instanceof Name && $type->isFalse()->yes()) {
33583362
$functionName = $this->reflectionProvider->resolveFunctionName($expr->name, $this);
33593363
if ($functionName !== null && in_array(strtolower($functionName), [
33603364
'is_dir',
@@ -4811,8 +4815,13 @@ private function getTypeToInstantiateForNew(Type $type): Type
48114815
return TypeCombinator::intersect(...$types);
48124816
}
48134817

4814-
if ($type instanceof ConstantStringType) {
4815-
return new ObjectType($type->getValue());
4818+
if (count($type->getConstantStrings()) > 0) {
4819+
$types = [];
4820+
foreach ($type->getConstantStrings() as $constantString) {
4821+
$types[] = new ObjectType($constantString->getValue());
4822+
}
4823+
4824+
return TypeCombinator::union(...$types);
48164825
}
48174826

48184827
if ($type instanceof GenericClassStringType) {

src/Analyser/NodeScopeResolver.php

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@
132132
use PHPStan\Type\Constant\ConstantArrayTypeBuilder;
133133
use PHPStan\Type\Constant\ConstantBooleanType;
134134
use PHPStan\Type\Constant\ConstantIntegerType;
135-
use PHPStan\Type\Constant\ConstantStringType;
136135
use PHPStan\Type\ErrorType;
137136
use PHPStan\Type\FileTypeMapper;
137+
use PHPStan\Type\GeneralizePrecision;
138138
use PHPStan\Type\Generic\GenericClassStringType;
139139
use PHPStan\Type\Generic\TemplateTypeHelper;
140140
use PHPStan\Type\Generic\TemplateTypeMap;
@@ -1916,8 +1916,8 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
19161916
foreach ($callArgs as $callArg) {
19171917
$callArgType = $scope->getType($callArg->value);
19181918
if ($callArg->unpack) {
1919-
if ($callArgType instanceof ConstantArrayType) {
1920-
$iterableValueTypes = $callArgType->getValueTypes();
1919+
if (count($callArgType->getConstantArrays()) === 1) {
1920+
$iterableValueTypes = $callArgType->getConstantArrays()[0]->getValueTypes();
19211921
} else {
19221922
$iterableValueTypes = [$callArgType->getIterableValueType()];
19231923
$nonConstantArrayWasUnpacked = true;
@@ -1960,7 +1960,7 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra
19601960
$valueTypes = $constantArray->getValueTypes();
19611961
foreach ($keyTypes as $k => $keyType) {
19621962
$arrayTypeBuilder->setOffsetValueType(
1963-
$keyType instanceof ConstantStringType ? $keyType : null,
1963+
count($keyType->getConstantStrings()) === 1 ? $keyType->getConstantStrings()[0] : null,
19641964
$valueTypes[$k],
19651965
$constantArray->isOptionalKey($k),
19661966
);
@@ -1969,10 +1969,11 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra
19691969

19701970
$constantArray = $arrayTypeBuilder->getArray();
19711971

1972-
if ($constantArray instanceof ConstantArrayType && $nonConstantArrayWasUnpacked) {
1972+
if ($constantArray->isConstantArray()->yes() && $nonConstantArrayWasUnpacked) {
1973+
$array = new ArrayType($constantArray->generalize(GeneralizePrecision::lessSpecific())->getIterableKeyType(), $constantArray->getIterableValueType());
19731974
$constantArray = $constantArray->isIterableAtLeastOnce()->yes()
1974-
? TypeCombinator::intersect($constantArray->generalizeKeys(), new NonEmptyArrayType())
1975-
: $constantArray->generalizeKeys();
1975+
? TypeCombinator::intersect($array, new NonEmptyArrayType())
1976+
: $array;
19761977
}
19771978

19781979
$newArrayTypes[] = $constantArray;
@@ -2202,27 +2203,37 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra
22022203
$nativeThisType = $nativeArgType;
22032204
}
22042205
}
2205-
$scopeClass = 'static';
2206+
$scopeClasses = ['static'];
22062207
if (isset($expr->getArgs()[2])) {
22072208
$argValue = $expr->getArgs()[2]->value;
22082209
$argValueType = $scope->getType($argValue);
22092210

2211+
$scopeClasses = [];
22102212
$directClassNames = $argValueType->getObjectClassNames();
2211-
if (count($directClassNames) === 1) {
2212-
$scopeClass = $directClassNames[0];
2213-
$thisType = new ObjectType($scopeClass);
2214-
} elseif ($argValueType instanceof ConstantStringType) {
2215-
$scopeClass = $argValueType->getValue();
2216-
$thisType = new ObjectType($scopeClass);
2213+
if (count($directClassNames) > 0) {
2214+
$scopeClasses = $directClassNames;
2215+
$thisTypes = [];
2216+
foreach ($directClassNames as $directClassName) {
2217+
$thisTypes[] = new ObjectType($directClassName);
2218+
}
2219+
$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);
22172228
} elseif ($argValueType instanceof GenericClassStringType) {
22182229
$genericClassNames = $argValueType->getGenericType()->getObjectClassNames();
2219-
if (count($genericClassNames) === 1) {
2220-
$scopeClass = $genericClassNames[0];
2230+
if (count($genericClassNames) > 0) {
2231+
$scopeClasses = $genericClassNames;
22212232
$thisType = $argValueType->getGenericType();
22222233
}
22232234
}
22242235
}
2225-
$closureBindScope = $scope->enterClosureBind($thisType, $nativeThisType, $scopeClass);
2236+
$closureBindScope = $scope->enterClosureBind($thisType, $nativeThisType, $scopeClasses);
22262237
}
22272238
} else {
22282239
$throwPoints[] = ThrowPoint::createImplicit($scope, $expr);

src/Reflection/InitializerExprTypeResolver.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -484,20 +484,21 @@ public function getArrayType(Expr\Array_ $expr, callable $getTypeCallback): Type
484484

485485
$valueType = $getTypeCallback($arrayItem->value);
486486
if ($arrayItem->unpack) {
487-
if ($valueType instanceof ConstantArrayType) {
487+
if (count($valueType->getConstantArrays()) === 1) {
488+
$constantArrayType = $valueType->getConstantArrays()[0];
488489
$hasStringKey = false;
489-
foreach ($valueType->getKeyTypes() as $keyType) {
490-
if ($keyType instanceof ConstantStringType) {
490+
foreach ($constantArrayType->getKeyTypes() as $keyType) {
491+
if ($keyType->isString()->yes()) {
491492
$hasStringKey = true;
492493
break;
493494
}
494495
}
495496

496-
foreach ($valueType->getValueTypes() as $i => $innerValueType) {
497+
foreach ($constantArrayType->getValueTypes() as $i => $innerValueType) {
497498
if ($hasStringKey && $this->phpVersion->supportsArrayUnpackingWithStringKeys()) {
498-
$arrayBuilder->setOffsetValueType($valueType->getKeyTypes()[$i], $innerValueType, $valueType->isOptionalKey($i));
499+
$arrayBuilder->setOffsetValueType($constantArrayType->getKeyTypes()[$i], $innerValueType, $constantArrayType->isOptionalKey($i));
499500
} else {
500-
$arrayBuilder->setOffsetValueType(null, $innerValueType, $valueType->isOptionalKey($i));
501+
$arrayBuilder->setOffsetValueType(null, $innerValueType, $constantArrayType->isOptionalKey($i));
501502
}
502503
}
503504
} else {
@@ -1493,9 +1494,9 @@ private function resolveCommonMath(Expr\BinaryOp $expr, Type $leftType, Type $ri
14931494

14941495
$types = TypeCombinator::union($leftType, $rightType);
14951496
if (
1496-
$leftType instanceof ArrayType
1497-
|| $rightType instanceof ArrayType
1498-
|| $types instanceof ArrayType
1497+
$leftType->isArray()->yes()
1498+
|| $rightType->isArray()->yes()
1499+
|| $types->isArray()->yes()
14991500
) {
15001501
return new ErrorType();
15011502
}

src/Rules/Api/ApiInstanceofRule.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use PHPStan\Rules\Rule;
1010
use PHPStan\Rules\RuleError;
1111
use PHPStan\Rules\RuleErrorBuilder;
12-
use PHPStan\Type\Constant\ConstantBooleanType;
1312
use PHPStan\Type\ObjectType;
1413
use PHPStan\Type\Type;
1514
use PHPStan\Type\UnionType;
@@ -84,7 +83,7 @@ private function processCoveredClass(Node\Expr\Instanceof_ $node, Scope $scope,
8483
}
8584

8685
$instanceofType = $scope->getType($node);
87-
if ($instanceofType instanceof ConstantBooleanType) {
86+
if ($instanceofType->isTrue()->or($instanceofType->isFalse())->yes()) {
8887
return [];
8988
}
9089

src/Rules/Arrays/AppendedArrayItemTypeRule.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use PHPStan\Rules\Rule;
1313
use PHPStan\Rules\RuleErrorBuilder;
1414
use PHPStan\Rules\RuleLevelHelper;
15-
use PHPStan\Type\ArrayType;
1615
use PHPStan\Type\VerbosityLevel;
1716
use function sprintf;
1817

@@ -62,7 +61,7 @@ public function processNode(Node $node, Scope $scope): array
6261
}
6362

6463
$assignedToType = $propertyReflection->getWritableType();
65-
if (!($assignedToType instanceof ArrayType)) {
64+
if (!$assignedToType->isArray()->yes()) {
6665
return [];
6766
}
6867

@@ -72,7 +71,7 @@ public function processNode(Node $node, Scope $scope): array
7271
$assignedValueType = $scope->getType($node);
7372
}
7473

75-
$itemType = $assignedToType->getItemType();
74+
$itemType = $assignedToType->getIterableValueType();
7675
$accepts = $this->ruleLevelHelper->acceptsWithReason($itemType, $assignedValueType, $scope->isDeclareStrictTypes());
7776
if (!$accepts->result) {
7877
$verbosityLevel = VerbosityLevel::getRecommendedLevelByType($itemType, $assignedValueType);

src/Rules/Arrays/AppendedArrayKeyTypeRule.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use PHPStan\Rules\Properties\PropertyReflectionFinder;
1010
use PHPStan\Rules\Rule;
1111
use PHPStan\Rules\RuleErrorBuilder;
12-
use PHPStan\Type\ArrayType;
1312
use PHPStan\Type\IntegerType;
1413
use PHPStan\Type\UnionType;
1514
use PHPStan\Type\VerbosityLevel;
@@ -53,7 +52,7 @@ public function processNode(Node $node, Scope $scope): array
5352
}
5453

5554
$arrayType = $propertyReflection->getReadableType();
56-
if (!$arrayType instanceof ArrayType) {
55+
if (!$arrayType->isArray()->yes()) {
5756
return [];
5857
}
5958

src/Rules/Arrays/ArrayDestructuringRule.php

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@
66
use PhpParser\Node;
77
use PhpParser\Node\Expr;
88
use PhpParser\Node\Expr\Assign;
9-
use PhpParser\Node\Scalar\LNumber;
109
use PHPStan\Analyser\Scope;
10+
use PHPStan\Node\Expr\TypeExpr;
1111
use PHPStan\Rules\Rule;
1212
use PHPStan\Rules\RuleError;
1313
use PHPStan\Rules\RuleErrorBuilder;
1414
use PHPStan\Rules\RuleLevelHelper;
1515
use PHPStan\Type\Constant\ConstantIntegerType;
16-
use PHPStan\Type\Constant\ConstantStringType;
1716
use PHPStan\Type\ErrorType;
1817
use PHPStan\Type\ObjectType;
1918
use PHPStan\Type\Type;
@@ -88,11 +87,7 @@ private function getErrors(Scope $scope, Expr $var, Expr $expr): array
8887
$keyExpr = new Node\Scalar\LNumber($i);
8988
} else {
9089
$keyType = $scope->getType($item->key);
91-
if ($keyType instanceof ConstantIntegerType) {
92-
$keyExpr = new LNumber($keyType->getValue());
93-
} elseif ($keyType instanceof ConstantStringType) {
94-
$keyExpr = new Node\Scalar\String_($keyType->getValue());
95-
}
90+
$keyExpr = new TypeExpr($keyType);
9691
}
9792

9893
$itemErrors = $this->nonexistentOffsetInArrayDimFetchCheck->check(
@@ -103,11 +98,6 @@ private function getErrors(Scope $scope, Expr $var, Expr $expr): array
10398
);
10499
$errors = array_merge($errors, $itemErrors);
105100

106-
if ($keyExpr === null) {
107-
$i++;
108-
continue;
109-
}
110-
111101
if (!$item->value instanceof Node\Expr\List_ && !$item->value instanceof Node\Expr\Array_) {
112102
$i++;
113103
continue;

src/Rules/DateTimeInstantiationRule.php

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use PhpParser\Node;
77
use PhpParser\Node\Expr\New_;
88
use PHPStan\Analyser\Scope;
9-
use PHPStan\Type\Constant\ConstantStringType;
109
use Throwable;
1110
use function count;
1211
use function in_array;
@@ -38,19 +37,20 @@ public function processNode(Node $node, Scope $scope): array
3837
}
3938

4039
$arg = $scope->getType($node->getArgs()[0]->value);
41-
if (!($arg instanceof ConstantStringType)) {
42-
return [];
43-
}
44-
4540
$errors = [];
46-
$dateString = $arg->getValue();
47-
try {
48-
new DateTime($dateString);
49-
} catch (Throwable) {
50-
// an exception is thrown for errors only but we want to catch warnings too
51-
}
52-
$lastErrors = DateTime::getLastErrors();
53-
if ($lastErrors !== false) {
41+
42+
foreach ($arg->getConstantStrings() as $constantString) {
43+
$dateString = $constantString->getValue();
44+
try {
45+
new DateTime($dateString);
46+
} catch (Throwable) {
47+
// an exception is thrown for errors only but we want to catch warnings too
48+
}
49+
$lastErrors = DateTime::getLastErrors();
50+
if ($lastErrors === false) {
51+
continue;
52+
}
53+
5454
foreach ($lastErrors['errors'] as $error) {
5555
$errors[] = RuleErrorBuilder::message(sprintf(
5656
'Instantiating %s with %s produces an error: %s',

0 commit comments

Comments
 (0)