Skip to content

Commit 551d3fd

Browse files
zonuexeondrejmirtes
authored andcommitted
Replace error-prone instanceof in Rules classes
1 parent cc57957 commit 551d3fd

20 files changed

+270
-228
lines changed

phpstan-baseline.neon

+1-67
Original file line numberDiff line numberDiff line change
@@ -459,30 +459,12 @@ parameters:
459459
count: 1
460460
path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php
461461

462-
-
463-
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#'
464-
identifier: phpstanApi.instanceofType
465-
count: 1
466-
path: src/Rules/Api/NodeConnectingVisitorAttributesRule.php
467-
468-
-
469-
message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#'
470-
identifier: phpstanApi.instanceofType
471-
count: 1
472-
path: src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php
473-
474462
-
475463
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#'
476464
identifier: phpstanApi.instanceofType
477465
count: 2
478466
path: src/Rules/Classes/ImpossibleInstanceOfRule.php
479467

480-
-
481-
message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#'
482-
identifier: phpstanApi.instanceofType
483-
count: 2
484-
path: src/Rules/Classes/RequireExtendsRule.php
485-
486468
-
487469
message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#'
488470
identifier: phpstanApi.instanceofType
@@ -507,12 +489,6 @@ parameters:
507489
count: 6
508490
path: src/Rules/Comparison/BooleanOrConstantConditionRule.php
509491

510-
-
511-
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#'
512-
identifier: phpstanApi.instanceofType
513-
count: 2
514-
path: src/Rules/Comparison/ConstantLooseComparisonRule.php
515-
516492
-
517493
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#'
518494
identifier: phpstanApi.instanceofType
@@ -540,7 +516,7 @@ parameters:
540516
-
541517
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#'
542518
identifier: phpstanApi.instanceofType
543-
count: 2
519+
count: 1
544520
path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php
545521

546522
-
@@ -693,18 +669,6 @@ parameters:
693669
count: 1
694670
path: src/Rules/Methods/StaticMethodCallCheck.php
695671

696-
-
697-
message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#'
698-
identifier: phpstanApi.instanceofType
699-
count: 1
700-
path: src/Rules/PhpDoc/RequireExtendsCheck.php
701-
702-
-
703-
message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#'
704-
identifier: phpstanApi.instanceofType
705-
count: 1
706-
path: src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php
707-
708672
-
709673
message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#'
710674
identifier: phpstanApi.instanceofType
@@ -723,36 +687,6 @@ parameters:
723687
count: 1
724688
path: src/Rules/RuleLevelHelper.php
725689

