From a82a18edd366575db60151880ca44f1a8c2a0120 Mon Sep 17 00:00:00 2001 From: Simon Podlipsky Date: Wed, 12 Jan 2022 16:43:53 +0100 Subject: [PATCH] Prevent UnionTypes rule from removing `@param static` in favor fo `self`-typed $argument (#1667) --- .../TypeComparator/TypeComparator.php | 15 +++++++++ .../Fixture/param_self_return_static.php.inc | 31 +++++++++++++++++++ .../Fixture/skip_static_param.php.inc | 13 ++++++++ 3 files changed, 59 insertions(+) create mode 100644 rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/Fixture/param_self_return_static.php.inc create mode 100644 rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/Fixture/skip_static_param.php.inc diff --git a/packages/NodeTypeResolver/TypeComparator/TypeComparator.php b/packages/NodeTypeResolver/TypeComparator/TypeComparator.php index 37c8779dd0e..11e3acbab56 100644 --- a/packages/NodeTypeResolver/TypeComparator/TypeComparator.php +++ b/packages/NodeTypeResolver/TypeComparator/TypeComparator.php @@ -6,6 +6,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\ClassReflection; use PHPStan\Type\ArrayType; @@ -15,15 +16,18 @@ use PHPStan\Type\IntegerType; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; +use PHPStan\Type\StaticType; use PHPStan\Type\ThisType; use PHPStan\Type\Type; use PHPStan\Type\TypeTraverser; use PHPStan\Type\UnionType; +use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory; use Rector\NodeTypeResolver\PHPStan\TypeHasher; use Rector\StaticTypeMapper\StaticTypeMapper; use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType; +use Rector\StaticTypeMapper\ValueObject\Type\SelfStaticType; use Rector\TypeDeclaration\TypeNormalizer; final class TypeComparator @@ -96,6 +100,10 @@ public function arePhpParserAndPhpStanPhpDocTypesEqual( return false; } + if ($this->isTypeSelfAndDocParamTypeStatic($phpStanDocType, $phpParserNodeType, $phpStanDocTypeNode)) { + return false; + } + // special case for non-final $this/self compare; in case of interface/abstract class, it can be another $this if ($phpStanDocType instanceof ThisType && $phpParserNodeType instanceof ThisType) { $scope = $node->getAttribute(AttributeKey::SCOPE); @@ -247,4 +255,11 @@ private function normalizeConstantBooleanType(Type $type): Type return $callable($type); }); } + + private function isTypeSelfAndDocParamTypeStatic(Type $phpStanDocType, Type $phpParserNodeType, TypeNode $phpStanDocTypeNode) : bool + { + return $phpStanDocType instanceof StaticType + && $phpParserNodeType instanceof ThisType + && $phpStanDocTypeNode->getAttribute(PhpDocAttributeKey::PARENT) instanceof ParamTagValueNode; + } } diff --git a/rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/Fixture/param_self_return_static.php.inc b/rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/Fixture/param_self_return_static.php.inc new file mode 100644 index 00000000000..8bea600b770 --- /dev/null +++ b/rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/Fixture/param_self_return_static.php.inc @@ -0,0 +1,31 @@ + +----- + diff --git a/rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/Fixture/skip_static_param.php.inc b/rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/Fixture/skip_static_param.php.inc new file mode 100644 index 00000000000..b4ac51d5a4b --- /dev/null +++ b/rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/Fixture/skip_static_param.php.inc @@ -0,0 +1,13 @@ +