diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 95215aa2f1..0dfe15c4bc 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -30,3 +30,4 @@ parameters: varTagType: true closureDefaultParameterTypeRule: true newRuleLevelHelper: true + instanceofType: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 3a19a84e26..b235a3239c 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -16,6 +16,8 @@ conditionalTags: phpstan.rules.rule: %featureToggles.runtimeReflectionRules% PHPStan\Rules\Api\ApiInstanceofRule: phpstan.rules.rule: %featureToggles.runtimeReflectionRules% + PHPStan\Rules\Api\ApiInstanceofTypeRule: + phpstan.rules.rule: %featureToggles.instanceofType% PHPStan\Rules\Api\RuntimeReflectionFunctionRule: phpstan.rules.rule: %featureToggles.runtimeReflectionRules% PHPStan\Rules\Api\RuntimeReflectionInstantiationRule: @@ -92,6 +94,8 @@ services: class: PHPStan\Rules\Api\ApiClassConstFetchRule - class: PHPStan\Rules\Api\ApiInstanceofRule + - + class: PHPStan\Rules\Api\ApiInstanceofTypeRule - class: PHPStan\Rules\Api\NodeConnectingVisitorAttributesRule - diff --git a/conf/config.neon b/conf/config.neon index ce198a3cd7..0b2ab875f4 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -60,6 +60,7 @@ parameters: varTagType: false closureDefaultParameterTypeRule: false newRuleLevelHelper: false + instanceofType: false fileExtensions: - php checkAdvancedIsset: false @@ -286,6 +287,7 @@ parametersSchema: varTagType: bool() closureDefaultParameterTypeRule: bool() newRuleLevelHelper: bool() + instanceofType: bool() ]) fileExtensions: listOf(string()) checkAdvancedIsset: bool() @@ -443,6 +445,8 @@ conditionalTags: phpstan.parser.richParserNodeVisitor: %featureToggles.nodeConnectingVisitorCompatibility% PHPStan\Parser\CurlSetOptArgVisitor: phpstan.parser.richParserNodeVisitor: %featureToggles.curlSetOptTypes% + PHPStan\Parser\TypeTraverserInstanceofVisitor: + phpstan.parser.richParserNodeVisitor: %featureToggles.instanceofType% services: - @@ -480,6 +484,9 @@ services: - class: PHPStan\Parser\CurlSetOptArgVisitor + - + class: PHPStan\Parser\TypeTraverserInstanceofVisitor + - class: PHPStan\Parser\ArrowFunctionArgVisitor tags: diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 15c7130f9e..e0f46684a7 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -31,6 +31,16 @@ parameters: count: 1 path: src/Analyser/MutatingScope.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 2 + path: src/Analyser/MutatingScope.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + count: 2 + path: src/Analyser/MutatingScope.php + - message: "#^Only numeric types are allowed in pre\\-decrement, bool\\|float\\|int\\|string\\|null given\\.$#" count: 1 @@ -51,6 +61,11 @@ parameters: count: 1 path: src/Analyser/NodeScopeResolver.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 5 + path: src/Analyser/TypeSpecifier.php + - message: "#^Template type TNodeType is declared as covariant, but occurs in contravariant position in parameter node of method PHPStan\\\\Collectors\\\\Collector\\:\\:processNode\\(\\)\\.$#" count: 1 @@ -141,6 +156,11 @@ parameters: count: 1 path: src/DependencyInjection/ParametersSchemaExtension.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Internal/ContainerDynamicReturnTypeExtension.php + - message: "#^Variable method call on PHPStan\\\\Reflection\\\\ClassReflection\\.$#" count: 2 @@ -214,6 +234,21 @@ parameters: count: 1 path: src/PhpDoc/Tag/VarTag.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone\\. Use Type\\:\\:getArrays\\(\\) instead\\.$#" + count: 1 + path: src/PhpDoc/TypeNodeResolver.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + count: 1 + path: src/PhpDoc/TypeNodeResolver.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + count: 1 + path: src/PhpDoc/TypeNodeResolver.php + - message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\Identifier\\\\Exception\\\\InvalidIdentifierName is never thrown in the try block\\.$#" count: 2 @@ -335,6 +370,16 @@ parameters: count: 1 path: src/Reflection/InitializerExprTypeResolver.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 4 + path: src/Reflection/InitializerExprTypeResolver.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 10 + path: src/Reflection/InitializerExprTypeResolver.php + - message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" count: 1 @@ -355,6 +400,11 @@ parameters: count: 1 path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Rules/Api/NodeConnectingVisitorAttributesRule.php + - message: """ #^Call to deprecated method doNotTreatPhpDocTypesAsCertain\\(\\) of class PHPStan\\\\Analyser\\\\Scope\\: @@ -363,6 +413,26 @@ parameters: count: 1 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 2 + path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 3 + path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + count: 1 + path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 1 + path: src/Rules/DeadCode/UnusedPrivateMethodRule.php + - 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\\.$#" count: 1 @@ -388,6 +458,16 @@ parameters: count: 1 path: src/Rules/DirectRegistry.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + count: 1 + path: src/Rules/FunctionReturnTypeCheck.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + count: 2 + path: src/Rules/Generators/YieldFromTypeRule.php + - 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\\.$#" count: 1 @@ -413,11 +493,111 @@ parameters: count: 1 path: src/Rules/LazyRegistry.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone\\. Use Type\\:\\:getArrays\\(\\) instead\\.$#" + count: 1 + path: src/Rules/Methods/MethodParameterComparisonHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + count: 1 + path: src/Rules/Methods/MethodParameterComparisonHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + count: 1 + path: src/Rules/Missing/MissingReturnRule.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + count: 2 + path: src/Rules/RuleLevelHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Rules/UnusedFunctionParametersCheck.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 1 + path: src/Rules/Variables/CompactVariablesRule.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Rules/Variables/CompactVariablesRule.php + - message: "#^Anonymous function has an unused use \\$container\\.$#" count: 1 path: src/Testing/PHPStanTestCase.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Accessory/AccessoryNonEmptyStringType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Accessory/AccessoryNumericStringType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 2 + path: src/Type/Accessory/HasOffsetValueType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone\\. Use Type\\:\\:getArrays\\(\\) instead\\.$#" + count: 3 + path: src/Type/ArrayType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 1 + path: src/Type/ArrayType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 2 + path: src/Type/ArrayType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + count: 2 + path: src/Type/BooleanType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + count: 4 + path: src/Type/CallableType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone\\. Use Type\\:\\:getArrays\\(\\) instead\\.$#" + count: 1 + path: src/Type/Constant/ConstantArrayType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 8 + path: src/Type/Constant/ConstantArrayType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 7 + path: src/Type/Constant/ConstantArrayType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + count: 1 + path: src/Type/Constant/ConstantArrayType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 2 + path: src/Type/Constant/ConstantArrayTypeBuilder.php + - message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" count: 2 @@ -428,21 +608,156 @@ parameters: count: 1 path: src/Type/Constant/ConstantArrayTypeBuilder.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + count: 1 + path: src/Type/Constant/ConstantBooleanType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + count: 1 + path: src/Type/Constant/ConstantFloatType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + count: 1 + path: src/Type/Constant/ConstantIntegerType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + count: 1 + path: src/Type/Constant/ConstantStringType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 4 + path: src/Type/Constant/ConstantStringType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + count: 1 + path: src/Type/Constant/ConstantStringType.php + - message: "#^PHPDoc tag @var with type int\\|string is not subtype of type string\\.$#" count: 1 path: src/Type/Constant/ConstantStringType.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 1 + path: src/Type/Constant/OversizedArrayBuilder.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" + count: 2 + path: src/Type/Enum/EnumCaseObjectType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + count: 2 + path: src/Type/FloatType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + count: 1 + path: src/Type/Generic/GenericClassStringType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 4 + path: src/Type/Generic/GenericClassStringType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + count: 2 + path: src/Type/Generic/GenericClassStringType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + count: 1 + path: src/Type/Generic/GenericObjectType.php + - message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\IntersectionType will always evaluate to false\\.$#" count: 2 path: src/Type/Generic/TemplateIntersectionType.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone\\. Use Type\\:\\:getArrays\\(\\) instead\\.$#" + count: 1 + path: src/Type/Generic/TemplateTypeFactory.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + count: 1 + path: src/Type/Generic/TemplateTypeFactory.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 1 + path: src/Type/Generic/TemplateTypeFactory.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Generic/TemplateTypeFactory.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + count: 1 + path: src/Type/Generic/TemplateTypeFactory.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + count: 1 + path: src/Type/Generic/TemplateTypeFactory.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + count: 1 + path: src/Type/Generic/TemplateTypeFactory.php + - message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\UnionType will always evaluate to false\\.$#" count: 2 path: src/Type/Generic/TemplateUnionType.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + count: 3 + path: src/Type/IntegerRangeType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + count: 2 + path: src/Type/IntegerType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + count: 2 + path: src/Type/IntersectionType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + count: 1 + path: src/Type/IntersectionType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + count: 2 + path: src/Type/IntersectionType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + count: 2 + path: src/Type/IterableType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + count: 3 + path: src/Type/NullType.php + - message: """ #^Call to deprecated method getInstance\\(\\) of class PHPStan\\\\Broker\\\\Broker\\: @@ -459,6 +774,76 @@ parameters: count: 1 path: src/Type/ObjectType.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" + count: 1 + path: src/Type/ObjectType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 2 + path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 4 + path: src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/CompactFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/CompactFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/DefineConstantTypeSpecifyingExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/DefinedConstantTypeSpecifyingExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/DsMapDynamicReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/FilterFunctionReturnTypeHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/IsAFunctionTypeSpecifyingExtension.php + - message: """ #^Call to deprecated method getTypeFromValue\\(\\) of class PHPStan\\\\Type\\\\ConstantTypeHelper\\: @@ -467,6 +852,216 @@ parameters: count: 1 path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 2 + path: src/Type/Php/LtrimFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/MbStrlenFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/MbSubstituteCharacterDynamicReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/MethodExistsTypeSpecifyingExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 2 + path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 2 + path: src/Type/Php/PropertyExistsTypeSpecifyingExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 2 + path: src/Type/Php/RangeFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/StrRepeatFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/Php/StrlenFunctionReturnTypeExtension.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: src/Type/StringType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + count: 2 + path: src/Type/StringType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + count: 1 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone\\. Use Type\\:\\:getArrays\\(\\) instead\\.$#" + count: 5 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + count: 1 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + count: 1 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + count: 1 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 12 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 4 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + count: 1 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + count: 1 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + count: 8 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + count: 2 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + count: 1 + path: src/Type/TypeCombinator.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone\\. Use Type\\:\\:getArrays\\(\\) instead\\.$#" + count: 3 + path: src/Type/TypeUtils.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 5 + path: src/Type/TypeUtils.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone\\. Use Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + count: 1 + path: src/Type/TypeUtils.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone\\. Use Type\\:\\:getArrays\\(\\) instead\\.$#" + count: 3 + path: src/Type/TypehintHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + count: 1 + path: src/Type/TypehintHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + count: 2 + path: src/Type/UnionType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + count: 1 + path: src/Type/UnionType.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + count: 3 + path: src/Type/UnionTypeHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 2 + path: src/Type/UnionTypeHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + count: 2 + path: src/Type/UnionTypeHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + count: 2 + path: src/Type/UnionTypeHelper.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + count: 1 + path: src/Type/VerbosityLevel.php + + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\VoidType is error\\-prone\\. Use Type\\:\\:isVoid\\(\\) instead\\.$#" + count: 3 + path: src/Type/VoidType.php + - message: "#^Unreachable statement \\- code above always terminates\\.$#" count: 1 diff --git a/src/Parser/TypeTraverserInstanceofVisitor.php b/src/Parser/TypeTraverserInstanceofVisitor.php new file mode 100644 index 0000000000..a39226bbb2 --- /dev/null +++ b/src/Parser/TypeTraverserInstanceofVisitor.php @@ -0,0 +1,56 @@ +depth = 0; + return null; + } + + public function enterNode(Node $node): ?Node + { + if ($node instanceof Node\Expr\Instanceof_ && $this->depth > 0) { + $node->setAttribute(self::ATTRIBUTE_NAME, true); + return null; + } + + if ( + $node instanceof Node\Expr\StaticCall + && $node->class instanceof Node\Name + && $node->class->toLowerString() === 'phpstan\\type\\typetraverser' + && $node->name instanceof Node\Identifier + && $node->name->toLowerString() === 'map' + ) { + $this->depth++; + } + + return null; + } + + public function leaveNode(Node $node): ?Node + { + if ( + $node instanceof Node\Expr\StaticCall + && $node->class instanceof Node\Name + && $node->class->toLowerString() === 'phpstan\\type\\typetraverser' + && $node->name instanceof Node\Identifier + && $node->name->toLowerString() === 'map' + ) { + $this->depth--; + } + + return null; + } + +} diff --git a/src/Rules/Api/ApiInstanceofTypeRule.php b/src/Rules/Api/ApiInstanceofTypeRule.php new file mode 100644 index 0000000000..a83385278e --- /dev/null +++ b/src/Rules/Api/ApiInstanceofTypeRule.php @@ -0,0 +1,126 @@ + + */ +class ApiInstanceofTypeRule implements Rule +{ + + private const MAP = [ + TypeWithClassName::class => 'Type::getObjectClassNames()', + EnumCaseObjectType::class => 'Type::getEnumCases()', + ConstantArrayType::class => 'Type::getConstantArrays()', + ArrayType::class => 'Type::getArrays()', + ConstantStringType::class => 'Type::getConstantStrings()', + StringType::class => 'Type::isString()', + ClassStringType::class => 'Type::isClassStringType()', + IntegerType::class => 'Type::isInteger()', + FloatType::class => 'Type::isFloat()', + NullType::class => 'Type::isNull()', + VoidType::class => 'Type::isVoid()', + BooleanType::class => 'Type::isBoolean()', + // ConstantBooleanType::class => 'Type::isTrue() or Type::isFalse()', skipped because not that valuable + CallableType::class => 'Type::isCallable() and Type::getCallableParametersAcceptors()', + IterableType::class => 'Type::isIterable()', + + // accessory types + NonEmptyArrayType::class => 'Type::isIterableAtLeastOnce()', + OversizedArrayType::class => 'Type::isOversizedArray()', + AccessoryArrayListType::class => 'Type::isList()', + AccessoryNumericStringType::class => 'Type::isNumericString()', + AccessoryLiteralStringType::class => 'Type::isLiteralString()', + AccessoryNonEmptyStringType::class => 'Type::isNonEmptyString()', + AccessoryNonFalsyStringType::class => 'Type::isNonFalsyString()', + HasMethodType::class => 'Type::hasMethod()', + HasPropertyType::class => 'Type::hasProperty()', + HasOffsetType::class => 'Type::hasOffsetValueType()', + AccessoryType::class => 'methods on PHPStan\\Type\\Type', + ]; + + public function __construct(private ReflectionProvider $reflectionProvider) + { + } + + public function getNodeType(): string + { + return Instanceof_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (!$node->class instanceof Node\Name) { + return []; + } + + if ($node->getAttribute(TypeTraverserInstanceofVisitor::ATTRIBUTE_NAME, false) === true) { + return []; + } + + $lowerMap = []; + foreach (self::MAP as $className => $method) { + $lowerMap[strtolower($className)] = $method; + } + + $className = $scope->resolveName($node->class); + $lowerClassName = strtolower($className); + if (!array_key_exists($lowerClassName, $lowerMap)) { + return []; + } + + if ($this->reflectionProvider->hasClass($className)) { + $classReflection = $this->reflectionProvider->getClass($className); + if ($classReflection->isSubclassOf(AccessoryType::class)) { + if ($className === $classReflection->getName()) { + return []; + } + } + } + + return [ + RuleErrorBuilder::message(sprintf( + 'Doing instanceof %s is error-prone. Use %s instead.', + $className, + $lowerMap[$lowerClassName], + ))->build(), + ]; + } + +} diff --git a/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php b/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php new file mode 100644 index 0000000000..bc5bbb79c7 --- /dev/null +++ b/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php @@ -0,0 +1,37 @@ + + */ +class ApiInstanceofTypeRuleTest extends RuleTestCase +{ + + public function getRule(): Rule + { + return new ApiInstanceofTypeRule($this->createReflectionProvider()); + } + + public function testRule(): void + { + $this->analyse([__DIR__ . '/data/instanceof-type.php'], [ + [ + 'Doing instanceof PHPStan\Type\TypeWithClassName is error-prone. Use Type::getObjectClassNames() instead.', + 19, + ], + [ + 'Doing instanceof phpstan\type\typewithclassname is error-prone. Use Type::getObjectClassNames() instead.', + 23, + ], + [ + 'Doing instanceof PHPStan\Type\TypeWithClassName is error-prone. Use Type::getObjectClassNames() instead.', + 35, + ], + ]); + } + +} diff --git a/tests/PHPStan/Rules/Api/data/instanceof-type.php b/tests/PHPStan/Rules/Api/data/instanceof-type.php new file mode 100644 index 0000000000..3a096d5b67 --- /dev/null +++ b/tests/PHPStan/Rules/Api/data/instanceof-type.php @@ -0,0 +1,40 @@ +