diff --git a/rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php b/rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php index 4a375acc14f..dda03adfbef 100644 --- a/rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php +++ b/rules/Php80/Rector/Switch_/ChangeSwitchToMatchRector.php @@ -139,6 +139,10 @@ public function refactor(Node $node) : ?Node } return null; } + public function provideMinPhpVersion() : int + { + return PhpVersionFeature::MATCH_EXPRESSION; + } private function castMatchCond(Match_ $match) : void { $type = $this->nodeTypeResolver->getNativeType($match->cond); @@ -169,10 +173,6 @@ private function castMatchCond(Match_ $match) : void $match->cond = $newMatchCond; } } - public function provideMinPhpVersion() : int - { - return PhpVersionFeature::MATCH_EXPRESSION; - } /** * @param CondAndExpr[] $condAndExprs */ diff --git a/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php b/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php index a9e504374ed..1332e25f098 100644 --- a/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php +++ b/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php @@ -17,6 +17,7 @@ use PHPStan\Type\ArrayType; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\IntegerType; +use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; use PHPStan\Type\Type; @@ -192,7 +193,12 @@ private function changeReturnType($node, ArrayType $arrayType) : void if ($arrayType instanceof ConstantArrayType && \count($arrayType->getValueTypes()) !== 1) { return; } - $narrowArrayType = new ArrayType(new MixedType(), $arrayType->getItemType()); + $itemType = $arrayType->getItemType(); + if ($itemType instanceof IntersectionType) { + $narrowArrayType = $arrayType; + } else { + $narrowArrayType = new ArrayType(new MixedType(), $itemType); + } $this->phpDocTypeChanger->changeReturnType($node, $phpDocInfo, $narrowArrayType); } /** diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index be68b374608..f67ecff810d 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '16f939995e159c934f0dcd1179a26a56fe64b65b'; + public const PACKAGE_VERSION = '52e3fdfb48a507be997bd0f47256ad14854be844'; /** * @api * @var string */ - public const RELEASE_DATE = '2024-10-11 13:52:42'; + public const RELEASE_DATE = '2024-10-11 15:33:12'; /** * @var int */ diff --git a/src/PHPStanStaticTypeMapper/TypeMapper/IntersectionTypeMapper.php b/src/PHPStanStaticTypeMapper/TypeMapper/IntersectionTypeMapper.php index 70ba622423d..6e2b180ed24 100644 --- a/src/PHPStanStaticTypeMapper/TypeMapper/IntersectionTypeMapper.php +++ b/src/PHPStanStaticTypeMapper/TypeMapper/IntersectionTypeMapper.php @@ -6,15 +6,19 @@ use PhpParser\Node; use PhpParser\Node\Name\FullyQualified; use PHPStan\PhpDocParser\Ast\Node as AstNode; +use PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; +use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; use PHPStan\Type\IntersectionType; +use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; use PHPStan\Type\ObjectWithoutClassType; use PHPStan\Type\Type; use Rector\Php\PhpVersionProvider; use Rector\PhpDocParser\PhpDocParser\PhpDocNodeTraverser; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; +use Rector\StaticTypeMapper\Mapper\ScalarStringToTypeMapper; use Rector\ValueObject\PhpVersionFeature; /** * @implements TypeMapperInterface @@ -36,11 +40,17 @@ final class IntersectionTypeMapper implements TypeMapperInterface * @var \Rector\PHPStanStaticTypeMapper\TypeMapper\ObjectTypeMapper */ private $objectTypeMapper; - public function __construct(PhpVersionProvider $phpVersionProvider, \Rector\PHPStanStaticTypeMapper\TypeMapper\ObjectWithoutClassTypeMapper $objectWithoutClassTypeMapper, \Rector\PHPStanStaticTypeMapper\TypeMapper\ObjectTypeMapper $objectTypeMapper) + /** + * @readonly + * @var \Rector\StaticTypeMapper\Mapper\ScalarStringToTypeMapper + */ + private $scalarStringToTypeMapper; + public function __construct(PhpVersionProvider $phpVersionProvider, \Rector\PHPStanStaticTypeMapper\TypeMapper\ObjectWithoutClassTypeMapper $objectWithoutClassTypeMapper, \Rector\PHPStanStaticTypeMapper\TypeMapper\ObjectTypeMapper $objectTypeMapper, ScalarStringToTypeMapper $scalarStringToTypeMapper) { $this->phpVersionProvider = $phpVersionProvider; $this->objectWithoutClassTypeMapper = $objectWithoutClassTypeMapper; $this->objectTypeMapper = $objectTypeMapper; + $this->scalarStringToTypeMapper = $scalarStringToTypeMapper; } public function getNodeClass() : string { @@ -53,12 +63,28 @@ public function mapToPHPStanPhpDocTypeNode(Type $type) : TypeNode { $typeNode = $type->toPhpDocNode(); $phpDocNodeTraverser = new PhpDocNodeTraverser(); - $phpDocNodeTraverser->traverseWithCallable($typeNode, '', static function (AstNode $astNode) : ?IdentifierTypeNode { - if ($astNode instanceof IdentifierTypeNode) { - $astNode->name = '\\' . \ltrim($astNode->name, '\\'); - return $astNode; + $phpDocNodeTraverser->traverseWithCallable($typeNode, '', function (AstNode $astNode) { + if ($astNode instanceof UnionTypeNode) { + return PhpDocNodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; } - return null; + if ($astNode instanceof ArrayShapeItemNode) { + return PhpDocNodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; + } + if (!$astNode instanceof IdentifierTypeNode) { + return PhpDocNodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; + } + $type = $this->scalarStringToTypeMapper->mapScalarStringToType($astNode->name); + if ($type->isScalar()->yes()) { + return PhpDocNodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; + } + if ($type->isArray()->yes()) { + return PhpDocNodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; + } + if ($type instanceof MixedType && $type->isExplicitMixed()) { + return PhpDocNodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; + } + $astNode->name = '\\' . \ltrim($astNode->name, '\\'); + return $astNode; }); return $typeNode; } diff --git a/src/StaticTypeMapper/Mapper/ScalarStringToTypeMapper.php b/src/StaticTypeMapper/Mapper/ScalarStringToTypeMapper.php index be6aec110aa..385861794e5 100644 --- a/src/StaticTypeMapper/Mapper/ScalarStringToTypeMapper.php +++ b/src/StaticTypeMapper/Mapper/ScalarStringToTypeMapper.php @@ -52,6 +52,9 @@ public function mapScalarStringToType(string $scalarName) : Type if ($loweredScalarName === 'array') { return new ArrayType(new MixedType(), new MixedType()); } + if ($loweredScalarName === 'non-empty-array') { + return new ArrayType(new MixedType(), new MixedType()); + } if ($loweredScalarName === 'iterable') { return new IterableType(new MixedType(), new MixedType()); }