Skip to content

Commit

Permalink
Prevent UnionTypes rule from removing literal value scalar types (#1666)
Browse files Browse the repository at this point in the history
  • Loading branch information
simPod committed Jan 14, 2022
1 parent fda8d1a commit 0947481
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 10 deletions.
41 changes: 31 additions & 10 deletions packages/NodeTypeResolver/TypeComparator/TypeComparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\Generic\GenericClassStringType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
Expand Down Expand Up @@ -103,18 +104,11 @@ public function arePhpParserAndPhpStanPhpDocTypesEqual(
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);
if ($scope instanceof Scope) {
$classReflection = $scope->getClassReflection();
if ($classReflection instanceof ClassReflection) {
return $classReflection->isFinal();
}
}
if ($this->areTypesSameWithLiteralTypeInPhpDoc($areDifferentScalarTypes, $phpStanDocType, $phpParserNodeType)) {
return false;
}

return true;
return $this->isThisTypeInFinalClass($phpStanDocType, $phpParserNodeType, $node);
}

public function isSubtype(Type $checkedType, Type $mainType): bool
Expand Down Expand Up @@ -264,4 +258,31 @@ private function isTypeSelfAndDocParamTypeStatic(
&& $phpParserNodeType instanceof ThisType
&& $phpStanDocTypeNode->getAttribute(PhpDocAttributeKey::PARENT) instanceof ParamTagValueNode;
}

private function areTypesSameWithLiteralTypeInPhpDoc(
bool $areDifferentScalarTypes,
Type $phpStanDocType,
Type $phpParserNodeType
): bool
{
return $areDifferentScalarTypes
&& $phpStanDocType instanceof ConstantScalarType
&& $phpParserNodeType->isSuperTypeOf($phpStanDocType)->yes();
}

private function isThisTypeInFinalClass(Type $phpStanDocType, Type $phpParserNodeType, Node $node) : bool
{
// 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);
if ($scope instanceof Scope) {
$classReflection = $scope->getClassReflection();
if ($classReflection instanceof ClassReflection) {
return $classReflection->isFinal();
}
}
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Rector\Tests\Php80\Rector\FunctionLike\UnionTypesRector\Fixture;

final class SkipLiteralValueStringUnionType
{
/**
* @param 'a' $message
*/
private function getMessage(string $message): string
{
return $message;
}
}

0 comments on commit 0947481

Please sign in to comment.