diff --git a/packages/CodeQuality/tests/Rector/If_/ExplicitBoolCompareRector/Fixture/spl_file_info_edge_case.php.inc b/packages/CodeQuality/tests/Rector/If_/ExplicitBoolCompareRector/Fixture/spl_file_info_edge_case.php.inc index 31aa006ddf3d..89f2826c9df8 100644 --- a/packages/CodeQuality/tests/Rector/If_/ExplicitBoolCompareRector/Fixture/spl_file_info_edge_case.php.inc +++ b/packages/CodeQuality/tests/Rector/If_/ExplicitBoolCompareRector/Fixture/spl_file_info_edge_case.php.inc @@ -19,3 +19,29 @@ final class SplFileInfoEdgeCase return 1; } } + +?> +----- +getRealPath() === '') { + return 0; + } + + return 1; + } +} + +?> diff --git a/packages/Doctrine/src/Rector/ClassMethod/ChangeGetIdTypeToUuidRector.php b/packages/Doctrine/src/Rector/ClassMethod/ChangeGetIdTypeToUuidRector.php index 415925c8048b..3a2fc00b37be 100644 --- a/packages/Doctrine/src/Rector/ClassMethod/ChangeGetIdTypeToUuidRector.php +++ b/packages/Doctrine/src/Rector/ClassMethod/ChangeGetIdTypeToUuidRector.php @@ -44,16 +44,21 @@ public function refactor(Node $node): ?Node return null; } - // is already set? - if ($node->returnType !== null) { - $currentType = $this->getName($node->returnType); - if ($currentType === UuidInterface::class) { - return null; - } + if ($this->hasUuidReturnType($node)) { + return null; } $node->returnType = new FullyQualified(UuidInterface::class); return $node; } + + private function hasUuidReturnType(Node $node): bool + { + if ($node->returnType === null) { + return false; + } + + return $this->isName($node->returnType, UuidInterface::class); + } } diff --git a/packages/NodeTypeResolver/src/NodeTypeResolver.php b/packages/NodeTypeResolver/src/NodeTypeResolver.php index 1e0c4e546567..c40396a736a9 100644 --- a/packages/NodeTypeResolver/src/NodeTypeResolver.php +++ b/packages/NodeTypeResolver/src/NodeTypeResolver.php @@ -29,7 +29,6 @@ use PHPStan\Type\Accessory\HasOffsetType; use PHPStan\Type\Accessory\NonEmptyArrayType; use PHPStan\Type\ArrayType; -use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\FloatType; use PHPStan\Type\IntegerType; use PHPStan\Type\IntersectionType; @@ -54,7 +53,6 @@ use Rector\PhpParser\Node\Resolver\NameResolver; use Rector\TypeDeclaration\PHPStan\Type\ObjectTypeSpecifier; use ReflectionProperty; -use Symfony\Component\Finder\SplFileInfo; final class NodeTypeResolver { @@ -200,7 +198,7 @@ public function isStringOrUnionStringOnlyType(Node $node): bool if ($nodeType instanceof UnionType) { foreach ($nodeType->getTypes() as $singleType) { - if (! $singleType instanceof StringType) { + if ($singleType->isSuperTypeOf(new StringType())->no()) { return false; } } @@ -227,19 +225,10 @@ public function isNullableType(Node $node): bool public function isCountableType(Node $node): bool { $nodeType = $this->getStaticType($node); - $nodeType = $this->pregMatchTypeCorrector->correct($node, $nodeType); - if ($nodeType instanceof ObjectType) { - if (is_a($nodeType->getClassName(), Countable::class, true)) { - return true; - } - // @see https://github.com/rectorphp/rector/issues/2028 - if (is_a($nodeType->getClassName(), 'SimpleXMLElement', true)) { - return true; - } - - return is_a($nodeType->getClassName(), 'ResourceBundle', true); + if ($this->isCountableObjectType($nodeType)) { + return true; } return $this->isArrayType($node); @@ -280,17 +269,12 @@ public function getStaticType(Node $node): Type throw new ShouldNotHappenException('Arg does not have a type, use $arg->value instead'); } - if ($node instanceof Param) { + if ($node instanceof Param || $node instanceof Scalar) { return $this->resolve($node); } /** @var Scope|null $nodeScope */ $nodeScope = $node->getAttribute(AttributeKey::SCOPE); - - if ($node instanceof Scalar) { - return $this->resolve($node); - } - if (! $node instanceof Expr || $nodeScope === null) { return new MixedType(); } @@ -299,14 +283,6 @@ public function getStaticType(Node $node): Type return new ObjectWithoutClassType(); } - // false type correction of inherited method - if ($node instanceof MethodCall && $this->isObjectType($node->var, SplFileInfo::class)) { - $methodName = $this->nameResolver->getName($node->name); - if ($methodName === 'getRealPath') { - return new UnionType([new StringType(), new ConstantBooleanType(false)]); - } - } - $staticType = $nodeScope->getType($node); if (! $staticType instanceof ObjectType) { return $staticType; @@ -334,10 +310,6 @@ public function resolveNodeToPHPStanType(Expr $expr): Type return new ArrayType(new MixedType(), new MixedType()); } - if ($this->isStringOrUnionStringOnlyType($expr)) { - return new StringType(); - } - return $this->getStaticType($expr); } @@ -648,4 +620,22 @@ private function getVendorPropertyFetchType(PropertyFetch $propertyFetch): ?Type return $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType($typeNode, new Nop()); } + + private function isCountableObjectType(Type $type): bool + { + if (! $type instanceof ObjectType) { + return false; + } + + if (is_a($type->getClassName(), Countable::class, true)) { + return true; + } + + // @see https://github.com/rectorphp/rector/issues/2028 + if (is_a($type->getClassName(), 'SimpleXMLElement', true)) { + return true; + } + + return is_a($type->getClassName(), 'ResourceBundle', true); + } } diff --git a/packages/NodeTypeResolver/src/PerNodeTypeResolver/ScalarTypeResolver.php b/packages/NodeTypeResolver/src/PerNodeTypeResolver/ScalarTypeResolver.php index 72b6266a9dd2..16fb5d05771d 100644 --- a/packages/NodeTypeResolver/src/PerNodeTypeResolver/ScalarTypeResolver.php +++ b/packages/NodeTypeResolver/src/PerNodeTypeResolver/ScalarTypeResolver.php @@ -4,8 +4,8 @@ namespace Rector\NodeTypeResolver\PerNodeTypeResolver; -use PhpParser\Node\Scalar; use PhpParser\Node; +use PhpParser\Node\Scalar; use PhpParser\Node\Scalar\DNumber; use PhpParser\Node\Scalar\LNumber; use PhpParser\Node\Scalar\MagicConst;