726-
-
727-
message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#'
728-
identifier: phpstanApi.instanceofType
729-
count: 2
730-
path: src/Rules/RuleLevelHelper.php
731-
732-
-
733-
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#'
734-
identifier: phpstanApi.instanceofType
735-
count: 1
736-
path: src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php
737-
738-
-
739-
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#'
740-
identifier: phpstanApi.instanceofType
741-
count: 1
742-
path: src/Rules/UnusedFunctionParametersCheck.php
743-
744-
-
745-
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#'
746-
identifier: phpstanApi.instanceofType
747-
count: 1
748-
path: src/Rules/Variables/CompactVariablesRule.php
749-
750-
-
751-
message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#'
752-
identifier: phpstanApi.instanceofType
753-
count: 1
754-
path: src/Rules/Variables/CompactVariablesRule.php
755-
756690
-
757691
message: '''
758692
#^Call to deprecated method assertFileNotExists\(\) of class PHPUnit\\Framework\\Assert\:

src/Rules/Api/NodeConnectingVisitorAttributesRule.php

+25-23
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
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;
1312
use function in_array;
@@ -41,37 +40,40 @@ public function processNode(Node $node, Scope $scope): array
4140
if (!isset($args[0])) {
4241
return [];
4342
}
43+
44+
$messages = [];
4445
$argType = $scope->getType($args[0]->value);
45-
if (!$argType instanceof ConstantStringType) {
46-
return [];
47-
}
48-
if (!in_array($argType->getValue(), ['parent', 'previous', 'next'], true)) {
49-
return [];
50-
}
51-
if (!$scope->isInClass()) {
52-
return [];
53-
}
46+
foreach ($argType->getConstantStrings() as $constantString) {
47+
$argValue = $constantString->getValue();
48+
if (!in_array($argValue, ['parent', 'previous', 'next'], true)) {
49+
continue;
50+
}
5451

55-
$classReflection = $scope->getClassReflection();
56-
$hasPhpStanInterface = false;
57-
foreach (array_keys($classReflection->getInterfaces()) as $interfaceName) {
58-
if (!str_starts_with($interfaceName, 'PHPStan\\')) {
52+
if (!$scope->isInClass()) {
5953
continue;
6054
}
6155

62-
$hasPhpStanInterface = true;
63-
}
56+
$classReflection = $scope->getClassReflection();
57+
$hasPhpStanInterface = false;
58+
foreach (array_keys($classReflection->getInterfaces()) as $interfaceName) {
59+
if (!str_starts_with($interfaceName, 'PHPStan\\')) {
60+
continue;
61+
}
6462

65-
if (!$hasPhpStanInterface) {
66-
return [];
67-
}
63+
$hasPhpStanInterface = true;
64+
}
6865

69-
return [
70-
RuleErrorBuilder::message(sprintf('Node attribute \'%s\' is no longer available.', $argType->getValue()))
66+
if (!$hasPhpStanInterface) {
67+
continue;
68+
}
69+
70+
$messages[] = RuleErrorBuilder::message(sprintf('Node attribute \'%s\' is no longer available.', $argValue))
7171
->identifier('phpParser.nodeConnectingAttribute')
7272
->tip('See: https://phpstan.org/blog/preprocessing-ast-for-custom-rules')
73-
->build(),
74-
];
73+
->build();
74+
}
75+
76+
return $messages;
7577
}
7678

7779
}

src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php

+21-21
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
use PHPStan\Rules\Rule;
1010
use PHPStan\Rules\RuleErrorBuilder;
1111
use PHPStan\Type\Constant\ConstantIntegerType;
12-
use PHPStan\Type\ConstantScalarType;
1312
use function array_keys;
1413
use function count;
1514
use function implode;
15+
use function is_int;
1616
use function max;
1717
use function sprintf;
1818
use function var_export;
@@ -70,38 +70,38 @@ public function processNode(Node $node, Scope $scope): array
7070
}
7171
} else {
7272
$keyType = $itemNode->getScope()->getType($key);
73-
74-
$arrayKeyValue = $keyType->toArrayKey();
75-
if ($arrayKeyValue instanceof ConstantIntegerType) {
73+
$arrayKeyValues = $keyType->toArrayKey()->getConstantScalarValues();
74+
if (count($arrayKeyValues) === 1 && is_int($arrayKeyValues[0])) {
7675
$autoGeneratedIndex = $autoGeneratedIndex === null
77-
? $arrayKeyValue->getValue()
78-
: max($autoGeneratedIndex, $arrayKeyValue->getValue());
76+
? $arrayKeyValues[0]
77+
: max($autoGeneratedIndex, $arrayKeyValues[0]);
7978
}
8079
}
8180

82-
if (!$keyType instanceof ConstantScalarType) {
81+
$keyValues = $keyType->getConstantScalarValues();
82+
if (count($keyValues) === 0) {
8383
$autoGeneratedIndex = false;
8484
continue;
8585
}
8686

87-
$value = $keyType->getValue();
88-
$printedValue = $key !== null
89-
? $this->exprPrinter->printExpr($key)
90-
: $value;
87+
foreach ($keyValues as $value) {
88+
$printedValue = $key !== null
89+
? $this->exprPrinter->printExpr($key)
90+
: $value;
91+
$printedValues[$value][] = $printedValue;
9192

92-
$printedValues[$value][] = $printedValue;
93+
if (!isset($valueLines[$value])) {
94+
$valueLines[$value] = $item->getStartLine();
95+
}
9396

94-
if (!isset($valueLines[$value])) {
95-
$valueLines[$value] = $item->getStartLine();
96-
}
97+
$previousCount = count($values);
98+
$values[$value] = $printedValue;
99+
if ($previousCount !== count($values)) {
100+
continue;
101+
}
97102

98-
$previousCount = count($values);
99-
$values[$value] = $printedValue;
100-
if ($previousCount !== count($values)) {
101-
continue;
103+
$duplicateKeys[$value] = true;
102104
}
103-
104-
$duplicateKeys[$value] = true;
105105
}
106106

107107
$messages = [];

src/Rules/Classes/RequireExtendsRule.php

+32-33
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
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;
1211
use function sprintf;
1312

@@ -35,49 +34,49 @@ public function processNode(Node $node, Scope $scope): array
3534
$extendsTags = $interface->getRequireExtendsTags();
3635
foreach ($extendsTags as $extendsTag) {
3736
$type = $extendsTag->getType();
38-
if (!$type instanceof ObjectType) {
39-
continue;
40-
}
37+
foreach ($type->getObjectClassNames() as $className) {
38+
if ($classReflection->is($className)) {
39+
continue;
40+
}
4141

42-
if ($classReflection->is($type->getClassName())) {
43-
continue;
44-
}
42+
$errors[] = RuleErrorBuilder::message(
43+
sprintf(
44+
'Interface %s requires implementing class to extend %s, but %s does not.',
45+
$interface->getDisplayName(),
46+
$type->describe(VerbosityLevel::typeOnly()),
47+
$classReflection->getDisplayName(),
48+
),
49+
)
50+
->identifier('class.missingExtends')
51+
->build();
4552

46-
$errors[] = RuleErrorBuilder::message(
47-
sprintf(
48-
'Interface %s requires implementing class to extend %s, but %s does not.',
49-
$interface->getDisplayName(),
50-
$type->describe(VerbosityLevel::typeOnly()),
51-
$classReflection->getDisplayName(),
52-
),
53-
)
54-
->identifier('class.missingExtends')
55-
->build();
53+
break;
54+
}
5655
}
5756
}
5857

5958
foreach ($classReflection->getTraits(true) as $trait) {
6059
$extendsTags = $trait->getRequireExtendsTags();
6160
foreach ($extendsTags as $extendsTag) {
6261
$type = $extendsTag->getType();
63-
if (!$type instanceof ObjectType) {
64-
continue;
65-
}
62+
foreach ($type->getObjectClassNames() as $className) {
63+
if ($classReflection->is($className)) {
64+
continue;
65+
}
6666

67-
if ($classReflection->is($type->getClassName())) {
68-
continue;
69-
}
67+
$errors[] = RuleErrorBuilder::message(
68+
sprintf(
69+
'Trait %s requires using class to extend %s, but %s does not.',
70+
$trait->getDisplayName(),
71+
$type->describe(VerbosityLevel::typeOnly()),
72+
$classReflection->getDisplayName(),
73+
),
74+
)
75+
->identifier('class.missingExtends')
76+
->build();
7077

71-
$errors[] = RuleErrorBuilder::message(
72-
sprintf(
73-
'Trait %s requires using class to extend %s, but %s does not.',
74-
$trait->getDisplayName(),
75-
$type->describe(VerbosityLevel::typeOnly()),
76-
$classReflection->getDisplayName(),
77-
),
78-
)
79-
->identifier('class.missingExtends')
80-
->build();
78+
break;
79+
}
8180
}
8281
}
8382

src/Rules/Comparison/ConstantLooseComparisonRule.php

+3-4
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->isFalse()->yes()) {
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

+3-2
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,12 @@ public function findSpecifiedType(
6969
if ($functionName === 'assert' && $argsCount >= 1) {
7070
$arg = $node->getArgs()[0]->value;
7171
$assertValue = ($this->treatPhpDocTypesAsCertain ? $scope->getType($arg) : $scope->getNativeType($arg))->toBoolean();
72-
if (!$assertValue instanceof ConstantBooleanType) {
72+
$assertValueIsTrue = $assertValue->isTrue()->yes();
73+
if (! $assertValueIsTrue && ! $assertValue->isFalse()->yes()) {
7374
return null;
7475
}
7576

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

0 commit comments

Comments
 (0)