Skip to content

Commit 4c5adfc

Browse files
committed
Replace error-prone instanceof in Rules classes
1 parent dc576b9 commit 4c5adfc

12 files changed

+50
-55
lines changed

src/Rules/Api/NodeConnectingVisitorAttributesRule.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
use PHPStan\Analyser\Scope;
88
use PHPStan\Rules\Rule;
99
use PHPStan\Rules\RuleErrorBuilder;
10-
use PHPStan\Type\Constant\ConstantStringType;
1110
use PHPStan\Type\ObjectType;
1211
use function array_keys;
12+
use function count;
1313
use function in_array;
1414
use function sprintf;
1515
use function str_starts_with;
@@ -42,10 +42,11 @@ public function processNode(Node $node, Scope $scope): array
4242
return [];
4343
}
4444
$argType = $scope->getType($args[0]->value);
45-
if (!$argType instanceof ConstantStringType) {
45+
if (count($argType->getConstantStrings()) === 0) {
4646
return [];
4747
}
48-
if (!in_array($argType->getValue(), ['parent', 'previous', 'next'], true)) {
48+
$argValue = $argType->getConstantScalarValues()[0];
49+
if (!in_array($argValue, ['parent', 'previous', 'next'], true)) {
4950
return [];
5051
}
5152
if (!$scope->isInClass()) {
@@ -67,7 +68,7 @@ public function processNode(Node $node, Scope $scope): array
6768
}
6869

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

src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php

Lines changed: 5 additions & 5 deletions
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

src/Rules/Classes/RequireExtendsRule.php

Lines changed: 6 additions & 9 deletions
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

src/Rules/Comparison/ConstantLooseComparisonRule.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use PHPStan\Parser\LastConditionVisitor;
88
use PHPStan\Rules\Rule;
99
use PHPStan\Rules\RuleErrorBuilder;
10-
use PHPStan\Type\Constant\ConstantBooleanType;
1110
use PHPStan\Type\VerbosityLevel;
1211
use function sprintf;
1312

@@ -37,7 +36,7 @@ public function processNode(Node $node, Scope $scope): array
3736
}
3837

3938
$nodeType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node) : $scope->getNativeType($node);
40-
if (!$nodeType instanceof ConstantBooleanType) {
39+
if (!$nodeType->isTrue()->yes() && !$nodeType->isFalse()->yes()) {
4140
return [];
4241
}
4342

@@ -47,7 +46,7 @@ public function processNode(Node $node, Scope $scope): array
4746
}
4847

4948
$instanceofTypeWithoutPhpDocs = $scope->getNativeType($node);
50-
if ($instanceofTypeWithoutPhpDocs instanceof ConstantBooleanType) {
49+
if ($instanceofTypeWithoutPhpDocs->isTrue()->yes() || $instanceofTypeWithoutPhpDocs->isFalse()->yes()) {
5150
return $ruleErrorBuilder;
5251
}
5352
if (!$this->treatPhpDocTypesAsCertainTip) {
@@ -57,7 +56,7 @@ public function processNode(Node $node, Scope $scope): array
5756
return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip();
5857
};
5958

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

src/Rules/Comparison/ImpossibleCheckTypeHelper.php

Lines changed: 4 additions & 3 deletions
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',

src/Rules/MissingTypehintCheck.php

Lines changed: 4 additions & 4 deletions
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

src/Rules/PhpDoc/RequireExtendsCheck.php

Lines changed: 3 additions & 3 deletions
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))

src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
use PHPStan\Rules\ClassNameNodePair;
1010
use PHPStan\Rules\Rule;
1111
use PHPStan\Rules\RuleErrorBuilder;
12-
use PHPStan\Type\ObjectType;
1312
use PHPStan\Type\VerbosityLevel;
1413
use function array_merge;
14+
use function count;
1515
use function sprintf;
1616
use function strtolower;
1717

@@ -49,15 +49,16 @@ public function processNode(Node $node, Scope $scope): array
4949
$errors = [];
5050
foreach ($implementsTags as $implementsTag) {
5151
$type = $implementsTag->getType();
52-
if (!$type instanceof ObjectType) {
52+
$classNames = $type->getObjectClassNames();
53+
if (count($classNames) === 0) {
5354
$errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @phpstan-require-implements contains non-object type %s.', $type->describe(VerbosityLevel::typeOnly())))
5455
->identifier('requireImplements.nonObject')
5556
->build();
5657
continue;
5758
}
5859

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

src/Rules/RuleLevelHelper.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use PHPStan\Type\MixedType;
1515
use PHPStan\Type\NeverType;
1616
use PHPStan\Type\NullType;
17-
use PHPStan\Type\ObjectType;
1817
use PHPStan\Type\StrictMixedType;
1918
use PHPStan\Type\Type;
2019
use PHPStan\Type\TypeCombinator;
@@ -304,10 +303,9 @@ private function findTypeToCheckImplementation(
304303
if (
305304
$type instanceof UnionType
306305
&& 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'
306+
&& $type->isObject()->yes()
307+
&& $type->getTypes()[0]->getObjectClassNames() === ['PhpParser\\Node\\Arg']
308+
&& $type->getTypes()[1]->getObjectClassNames() === ['PhpParser\\Node\\VariadicPlaceholder']
311309
&& !$unionTypeCriteriaCallback($type)
312310
) {
313311
$tip = 'Use <fg=cyan>->getArgs()</> instead of <fg=cyan>->args</>.';

src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use PHPStan\Node\MethodReturnStatementsNode;
88
use PHPStan\Rules\Rule;
99
use PHPStan\Rules\RuleErrorBuilder;
10-
use PHPStan\Type\Constant\ConstantBooleanType;
1110
use PHPStan\Type\TypeCombinator;
1211
use PHPStan\Type\TypeUtils;
1312
use PHPStan\Type\UnionType;
@@ -82,9 +81,9 @@ public function processNode(Node $node, Scope $scope): array
8281

8382
$returnType = TypeCombinator::union(...$returnTypes);
8483
if (
85-
!$method->isPrivate()
86-
&& ($returnType->isNull()->yes() || $returnType instanceof ConstantBooleanType)
87-
&& !$isFirstDeclaration
84+
!$isFirstDeclaration
85+
&& !$method->isPrivate()
86+
&& ($returnType->isNull()->yes() || $returnType->isTrue()->yes() || $returnType->isFalse()->yes())
8887
) {
8988
return [];
9089
}

0 commit comments

Comments
 (0)