From 4df6e0bdc97d82a39ded39fada78f32ab2428d62 Mon Sep 17 00:00:00 2001 From: Carlos Granados Date: Fri, 15 Nov 2024 13:04:39 +0100 Subject: [PATCH 1/6] Updates for PHPStan 2.0 --- composer.json | 4 ++-- phpstan.neon | 1 - .../ClassMethodCallReferenceResolver.php | 4 ++-- src/Printer/CollectorMetadataPrinter.php | 23 +++++++++---------- src/Printer/NodeComparator.php | 6 ++--- src/Reflection/ReflectionParser.php | 3 ++- .../NarrowPrivateClassMethodParamTypeRule.php | 5 +--- src/Rules/NarrowReturnObjectTypeRule.php | 14 ++++++----- src/Rules/NoArrayAccessOnObjectRule.php | 1 + src/Rules/NoMixedMethodCallerRule.php | 6 ++--- src/Rules/NoMixedPropertyFetcherRule.php | 6 ++--- src/Rules/NoParamTypeRemovalRule.php | 1 + src/Rules/ReturnNullOverFalseRule.php | 3 ++- ...rowPrivateClassMethodParamTypeRuleTest.php | 2 +- ...rrowPublicClassMethodParamTypeRuleTest.php | 2 +- .../NarrowReturnObjectTypeRuleTest.php | 2 +- .../NoArrayAccessOnObjectRuleTest.php | 2 +- .../NoEmptyOnObjectRuleTest.php | 2 +- .../NoIssetOnObjectRuleTest.php | 2 +- .../NoMixedMethodCallerRuleTest.php | 3 +++ .../NoMixedPropertyFetcherRuleTest.php | 3 +++ .../NoParamTypeRemovalRuleTest.php | 2 +- .../ReturnNullOverFalseRuleTest.php | 2 +- 23 files changed, 53 insertions(+), 46 deletions(-) diff --git a/composer.json b/composer.json index 1c2c2f8b..8893230e 100644 --- a/composer.json +++ b/composer.json @@ -5,11 +5,11 @@ "license": "MIT", "require": { "php": "^8.2", - "phpstan/phpstan": "^1.11", + "phpstan/phpstan": "^2.0", "webmozart/assert": "^1.11" }, "require-dev": { - "nikic/php-parser": "^4.19", + "nikic/php-parser": "^5.0", "symplify/phpstan-extensions": "^11.4", "symplify/rule-doc-generator": "^12.1", "phpunit/phpunit": "^10.5", diff --git a/phpstan.neon b/phpstan.neon index 8d75e428..47de06c2 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -19,4 +19,3 @@ parameters: # overly detailed generics - '#Rector\\TypePerfect\\Tests\\Rules\\(.*?) generic (class|interface)#' - - '#Method Rector\\TypePerfect\\Tests\\Rules\\(.*?)testRule\(\) has parameter \$expectedErrorsWithLines with no value type specified in iterable type array#' diff --git a/src/Matcher/ClassMethodCallReferenceResolver.php b/src/Matcher/ClassMethodCallReferenceResolver.php index 747be901..714333e8 100644 --- a/src/Matcher/ClassMethodCallReferenceResolver.php +++ b/src/Matcher/ClassMethodCallReferenceResolver.php @@ -40,12 +40,12 @@ public function resolve(MethodCall|MethodCallableNode $methodCallOrMethodCallabl return null; } - if (! $callerType instanceof TypeWithClassName) { + if (count($callerType->getObjectClassNames()) !== 1) { return null; } // move to the class where method is defined, e.g. parent class defines the method, so it should be checked there - $className = $callerType->getClassName(); + $className = $callerType->getObjectClassNames()[0]; $methodNameString = $methodName->toString(); return new MethodCallReference($className, $methodNameString); diff --git a/src/Printer/CollectorMetadataPrinter.php b/src/Printer/CollectorMetadataPrinter.php index a92b5bec..b8c9f86d 100644 --- a/src/Printer/CollectorMetadataPrinter.php +++ b/src/Printer/CollectorMetadataPrinter.php @@ -13,7 +13,7 @@ use PhpParser\Node\NullableType; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\UnionType; -use PhpParser\PrettyPrinter\Standard; +use PHPStan\Node\Printer\Printer; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ParametersAcceptorSelector; @@ -35,11 +35,9 @@ final readonly class CollectorMetadataPrinter { - private Standard $printerStandard; - - public function __construct() - { - $this->printerStandard = new Standard(); + public function __construct( + private Printer $printer + ) { } public function printArgTypesAsString(MethodCall $methodCall, ExtendedMethodReflection $extendedMethodReflection, Scope $scope): string @@ -56,6 +54,7 @@ public function printArgTypesAsString(MethodCall $methodCall, ExtendedMethodRefl return ResolvedTypes::UNKNOWN_TYPES; } + // @phpstan-ignore phpstanApi.instanceofType if ($argType instanceof IntersectionType) { return ResolvedTypes::UNKNOWN_TYPES; } @@ -100,7 +99,7 @@ public function printParamTypesToString(ClassMethod $classMethod, ?string $class $paramType = $this->resolveSortedTypes($paramType, $className); } - $printedParamType = $this->printerStandard->prettyPrint([$paramType]); + $printedParamType = $this->printer->prettyPrint([$paramType]); $printedParamType = str_replace('\Closure', 'callable', $printedParamType); $printedParamType = ltrim($printedParamType, '\\'); $printedParamType = str_replace('|\\', '|', $printedParamType); @@ -160,15 +159,15 @@ private function resolveSortedTypes(UnionType|NodeIntersectionType $paramType, ? private function printTypeToString(Type $type): string { - if ($type instanceof ClassStringType) { + if ($type->isClassString()->yes()) { return 'string'; } - if ($type instanceof ArrayType) { + if ($type->isArray()->yes()) { return 'array'; } - if ($type instanceof BooleanType) { + if ($type->isBoolean()->yes()) { return 'bool'; } @@ -180,8 +179,8 @@ private function printTypeToString(Type $type): string return 'callable'; } - if ($type instanceof EnumCaseObjectType) { - return $type->getClassName(); + if (count($type->getEnumCases()) === 1) { + return $type->getEnumCases()[0]->getClassName(); } return $type->describe(VerbosityLevel::typeOnly()); diff --git a/src/Printer/NodeComparator.php b/src/Printer/NodeComparator.php index c8cbc7fe..1d1efaef 100644 --- a/src/Printer/NodeComparator.php +++ b/src/Printer/NodeComparator.php @@ -5,12 +5,12 @@ namespace Rector\TypePerfect\Printer; use PhpParser\Node; -use PhpParser\PrettyPrinter\Standard; +use PHPStan\Node\Printer\Printer; final readonly class NodeComparator { public function __construct( - private Standard $standard + private Printer $printer ) { } @@ -20,6 +20,6 @@ public function areNodesEqual(Node $firstNode, Node $secondNode): bool $firstNode->setAttribute('comments', null); $secondNode->setAttribute('comments', null); - return $this->standard->prettyPrint([$firstNode]) === $this->standard->prettyPrint([$secondNode]); + return $this->printer->prettyPrint([$firstNode]) === $this->printer->prettyPrint([$secondNode]); } } diff --git a/src/Reflection/ReflectionParser.php b/src/Reflection/ReflectionParser.php index 2419be1e..df982ab6 100644 --- a/src/Reflection/ReflectionParser.php +++ b/src/Reflection/ReflectionParser.php @@ -11,6 +11,7 @@ use PhpParser\NodeVisitor\NameResolver; use PhpParser\Parser; use PhpParser\ParserFactory; +use PhpParser\PhpVersion; use PHPStan\Reflection\ClassReflection; use Throwable; @@ -26,7 +27,7 @@ final class ReflectionParser public function __construct() { $parserFactory = new ParserFactory(); - $this->parser = $parserFactory->create(ParserFactory::PREFER_PHP7); + $this->parser = $parserFactory->createForVersion(PhpVersion::fromString('7.4')); } public function parseClassReflection(ClassReflection $classReflection): ?ClassLike diff --git a/src/Rules/NarrowPrivateClassMethodParamTypeRule.php b/src/Rules/NarrowPrivateClassMethodParamTypeRule.php index a2a8bd03..3d45e0c6 100644 --- a/src/Rules/NarrowPrivateClassMethodParamTypeRule.php +++ b/src/Rules/NarrowPrivateClassMethodParamTypeRule.php @@ -110,10 +110,6 @@ private function validateArgVsParamTypes(array $args, MethodCall $methodCall, Sc continue; } - if (! $arg instanceof Arg) { - continue; - } - $paramRuleError = $this->validateParam($param, $position, $arg->value, $scope); if (! $paramRuleError instanceof RuleError) { continue; @@ -149,6 +145,7 @@ private function validateParam(Param $param, int $position, Expr $expr, Scope $s return null; } + // @phpstan-ignore phpstanApi.instanceofType if ($argType instanceof IntersectionType) { return null; } diff --git a/src/Rules/NarrowReturnObjectTypeRule.php b/src/Rules/NarrowReturnObjectTypeRule.php index 5d7655e5..ad63368e 100644 --- a/src/Rules/NarrowReturnObjectTypeRule.php +++ b/src/Rules/NarrowReturnObjectTypeRule.php @@ -94,8 +94,11 @@ public function processNode(Node $node, Scope $scope): array return []; } - /** @var TypeWithClassName $returnExprType */ - $errorMessage = sprintf(self::ERROR_MESSAGE, $returnExprType->getClassName()); + if (count($returnExprType->getObjectClassNames()) !== 1) { + return []; + } + + $errorMessage = sprintf(self::ERROR_MESSAGE, $returnExprType->getObjectClassNames()[0]); return [ RuleErrorBuilder::message($errorMessage) @@ -127,15 +130,14 @@ private function shouldSkipScope(Scope $scope): bool private function shouldSkipReturnExprType(Type $type): bool { - if (! $type instanceof TypeWithClassName) { + if (count($type->getObjectClassNames()) !== 1) { return true; } - $classReflection = $type->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { + if (count($type->getObjectClassReflections()) !== 1) { return true; } - return $classReflection->isAnonymous(); + return $type->getObjectClassReflections()[0]->isAnonymous(); } } diff --git a/src/Rules/NoArrayAccessOnObjectRule.php b/src/Rules/NoArrayAccessOnObjectRule.php index 577cac7d..45f5c633 100644 --- a/src/Rules/NoArrayAccessOnObjectRule.php +++ b/src/Rules/NoArrayAccessOnObjectRule.php @@ -43,6 +43,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { $varType = $scope->getType($node->var); + // @phpstan-ignore phpstanApi.instanceofType if (! $varType instanceof ObjectType) { return []; } diff --git a/src/Rules/NoMixedMethodCallerRule.php b/src/Rules/NoMixedMethodCallerRule.php index 5f667f4f..44b7b2df 100644 --- a/src/Rules/NoMixedMethodCallerRule.php +++ b/src/Rules/NoMixedMethodCallerRule.php @@ -6,7 +6,7 @@ use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; -use PhpParser\PrettyPrinter\Standard; +use PHPStan\Node\Printer\Printer; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleError; @@ -27,7 +27,7 @@ public const ERROR_MESSAGE = 'Mixed variable in a `%s->...()` can skip important errors. Make sure the type is known'; public function __construct( - private Standard $printerStandard, + private Printer $printer, private Configuration $configuration, ) { } @@ -65,7 +65,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - $printedMethodCall = $this->printerStandard->prettyPrintExpr($node->var); + $printedMethodCall = $this->printer->prettyPrintExpr($node->var); return [ RuleErrorBuilder::message(sprintf(self::ERROR_MESSAGE, $printedMethodCall)) diff --git a/src/Rules/NoMixedPropertyFetcherRule.php b/src/Rules/NoMixedPropertyFetcherRule.php index 66e2af2b..5f49047b 100644 --- a/src/Rules/NoMixedPropertyFetcherRule.php +++ b/src/Rules/NoMixedPropertyFetcherRule.php @@ -6,7 +6,7 @@ use PhpParser\Node; use PhpParser\Node\Expr\PropertyFetch; -use PhpParser\PrettyPrinter\Standard; +use PHPStan\Node\Printer\Printer; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleError; @@ -26,7 +26,7 @@ public const ERROR_MESSAGE = 'Mixed property fetch in a "%s->..." can skip important errors. Make sure the type is known'; public function __construct( - private Standard $standard, + private Printer $printer, private Configuration $configuration, ) { } @@ -54,7 +54,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - $printedVar = $this->standard->prettyPrintExpr($node->var); + $printedVar = $this->printer->prettyPrintExpr($node->var); return [ RuleErrorBuilder::message(sprintf(self::ERROR_MESSAGE, $printedVar)) diff --git a/src/Rules/NoParamTypeRemovalRule.php b/src/Rules/NoParamTypeRemovalRule.php index a6046036..9f1e195d 100644 --- a/src/Rules/NoParamTypeRemovalRule.php +++ b/src/Rules/NoParamTypeRemovalRule.php @@ -55,6 +55,7 @@ public function processNode(Node $node, Scope $scope): array } $parentClassMethodReflection = $this->methodNodeAnalyser->matchFirstParentClassMethod($scope, $classMethodName); + // @phpstan-ignore phpstanApi.instanceofAssumption if (! $parentClassMethodReflection instanceof PhpMethodReflection) { return []; } diff --git a/src/Rules/ReturnNullOverFalseRule.php b/src/Rules/ReturnNullOverFalseRule.php index 81fc8dd0..659c4a1d 100644 --- a/src/Rules/ReturnNullOverFalseRule.php +++ b/src/Rules/ReturnNullOverFalseRule.php @@ -74,8 +74,9 @@ public function processNode(Node $node, Scope $scope): array } $exprType = $scope->getType($return->expr); + // @phpstan-ignore phpstanApi.instanceofType if (! $exprType instanceof ConstantBooleanType) { - if ($exprType instanceof BooleanType) { + if ($exprType->isBoolean()->yes()) { return []; } diff --git a/tests/Rules/NarrowPrivateClassMethodParamTypeRule/NarrowPrivateClassMethodParamTypeRuleTest.php b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/NarrowPrivateClassMethodParamTypeRuleTest.php index d8a0a3f1..1005cc1d 100644 --- a/tests/Rules/NarrowPrivateClassMethodParamTypeRule/NarrowPrivateClassMethodParamTypeRuleTest.php +++ b/tests/Rules/NarrowPrivateClassMethodParamTypeRule/NarrowPrivateClassMethodParamTypeRuleTest.php @@ -16,7 +16,7 @@ final class NarrowPrivateClassMethodParamTypeRuleTest extends RuleTestCase { /** - * @param mixed[] $expectedErrorsWithLines + * @param list $expectedErrorsWithLines */ #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorsWithLines): void diff --git a/tests/Rules/NarrowPublicClassMethodParamTypeRule/NarrowPublicClassMethodParamTypeRuleTest.php b/tests/Rules/NarrowPublicClassMethodParamTypeRule/NarrowPublicClassMethodParamTypeRuleTest.php index 42046f45..88578e0c 100644 --- a/tests/Rules/NarrowPublicClassMethodParamTypeRule/NarrowPublicClassMethodParamTypeRuleTest.php +++ b/tests/Rules/NarrowPublicClassMethodParamTypeRule/NarrowPublicClassMethodParamTypeRuleTest.php @@ -16,7 +16,7 @@ final class NarrowPublicClassMethodParamTypeRuleTest extends RuleTestCase { /** * @param string[] $filePaths - * @param mixed[] $expectedErrorsWithLines + * @param list $expectedErrorsWithLines */ #[DataProvider('provideData')] public function testRule(array $filePaths, array $expectedErrorsWithLines): void diff --git a/tests/Rules/NarrowReturnObjectTypeRule/NarrowReturnObjectTypeRuleTest.php b/tests/Rules/NarrowReturnObjectTypeRule/NarrowReturnObjectTypeRuleTest.php index e5ae2264..ad525cac 100644 --- a/tests/Rules/NarrowReturnObjectTypeRule/NarrowReturnObjectTypeRuleTest.php +++ b/tests/Rules/NarrowReturnObjectTypeRule/NarrowReturnObjectTypeRuleTest.php @@ -14,7 +14,7 @@ final class NarrowReturnObjectTypeRuleTest extends RuleTestCase { /** - * @param mixed[] $expectedErrorMessagesWithLines + * @param list $expectedErrorMessagesWithLines */ #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void diff --git a/tests/Rules/NoArrayAccessOnObjectRule/NoArrayAccessOnObjectRuleTest.php b/tests/Rules/NoArrayAccessOnObjectRule/NoArrayAccessOnObjectRuleTest.php index 8977e63c..7b5030f0 100644 --- a/tests/Rules/NoArrayAccessOnObjectRule/NoArrayAccessOnObjectRuleTest.php +++ b/tests/Rules/NoArrayAccessOnObjectRule/NoArrayAccessOnObjectRuleTest.php @@ -13,7 +13,7 @@ final class NoArrayAccessOnObjectRuleTest extends RuleTestCase { /** - * @param mixed[] $expectedErrorMessagesWithLines + * @param list $expectedErrorMessagesWithLines */ #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void diff --git a/tests/Rules/NoEmptyOnObjectRule/NoEmptyOnObjectRuleTest.php b/tests/Rules/NoEmptyOnObjectRule/NoEmptyOnObjectRuleTest.php index 1509b964..59ce9fd4 100644 --- a/tests/Rules/NoEmptyOnObjectRule/NoEmptyOnObjectRuleTest.php +++ b/tests/Rules/NoEmptyOnObjectRule/NoEmptyOnObjectRuleTest.php @@ -13,7 +13,7 @@ final class NoEmptyOnObjectRuleTest extends RuleTestCase { /** - * @param mixed[] $expectedErrorMessagesWithLines + * @param list $expectedErrorMessagesWithLines */ #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void diff --git a/tests/Rules/NoIssetOnObjectRule/NoIssetOnObjectRuleTest.php b/tests/Rules/NoIssetOnObjectRule/NoIssetOnObjectRuleTest.php index aafa1472..a9f915b4 100644 --- a/tests/Rules/NoIssetOnObjectRule/NoIssetOnObjectRuleTest.php +++ b/tests/Rules/NoIssetOnObjectRule/NoIssetOnObjectRuleTest.php @@ -13,7 +13,7 @@ final class NoIssetOnObjectRuleTest extends RuleTestCase { /** - * @param mixed[] $expectedErrorMessagesWithLines + * @param list $expectedErrorMessagesWithLines */ #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void diff --git a/tests/Rules/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php b/tests/Rules/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php index 1e8d2749..ffc37211 100644 --- a/tests/Rules/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php +++ b/tests/Rules/NoMixedMethodCallerRule/NoMixedMethodCallerRuleTest.php @@ -12,6 +12,9 @@ final class NoMixedMethodCallerRuleTest extends RuleTestCase { + /** + * @param list $expectedErrorsWithLines + */ #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorsWithLines): void { diff --git a/tests/Rules/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php b/tests/Rules/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php index 215f5028..6d84b500 100644 --- a/tests/Rules/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php +++ b/tests/Rules/NoMixedPropertyFetcherRule/NoMixedPropertyFetcherRuleTest.php @@ -12,6 +12,9 @@ final class NoMixedPropertyFetcherRuleTest extends RuleTestCase { + /** + * @param list $expectedErrorsWithLines + */ #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorsWithLines): void { diff --git a/tests/Rules/NoParamTypeRemovalRule/NoParamTypeRemovalRuleTest.php b/tests/Rules/NoParamTypeRemovalRule/NoParamTypeRemovalRuleTest.php index 0e2fbfc9..d79d8ef2 100644 --- a/tests/Rules/NoParamTypeRemovalRule/NoParamTypeRemovalRuleTest.php +++ b/tests/Rules/NoParamTypeRemovalRule/NoParamTypeRemovalRuleTest.php @@ -13,7 +13,7 @@ final class NoParamTypeRemovalRuleTest extends RuleTestCase { /** - * @param mixed[] $expectedErrorMessagesWithLines + * @param list $expectedErrorMessagesWithLines */ #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void diff --git a/tests/Rules/ReturnNullOverFalseRule/ReturnNullOverFalseRuleTest.php b/tests/Rules/ReturnNullOverFalseRule/ReturnNullOverFalseRuleTest.php index 7c53c9cb..677156db 100644 --- a/tests/Rules/ReturnNullOverFalseRule/ReturnNullOverFalseRuleTest.php +++ b/tests/Rules/ReturnNullOverFalseRule/ReturnNullOverFalseRuleTest.php @@ -13,7 +13,7 @@ final class ReturnNullOverFalseRuleTest extends RuleTestCase { /** - * @param mixed[] $expectedErrorMessagesWithLines + * @param list $expectedErrorMessagesWithLines */ #[DataProvider('provideData')] public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void From 9818b4247fb5c3afdfe1d3df1876b796fb623585 Mon Sep 17 00:00:00 2001 From: Carlos Granados Date: Fri, 15 Nov 2024 14:18:39 +0100 Subject: [PATCH 2/6] Changes after PR review --- phpstan.neon | 13 +++++++++++++ src/Printer/CollectorMetadataPrinter.php | 10 ++++------ src/Reflection/ReflectionParser.php | 3 +-- src/Rules/NarrowPrivateClassMethodParamTypeRule.php | 1 - src/Rules/NoArrayAccessOnObjectRule.php | 1 - src/Rules/NoParamTypeRemovalRule.php | 1 - src/Rules/ReturnNullOverFalseRule.php | 2 -- 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 47de06c2..09501de1 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -19,3 +19,16 @@ parameters: # overly detailed generics - '#Rector\\TypePerfect\\Tests\\Rules\\(.*?) generic (class|interface)#' + + - + identifier: phpstanApi.instanceofType + paths: + - src/Printer/CollectorMetadataPrinter.php + - src/Rules/NarrowPrivateClassMethodParamTypeRule.php + - src/Rules/NoArrayAccessOnObjectRule.php + - src/Rules/ReturnNullOverFalseRule.php + + - + identifier: phpstanApi.instanceofAssumption + paths: + - src/Rules/NoParamTypeRemovalRule.php diff --git a/src/Printer/CollectorMetadataPrinter.php b/src/Printer/CollectorMetadataPrinter.php index b8c9f86d..ed82c97c 100644 --- a/src/Printer/CollectorMetadataPrinter.php +++ b/src/Printer/CollectorMetadataPrinter.php @@ -13,15 +13,12 @@ use PhpParser\Node\NullableType; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\UnionType; +use PhpParser\PrettyPrinter\Standard; use PHPStan\Node\Printer\Printer; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ParametersAcceptorSelector; -use PHPStan\Type\ArrayType; -use PHPStan\Type\BooleanType; -use PHPStan\Type\ClassStringType; use PHPStan\Type\ClosureType; -use PHPStan\Type\Enum\EnumCaseObjectType; use PHPStan\Type\IntegerRangeType; use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; @@ -35,9 +32,11 @@ final readonly class CollectorMetadataPrinter { + private Standard $printer; + public function __construct( - private Printer $printer ) { + $this->printer = new Standard(); } public function printArgTypesAsString(MethodCall $methodCall, ExtendedMethodReflection $extendedMethodReflection, Scope $scope): string @@ -54,7 +53,6 @@ public function printArgTypesAsString(MethodCall $methodCall, ExtendedMethodRefl return ResolvedTypes::UNKNOWN_TYPES; } - // @phpstan-ignore phpstanApi.instanceofType if ($argType instanceof IntersectionType) { return ResolvedTypes::UNKNOWN_TYPES; } diff --git a/src/Reflection/ReflectionParser.php b/src/Reflection/ReflectionParser.php index df982ab6..7e72ac2d 100644 --- a/src/Reflection/ReflectionParser.php +++ b/src/Reflection/ReflectionParser.php @@ -11,7 +11,6 @@ use PhpParser\NodeVisitor\NameResolver; use PhpParser\Parser; use PhpParser\ParserFactory; -use PhpParser\PhpVersion; use PHPStan\Reflection\ClassReflection; use Throwable; @@ -27,7 +26,7 @@ final class ReflectionParser public function __construct() { $parserFactory = new ParserFactory(); - $this->parser = $parserFactory->createForVersion(PhpVersion::fromString('7.4')); + $this->parser = $parserFactory->createForNewestSupportedVersion(); } public function parseClassReflection(ClassReflection $classReflection): ?ClassLike diff --git a/src/Rules/NarrowPrivateClassMethodParamTypeRule.php b/src/Rules/NarrowPrivateClassMethodParamTypeRule.php index 3d45e0c6..4c8d82e6 100644 --- a/src/Rules/NarrowPrivateClassMethodParamTypeRule.php +++ b/src/Rules/NarrowPrivateClassMethodParamTypeRule.php @@ -145,7 +145,6 @@ private function validateParam(Param $param, int $position, Expr $expr, Scope $s return null; } - // @phpstan-ignore phpstanApi.instanceofType if ($argType instanceof IntersectionType) { return null; } diff --git a/src/Rules/NoArrayAccessOnObjectRule.php b/src/Rules/NoArrayAccessOnObjectRule.php index 45f5c633..577cac7d 100644 --- a/src/Rules/NoArrayAccessOnObjectRule.php +++ b/src/Rules/NoArrayAccessOnObjectRule.php @@ -43,7 +43,6 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { $varType = $scope->getType($node->var); - // @phpstan-ignore phpstanApi.instanceofType if (! $varType instanceof ObjectType) { return []; } diff --git a/src/Rules/NoParamTypeRemovalRule.php b/src/Rules/NoParamTypeRemovalRule.php index 9f1e195d..a6046036 100644 --- a/src/Rules/NoParamTypeRemovalRule.php +++ b/src/Rules/NoParamTypeRemovalRule.php @@ -55,7 +55,6 @@ public function processNode(Node $node, Scope $scope): array } $parentClassMethodReflection = $this->methodNodeAnalyser->matchFirstParentClassMethod($scope, $classMethodName); - // @phpstan-ignore phpstanApi.instanceofAssumption if (! $parentClassMethodReflection instanceof PhpMethodReflection) { return []; } diff --git a/src/Rules/ReturnNullOverFalseRule.php b/src/Rules/ReturnNullOverFalseRule.php index 659c4a1d..de73e04d 100644 --- a/src/Rules/ReturnNullOverFalseRule.php +++ b/src/Rules/ReturnNullOverFalseRule.php @@ -13,7 +13,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleError; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\BooleanType; use PHPStan\Type\Constant\ConstantBooleanType; use Rector\TypePerfect\Configuration; @@ -74,7 +73,6 @@ public function processNode(Node $node, Scope $scope): array } $exprType = $scope->getType($return->expr); - // @phpstan-ignore phpstanApi.instanceofType if (! $exprType instanceof ConstantBooleanType) { if ($exprType->isBoolean()->yes()) { return []; From 647cc0ebb595d366930ef910850e28cd25fa1e48 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 12 Dec 2024 17:33:57 +0700 Subject: [PATCH 3/6] Bump to phpstan-extension 12.0 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 8893230e..28337644 100644 --- a/composer.json +++ b/composer.json @@ -10,10 +10,10 @@ }, "require-dev": { "nikic/php-parser": "^5.0", - "symplify/phpstan-extensions": "^11.4", + "symplify/phpstan-extensions": "^12.0", "symplify/rule-doc-generator": "^12.1", "phpunit/phpunit": "^10.5", - "rector/rector": "^1.1", + "rector/rector": "^2.0", "symplify/easy-coding-standard": "^12.1", "phpstan/extension-installer": "^1.3", "tomasvotruba/class-leak": "^0.2", From f2a1e2623f8407898ac1a3048a08dc5689f93dd9 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 12 Dec 2024 17:35:08 +0700 Subject: [PATCH 4/6] fix donwgrade script --- .github/workflows/downgraded_release.yaml | 4 ++-- ...ector-downgrade-php-72.php => rector-downgrade-php-74.php} | 2 +- .../.github/workflows/standalone_install.yaml | 2 +- build/target-repository/composer.json | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename build/{rector-downgrade-php-72.php => rector-downgrade-php-74.php} (77%) diff --git a/.github/workflows/downgraded_release.yaml b/.github/workflows/downgraded_release.yaml index 07c23b5f..094f62c5 100644 --- a/.github/workflows/downgraded_release.yaml +++ b/.github/workflows/downgraded_release.yaml @@ -32,7 +32,7 @@ jobs: - run: mkdir rector-local - run: composer require rector/rector:^1.1 --working-dir rector-local --ansi - # downgrade to PHP 7.2 + # downgrade to PHP 7.4 - run: rector-local/vendor/bin/rector process src --config build/rector-downgrade-php-72.php --ansi # clear the dev files @@ -56,7 +56,7 @@ jobs: run: | # separate a "git add" to add untracked (new) files too git add --all - git commit -m "release PHP 7.2 downgraded" + git commit -m "release PHP 7.4 downgraded" # force push tag, so there is only 1 version git tag "${GITHUB_REF#refs/tags/}" --force diff --git a/build/rector-downgrade-php-72.php b/build/rector-downgrade-php-74.php similarity index 77% rename from build/rector-downgrade-php-72.php rename to build/rector-downgrade-php-74.php index 667b7f0c..48e8c8b1 100644 --- a/build/rector-downgrade-php-72.php +++ b/build/rector-downgrade-php-74.php @@ -6,7 +6,7 @@ use Rector\Set\ValueObject\DowngradeLevelSetList; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->sets([DowngradeLevelSetList::DOWN_TO_PHP_72]); + $rectorConfig->sets([DowngradeLevelSetList::DOWN_TO_PHP_74]); $rectorConfig->skip(['*/tests/*']); }; diff --git a/build/target-repository/.github/workflows/standalone_install.yaml b/build/target-repository/.github/workflows/standalone_install.yaml index a54a1c88..7a27d0aa 100644 --- a/build/target-repository/.github/workflows/standalone_install.yaml +++ b/build/target-repository/.github/workflows/standalone_install.yaml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - php_version: ['7.2', '7.3', '7.4', '8.0', '8.1'] + php_version: ['7.4', '8.0', '8.1'] steps: # prepare empty composer.json that allows the phpstan extension plugin diff --git a/build/target-repository/composer.json b/build/target-repository/composer.json index 0c1df372..af6abc9f 100644 --- a/build/target-repository/composer.json +++ b/build/target-repository/composer.json @@ -4,8 +4,8 @@ "description": "Next level type declaration checks", "license": "MIT", "require": { - "php": "^7.2|^8.0", - "phpstan/phpstan": "^1.11", + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.0", "webmozart/assert": "^1.11" }, "autoload": { From f4c13e18cab4d159e7e2e973946aad6fd95641cc Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 12 Dec 2024 17:36:43 +0700 Subject: [PATCH 5/6] Run Rector and cs fix --- src/Matcher/ClassMethodCallReferenceResolver.php | 1 - src/Printer/CollectorMetadataPrinter.php | 7 +++---- src/Reflection/ReflectionParser.php | 8 +------- src/Rules/NarrowReturnObjectTypeRule.php | 1 - src/Rules/NoMixedMethodCallerRule.php | 2 +- src/Rules/NoMixedPropertyFetcherRule.php | 2 +- src/Rules/NoParamTypeRemovalRule.php | 4 ++-- 7 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/Matcher/ClassMethodCallReferenceResolver.php b/src/Matcher/ClassMethodCallReferenceResolver.php index 714333e8..b9574210 100644 --- a/src/Matcher/ClassMethodCallReferenceResolver.php +++ b/src/Matcher/ClassMethodCallReferenceResolver.php @@ -10,7 +10,6 @@ use PHPStan\Node\MethodCallableNode; use PHPStan\Type\ThisType; use PHPStan\Type\TypeCombinator; -use PHPStan\Type\TypeWithClassName; use Rector\TypePerfect\ValueObject\MethodCallReference; final class ClassMethodCallReferenceResolver diff --git a/src/Printer/CollectorMetadataPrinter.php b/src/Printer/CollectorMetadataPrinter.php index ed82c97c..afb8bc7d 100644 --- a/src/Printer/CollectorMetadataPrinter.php +++ b/src/Printer/CollectorMetadataPrinter.php @@ -14,7 +14,6 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\UnionType; use PhpParser\PrettyPrinter\Standard; -use PHPStan\Node\Printer\Printer; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ParametersAcceptorSelector; @@ -32,11 +31,11 @@ final readonly class CollectorMetadataPrinter { - private Standard $printer; + private Standard $standard; public function __construct( ) { - $this->printer = new Standard(); + $this->standard = new Standard(); } public function printArgTypesAsString(MethodCall $methodCall, ExtendedMethodReflection $extendedMethodReflection, Scope $scope): string @@ -97,7 +96,7 @@ public function printParamTypesToString(ClassMethod $classMethod, ?string $class $paramType = $this->resolveSortedTypes($paramType, $className); } - $printedParamType = $this->printer->prettyPrint([$paramType]); + $printedParamType = $this->standard->prettyPrint([$paramType]); $printedParamType = str_replace('\Closure', 'callable', $printedParamType); $printedParamType = ltrim($printedParamType, '\\'); $printedParamType = str_replace('|\\', '|', $printedParamType); diff --git a/src/Reflection/ReflectionParser.php b/src/Reflection/ReflectionParser.php index 7e72ac2d..ab3fc546 100644 --- a/src/Reflection/ReflectionParser.php +++ b/src/Reflection/ReflectionParser.php @@ -79,12 +79,6 @@ private function parseFilenameToClass(string $fileName): ClassLike|null private function findFirstClassLike(array $nodes): ?ClassLike { $nodeFinder = new NodeFinder(); - - $foundClassLike = $nodeFinder->findFirstInstanceOf($nodes, ClassLike::class); - if ($foundClassLike instanceof ClassLike) { - return $foundClassLike; - } - - return null; + return $nodeFinder->findFirstInstanceOf($nodes, ClassLike::class); } } diff --git a/src/Rules/NarrowReturnObjectTypeRule.php b/src/Rules/NarrowReturnObjectTypeRule.php index ad63368e..295cb51d 100644 --- a/src/Rules/NarrowReturnObjectTypeRule.php +++ b/src/Rules/NarrowReturnObjectTypeRule.php @@ -15,7 +15,6 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; -use PHPStan\Type\TypeWithClassName; use Rector\TypePerfect\Configuration; use Rector\TypePerfect\NodeFinder\ReturnNodeFinder; use Rector\TypePerfect\Reflection\MethodNodeAnalyser; diff --git a/src/Rules/NoMixedMethodCallerRule.php b/src/Rules/NoMixedMethodCallerRule.php index 44b7b2df..a8de0d1e 100644 --- a/src/Rules/NoMixedMethodCallerRule.php +++ b/src/Rules/NoMixedMethodCallerRule.php @@ -6,8 +6,8 @@ use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; -use PHPStan\Node\Printer\Printer; use PHPStan\Analyser\Scope; +use PHPStan\Node\Printer\Printer; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleError; use PHPStan\Rules\RuleErrorBuilder; diff --git a/src/Rules/NoMixedPropertyFetcherRule.php b/src/Rules/NoMixedPropertyFetcherRule.php index 5f49047b..e715353c 100644 --- a/src/Rules/NoMixedPropertyFetcherRule.php +++ b/src/Rules/NoMixedPropertyFetcherRule.php @@ -6,8 +6,8 @@ use PhpParser\Node; use PhpParser\Node\Expr\PropertyFetch; -use PHPStan\Node\Printer\Printer; use PHPStan\Analyser\Scope; +use PHPStan\Node\Printer\Printer; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleError; use PHPStan\Rules\RuleErrorBuilder; diff --git a/src/Rules/NoParamTypeRemovalRule.php b/src/Rules/NoParamTypeRemovalRule.php index a6046036..cb473990 100644 --- a/src/Rules/NoParamTypeRemovalRule.php +++ b/src/Rules/NoParamTypeRemovalRule.php @@ -82,8 +82,8 @@ public function processNode(Node $node, Scope $scope): array private function resolveParentParamType(PhpMethodReflection $phpMethodReflection, int $paramPosition): Type { - foreach ($phpMethodReflection->getVariants() as $parametersAcceptorWithPhpDoc) { - foreach ($parametersAcceptorWithPhpDoc->getParameters() as $parentParamPosition => $parameterReflectionWithPhpDoc) { + foreach ($phpMethodReflection->getVariants() as $variant) { + foreach ($variant->getParameters() as $parentParamPosition => $parameterReflectionWithPhpDoc) { if ($paramPosition !== $parentParamPosition) { continue; } From 6fb8246807cf2bf17cdbbad934cb47cdb6df1fc5 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 12 Dec 2024 17:38:24 +0700 Subject: [PATCH 6/6] Use php 7.4 --- .github/workflows/downgraded_release.yaml | 2 +- full-tool-build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/downgraded_release.yaml b/.github/workflows/downgraded_release.yaml index 094f62c5..84118496 100644 --- a/.github/workflows/downgraded_release.yaml +++ b/.github/workflows/downgraded_release.yaml @@ -33,7 +33,7 @@ jobs: - run: composer require rector/rector:^1.1 --working-dir rector-local --ansi # downgrade to PHP 7.4 - - run: rector-local/vendor/bin/rector process src --config build/rector-downgrade-php-72.php --ansi + - run: rector-local/vendor/bin/rector process src --config build/rector-downgrade-php-74.php --ansi # clear the dev files - run: rm -rf tests rector-local ecs.php phpstan.neon phpunit.xml .editorconfig diff --git a/full-tool-build.sh b/full-tool-build.sh index 47c552dd..93136248 100644 --- a/full-tool-build.sh +++ b/full-tool-build.sh @@ -12,4 +12,4 @@ rm -rf tests # downgrade with rector mkdir rector-local composer require rector/rector --working-dir rector-local -rector-local/vendor/bin/rector process src --config build/rector-downgrade-php-72.php --ansi +rector-local/vendor/bin/rector process src --config build/rector-downgrade-php-74.php --ansi