From d36c13269e5e8e1ec044429e3e274bbac0e71acb Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 10 Feb 2022 18:40:53 +0100 Subject: [PATCH 1/5] added failling test-case --- ...sibleCheckTypeGenericOverwriteRuleTest.php | 45 ++++++++++++++ .../TestTypeOverwriteSpecifyingExtensions.php | 58 +++++++++++++++++++ .../Comparison/data/generic-type-override.php | 39 +++++++++++++ ...possible-check-type-generic-overwrite.neon | 5 ++ 4 files changed, 147 insertions(+) create mode 100644 tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php create mode 100644 tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php create mode 100644 tests/PHPStan/Rules/Comparison/data/generic-type-override.php create mode 100644 tests/PHPStan/Rules/Comparison/impossible-check-type-generic-overwrite.neon diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php new file mode 100644 index 0000000000..911bfba5ef --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php @@ -0,0 +1,45 @@ + + */ +class ImpossibleCheckTypeGenericOverwriteRuleTest extends RuleTestCase +{ + + private bool $treatPhpDocTypesAsCertain; + + public function getRule(): Rule + { + return new ImpossibleCheckTypeMethodCallRule( + new ImpossibleCheckTypeHelper( + $this->createReflectionProvider(), + $this->getTypeSpecifier(), + [], + $this->treatPhpDocTypesAsCertain, + ), + true, + $this->treatPhpDocTypesAsCertain, + ); + } + + public function testNoReportedErrorOnOverwrite(): void + { + $this->treatPhpDocTypesAsCertain = false; + + $this->analyse([__DIR__ . '/data/generic-type-override.php'], [ + ]); + } + + public static function getAdditionalConfigFiles(): array + { + return [ + __DIR__ . '/impossible-check-type-generic-overwrite.neon', + ]; + } + +} diff --git a/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php b/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php new file mode 100644 index 0000000000..7ac92b30b3 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php @@ -0,0 +1,58 @@ +typeSpecifier = $typeSpecifier; + } + + public function getClass(): string + { + return \GenericTypeOverride\Foo::class; + } + + public function isMethodSupported( + MethodReflection $methodReflection, + MethodCall $node, + TypeSpecifierContext $context + ): bool + { + return $methodReflection->getName() === 'setFetchMode'; + } + + public function specifyTypes( + MethodReflection $methodReflection, + MethodCall $node, + Scope $scope, + TypeSpecifierContext $context + ): SpecifiedTypes + { + $newType = new GenericObjectType(\GenericTypeOverride\Foo::class, [\GenericTypeOverride\Bar::class]); + + return $this->typeSpecifier->create( + $node->var, + $newType, + TypeSpecifierContext::createTruthy(), + true + ); + } + +} diff --git a/tests/PHPStan/Rules/Comparison/data/generic-type-override.php b/tests/PHPStan/Rules/Comparison/data/generic-type-override.php new file mode 100644 index 0000000000..11cc1ac3d8 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/generic-type-override.php @@ -0,0 +1,39 @@ +createGenericFoo(); + assertType('Foo', $foo); + + // $foo generic will be overridden via MethodTypeSpecifyingExtension + $foo->setFetchMode(); + assertType('Foo', $foo); + } + + /** + * @return Foo + */ + public function createGenericFoo() { + + } +} + + +/** + * @template T + */ +class Foo +{ + public function setFetchMode() { + + } +} + + +class Bar +{ +} diff --git a/tests/PHPStan/Rules/Comparison/impossible-check-type-generic-overwrite.neon b/tests/PHPStan/Rules/Comparison/impossible-check-type-generic-overwrite.neon new file mode 100644 index 0000000000..beb99fbc14 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/impossible-check-type-generic-overwrite.neon @@ -0,0 +1,5 @@ +services: + - + class: PHPStan\Rules\Comparison\GenericTypeOverride + tags: + - phpstan.typeSpecifier.methodTypeSpecifyingExtension From 72c00c0e5523254c2a82882a0df241fdeb80c725 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 10 Feb 2022 18:40:57 +0100 Subject: [PATCH 2/5] fix --- src/Rules/Comparison/ImpossibleCheckTypeHelper.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php index 15e69dc664..08d4d8ec77 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php @@ -158,6 +158,12 @@ public function findSpecifiedType( } $specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($scope, $node, TypeSpecifierContext::createTruthy()); + + // don't validate types on overwrite + if ($specifiedTypes->shouldOverwrite()) { + return null; + } + $sureTypes = $specifiedTypes->getSureTypes(); $sureNotTypes = $specifiedTypes->getSureNotTypes(); From e9c513dd6d06672414b4c869b020717a7942db9d Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 10 Feb 2022 18:47:08 +0100 Subject: [PATCH 3/5] fix --- .../Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php | 3 +-- tests/PHPStan/Rules/Comparison/data/generic-type-override.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php index 911bfba5ef..0ca0696ac8 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php @@ -31,8 +31,7 @@ public function testNoReportedErrorOnOverwrite(): void { $this->treatPhpDocTypesAsCertain = false; - $this->analyse([__DIR__ . '/data/generic-type-override.php'], [ - ]); + $this->analyse([__DIR__ . '/data/generic-type-override.php'], []); } public static function getAdditionalConfigFiles(): array diff --git a/tests/PHPStan/Rules/Comparison/data/generic-type-override.php b/tests/PHPStan/Rules/Comparison/data/generic-type-override.php index 11cc1ac3d8..e5dad0ece2 100644 --- a/tests/PHPStan/Rules/Comparison/data/generic-type-override.php +++ b/tests/PHPStan/Rules/Comparison/data/generic-type-override.php @@ -11,7 +11,7 @@ public function doFoo() { // $foo generic will be overridden via MethodTypeSpecifyingExtension $foo->setFetchMode(); - assertType('Foo', $foo); + assertType('Foo', $foo); } /** From c40a66d93a19edf4e05b5f1102ecc8fbc36483f6 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 11 Feb 2022 09:49:05 +0100 Subject: [PATCH 4/5] fixed test --- .../Comparison/data/TestTypeOverwriteSpecifyingExtensions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php b/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php index 7ac92b30b3..4e2acbd198 100644 --- a/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php +++ b/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php @@ -10,7 +10,7 @@ use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\MethodTypeSpecifyingExtension; -use PHPStan\Type\StringType; +use PHPStan\Type\ObjectType; use PHPStan\Type\Generic\GenericObjectType; class GenericTypeOverride implements MethodTypeSpecifyingExtension, TypeSpecifierAwareExtension @@ -45,7 +45,7 @@ public function specifyTypes( TypeSpecifierContext $context ): SpecifiedTypes { - $newType = new GenericObjectType(\GenericTypeOverride\Foo::class, [\GenericTypeOverride\Bar::class]); + $newType = new GenericObjectType(\GenericTypeOverride\Foo::class, [new ObjectType(\GenericTypeOverride\Bar::class)]); return $this->typeSpecifier->create( $node->var, From 138799b59dfe7fd25586cf0c14da213ea1c65520 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 11 Feb 2022 11:01:04 +0100 Subject: [PATCH 5/5] removed leftover treatPhpDocTypesAsCertain property in test --- .../ImpossibleCheckTypeGenericOverwriteRuleTest.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php index 0ca0696ac8..7d12e3f769 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php @@ -11,8 +11,6 @@ class ImpossibleCheckTypeGenericOverwriteRuleTest extends RuleTestCase { - private bool $treatPhpDocTypesAsCertain; - public function getRule(): Rule { return new ImpossibleCheckTypeMethodCallRule( @@ -20,17 +18,15 @@ public function getRule(): Rule $this->createReflectionProvider(), $this->getTypeSpecifier(), [], - $this->treatPhpDocTypesAsCertain, + true, ), true, - $this->treatPhpDocTypesAsCertain, + true, ); } public function testNoReportedErrorOnOverwrite(): void { - $this->treatPhpDocTypesAsCertain = false; - $this->analyse([__DIR__ . '/data/generic-type-override.php'], []); }