Skip to content

Commit d25139a

Browse files
committed
Replace error-prone instanceof in Rules classes
1 parent 8d4796d commit d25139a

12 files changed

+50
-50
lines changed

Diff for: src/Rules/Api/NodeConnectingVisitorAttributesRule.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PHPStan\Type\Constant\ConstantStringType;
1111
use PHPStan\Type\ObjectType;
1212
use function array_keys;
13+
use function count;
1314
use function in_array;
1415
use function sprintf;
1516
use function str_starts_with;
@@ -42,10 +43,11 @@ public function processNode(Node $node, Scope $scope): array
4243
return [];
4344
}
4445
$argType = $scope->getType($args[0]->value);
45-
if (!$argType instanceof ConstantStringType) {
46+
if (count($argType->getConstantStrings()) === 0) {
4647
return [];
4748
}
48-
if (!in_array($argType->getValue(), ['parent', 'previous', 'next'], true)) {
49+
$argValue = $argType->getConstantScalarValues()[0];
50+
if (!in_array($argValue, ['parent', 'previous', 'next'], true)) {
4951
return [];
5052
}
5153
if (!$scope->isInClass()) {
@@ -67,7 +69,7 @@ public function processNode(Node $node, Scope $scope): array
6769
}
6870

6971
return [
70-
RuleErrorBuilder::message(sprintf('Node attribute \'%s\' is no longer available.', $argType->getValue()))
72+
RuleErrorBuilder::message(sprintf('Node attribute \'%s\' is no longer available.', $argValue))
7173
->identifier('phpParser.nodeConnectingAttribute')
7274
->tip('See: https://phpstan.org/blog/preprocessing-ast-for-custom-rules')
7375
->build(),

Diff for: src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use function array_keys;
1414
use function count;
1515
use function implode;
16+
use function is_int;
1617
use function max;
1718
use function sprintf;
1819
use function var_export;
@@ -70,12 +71,11 @@ public function processNode(Node $node, Scope $scope): array
7071
}
7172
} else {
7273
$keyType = $itemNode->getScope()->getType($key);
73-
74-
$arrayKeyValue = $keyType->toArrayKey();
75-
if ($arrayKeyValue instanceof ConstantIntegerType) {
74+
$arrayKeyValues = $keyType->toArrayKey()->getConstantScalarValues();
75+
if (count($arrayKeyValues) === 1 && is_int($arrayKeyValues[0])) {
7676
$autoGeneratedIndex = $autoGeneratedIndex === null
77-
? $arrayKeyValue->getValue()
78-
: max($autoGeneratedIndex, $arrayKeyValue->getValue());
77+
? $arrayKeyValues[0]
78+
: max($autoGeneratedIndex, $arrayKeyValues[0]);
7979
}
8080
}
8181

Diff for: src/Rules/Classes/RequireExtendsRule.php

+6-9
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
use PHPStan\Node\InClassNode;
88
use PHPStan\Rules\Rule;
99
use PHPStan\Rules\RuleErrorBuilder;
10-
use PHPStan\Type\ObjectType;
1110
use PHPStan\Type\VerbosityLevel;
11+
use function count;
1212
use function sprintf;
1313

1414
/**
@@ -35,11 +35,8 @@ public function processNode(Node $node, Scope $scope): array
3535
$extendsTags = $interface->getRequireExtendsTags();
3636
foreach ($extendsTags as $extendsTag) {
3737
$type = $extendsTag->getType();
38-
if (!$type instanceof ObjectType) {
39-
continue;
40-
}
41-
42-
if ($classReflection->is($type->getClassName())) {
38+
$classNames = $type->getObjectClassNames();
39+
if (count($classNames) === 1 && $classReflection->is($classNames[0])) {
4340
continue;
4441
}
4542

@@ -60,11 +57,11 @@ public function processNode(Node $node, Scope $scope): array
6057
$extendsTags = $trait->getRequireExtendsTags();
6158
foreach ($extendsTags as $extendsTag) {
6259
$type = $extendsTag->getType();
63-
if (!$type instanceof ObjectType) {
60+
$classNames = $type->getObjectClassNames();
61+
if (count($classNames) === 0) {
6462
continue;
6563
}
66-
67-
if ($classReflection->is($type->getClassName())) {
64+
if (count($classNames) === 1 && $classReflection->is($classNames[0])) {
6865
continue;
6966
}
7067

Diff for: src/Rules/Comparison/ConstantLooseComparisonRule.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function processNode(Node $node, Scope $scope): array
3737
}
3838

3939
$nodeType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node) : $scope->getNativeType($node);
40-
if (!$nodeType instanceof ConstantBooleanType) {
40+
if (!$nodeType->isTrue()->yes() && !$nodeType->isFalse()->yes()) {
4141
return [];
4242
}
4343

@@ -47,7 +47,7 @@ public function processNode(Node $node, Scope $scope): array
4747
}
4848

4949
$instanceofTypeWithoutPhpDocs = $scope->getNativeType($node);
50-
if ($instanceofTypeWithoutPhpDocs instanceof ConstantBooleanType) {
50+
if ($instanceofTypeWithoutPhpDocs->isTrue()->yes() || $instanceofTypeWithoutPhpDocs->isFalse()->yes()) {
5151
return $ruleErrorBuilder;
5252
}
5353
if (!$this->treatPhpDocTypesAsCertainTip) {
@@ -57,7 +57,7 @@ public function processNode(Node $node, Scope $scope): array
5757
return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip();
5858
};
5959

60-
if (!$nodeType->getValue()) {
60+
if ($nodeType->getConstantScalarValues()[0] === false) {
6161
return [
6262
$addTip(RuleErrorBuilder::message(sprintf(
6363
'Loose comparison using %s between %s and %s will always evaluate to false.',

Diff for: src/Rules/Comparison/ImpossibleCheckTypeHelper.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
use function count;
3636
use function implode;
3737
use function in_array;
38+
use function is_bool;
3839
use function is_string;
3940
use function sprintf;
4041
use function strtolower;
@@ -68,12 +69,12 @@ public function findSpecifiedType(
6869
$functionName = strtolower((string) $node->name);
6970
if ($functionName === 'assert' && $argsCount >= 1) {
7071
$arg = $node->getArgs()[0]->value;
71-
$assertValue = ($this->treatPhpDocTypesAsCertain ? $scope->getType($arg) : $scope->getNativeType($arg))->toBoolean();
72-
if (!$assertValue instanceof ConstantBooleanType) {
72+
$assertValues = ($this->treatPhpDocTypesAsCertain ? $scope->getType($arg) : $scope->getNativeType($arg))->getConstantScalarValues();
73+
if (count($assertValues) === 0 || !is_bool($assertValues[0])) {
7374
return null;
7475
}
7576

76-
return $assertValue->getValue();
77+
return $assertValues[0];
7778
}
7879
if (in_array($functionName, [
7980
'class_exists',

Diff for: src/Rules/MissingTypehintCheck.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,11 @@ public function getNonGenericObjectTypesWithGenericClass(Type $type): array
108108
if ($type instanceof TemplateType) {
109109
return $type;
110110
}
111-
if ($type instanceof ObjectType) {
112-
$classReflection = $type->getClassReflection();
113-
if ($classReflection === null) {
111+
if (count($type->getObjectClassNames()) > 0) {
112+
if (count($type->getObjectClassReflections()) === 0) {
114113
return $type;
115114
}
115+
$classReflection = $type->getObjectClassReflections()[0];
116116
if (in_array($classReflection->getName(), self::ITERABLE_GENERIC_CLASS_NAMES, true)) {
117117
// checked by getIterableTypesWithMissingValueTypehint() already
118118
return $type;
@@ -128,7 +128,7 @@ public function getNonGenericObjectTypesWithGenericClass(Type $type): array
128128
}
129129

130130
$resolvedType = TemplateTypeHelper::resolveToBounds($type);
131-
if (!$resolvedType instanceof ObjectType) {
131+
if (count($resolvedType->getObjectClassNames()) === 0) {
132132
throw new ShouldNotHappenException();
133133
}
134134

Diff for: src/Rules/PhpDoc/RequireExtendsCheck.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ public function checkExtendsTags(Node $node, array $extendsTags): array
4141

4242
foreach ($extendsTags as $extendsTag) {
4343
$type = $extendsTag->getType();
44-
if (!$type instanceof ObjectType) {
44+
if (count($type->getObjectClassNames()) === 0) {
4545
$errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))
4646
->identifier('requireExtends.nonObject')
4747
->build();
4848
continue;
4949
}
5050

51-
$class = $type->getClassName();
52-
$referencedClassReflection = $type->getClassReflection();
51+
$class = $type->getObjectClassNames()[0];
52+
$referencedClassReflection = $type->getObjectClassReflections()[0] ?? null;
5353

5454
if ($referencedClassReflection === null) {
5555
$errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-extends contains unknown class %s.', $class))

Diff for: src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PHPStan\Type\ObjectType;
1313
use PHPStan\Type\VerbosityLevel;
1414
use function array_merge;
15+
use function count;
1516
use function sprintf;
1617
use function strtolower;
1718

@@ -49,15 +50,16 @@ public function processNode(Node $node, Scope $scope): array
4950
$errors = [];
5051
foreach ($implementsTags as $implementsTag) {
5152
$type = $implementsTag->getType();
52-
if (!$type instanceof ObjectType) {
53+
$classNames = $type->getObjectClassNames();
54+
if (count($classNames) === 0) {
5355
$errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))
5456
->identifier('requireImplements.nonObject')
5557
->build();
5658
continue;
5759
}
5860

59-
$class = $type->getClassName();
60-
$referencedClassReflection = $type->getClassReflection();
61+
$class = $classNames[0];
62+
$referencedClassReflection = $type->getObjectClassReflections()[0] ?? null;
6163
if ($referencedClassReflection === null) {
6264
$errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains unknown class %s.', $class))
6365
->discoveringSymbolsTip()

Diff for: src/Rules/RuleLevelHelper.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,9 @@ private function findTypeToCheckImplementation(
304304
if (
305305
$type instanceof UnionType
306306
&& count($type->getTypes()) === 2
307-
&& $type->getTypes()[0] instanceof ObjectType
308-
&& $type->getTypes()[1] instanceof ObjectType
309-
&& $type->getTypes()[0]->getClassName() === 'PhpParser\\Node\\Arg'
310-
&& $type->getTypes()[1]->getClassName() === 'PhpParser\\Node\\VariadicPlaceholder'
307+
&& $type->isObject()->yes()
308+
&& $type->getTypes()[0]->getObjectClassNames() === ['PhpParser\\Node\\Arg']
309+
&& $type->getTypes()[1]->getObjectClassNames() === ['PhpParser\\Node\\VariadicPlaceholder']
311310
&& !$unionTypeCriteriaCallback($type)
312311
) {
313312
$tip = 'Use <fg=cyan>->getArgs()</> instead of <fg=cyan>->args</>.';

Diff for: src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@ public function processNode(Node $node, Scope $scope): array
8282

8383
$returnType = TypeCombinator::union(...$returnTypes);
8484
if (
85-
!$method->isPrivate()
86-
&& ($returnType->isNull()->yes() || $returnType instanceof ConstantBooleanType)
87-
&& !$isFirstDeclaration
85+
!$isFirstDeclaration
86+
&& !$method->isPrivate()
87+
&& ($returnType->isNull()->yes() || $returnType->isTrue()->yes() || $returnType->isFalse()->yes())
8888
) {
8989
return [];
9090
}

Diff for: src/Rules/UnusedFunctionParametersCheck.php

+4-5
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
use PHPStan\Analyser\Scope;
88
use PHPStan\Reflection\ReflectionProvider;
99
use PHPStan\ShouldNotHappenException;
10-
use PHPStan\Type\Constant\ConstantStringType;
1110
use function array_combine;
1211
use function array_map;
1312
use function array_merge;
13+
use function count;
1414
use function is_array;
1515
use function is_string;
1616
use function sprintf;
@@ -92,11 +92,10 @@ private function getUsedVariables(Scope $scope, $node): array
9292
) {
9393
foreach ($node->getArgs() as $arg) {
9494
$argType = $scope->getType($arg->value);
95-
if (!($argType instanceof ConstantStringType)) {
96-
continue;
95+
if (count($argType->getConstantStrings()) === 1) {
96+
$constantStringType = $argType->getConstantStrings()[0];
97+
$variableNames[] = $constantStringType->getValue();
9798
}
98-
99-
$variableNames[] = $argType->getValue();
10099
}
101100
}
102101
foreach ($node->getSubNodeNames() as $subNodeName) {

Diff for: src/Rules/Variables/CompactVariablesRule.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,17 @@ public function processNode(Node $node, Scope $scope): array
6666
}
6767

6868
/**
69-
* @return array<int, ConstantStringType>
69+
* @return list<ConstantStringType>
7070
*/
7171
private function findConstantStrings(Type $type): array
7272
{
73-
if ($type instanceof ConstantStringType) {
74-
return [$type];
73+
if (count($type->getConstantStrings()) > 0) {
74+
return $type->getConstantStrings();
7575
}
7676

77-
if ($type instanceof ConstantArrayType) {
77+
if (count($type->getConstantArrays()) > 1) {
7878
$result = [];
79-
foreach ($type->getValueTypes() as $valueType) {
79+
foreach ($type->getConstantArrays()[0]->getValueTypes() as $valueType) {
8080
$constantStrings = $this->findConstantStrings($valueType);
8181
$result = array_merge($result, $constantStrings);
8282
}

0 commit comments

Comments
 (0)