From a4e90efb7c4e34b21fb10d12af97976e9f9a6c85 Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Wed, 15 Jan 2020 03:11:11 +0100 Subject: [PATCH 1/3] use @required --- README.md | 2 +- .../PHPStanStaticTypeMapperAwareInterface.php | 12 ----- .../src/Contract/TypeMapperInterface.php | 2 + .../src/PHPStanStaticTypeMapper.php | 9 +--- .../src/TypeMapper/IterableTypeMapper.php | 45 ++++++++++++++++++- .../src/TypeMapper/UnionTypeMapper.php | 5 +-- 6 files changed, 49 insertions(+), 26 deletions(-) delete mode 100644 packages/PHPStanStaticTypeMapper/src/Contract/PHPStanStaticTypeMapperAwareInterface.php diff --git a/README.md b/README.md index 474828ac9827..87d8f53c1cdd 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ class SomeClass ### Filter Rectors -If you have a configuration file for Rector including many sets and Rectors, you might want at times to run only a single Rector from them. The `--only` argument allows that, for example : +If you have a configuration file for Rector including many sets and Rectors, you might want at times to run only a single Rector from them. The `--only` argument allows that, for example : ```bash vendor/bin/rector process --set solid --only "Rector\SOLID\Rector\Class_\FinalizeClassesWithoutChildrenRector" src/ diff --git a/packages/PHPStanStaticTypeMapper/src/Contract/PHPStanStaticTypeMapperAwareInterface.php b/packages/PHPStanStaticTypeMapper/src/Contract/PHPStanStaticTypeMapperAwareInterface.php deleted file mode 100644 index fcfe36d21be8..000000000000 --- a/packages/PHPStanStaticTypeMapper/src/Contract/PHPStanStaticTypeMapperAwareInterface.php +++ /dev/null @@ -1,12 +0,0 @@ -mapToPHPStanPhpDocTypeNode($type->getItemType()); - if ($itemTypeNode instanceof UnionTypeNode) { return $this->convertUnionArrayTypeNodesToArrayTypeOfUnionTypeNodes($itemTypeNode); } @@ -85,11 +83,6 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode continue; } - // prevents circular dependency - if ($typeMapper instanceof PHPStanStaticTypeMapperAwareInterface) { - $typeMapper->setPHPStanStaticTypeMapper($this); - } - return $typeMapper->mapToPHPStanPhpDocTypeNode($type); } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/IterableTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/IterableTypeMapper.php index cd4ca079bef3..a524b87d91c5 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/IterableTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/IterableTypeMapper.php @@ -6,14 +6,30 @@ use PhpParser\Node; use PhpParser\Node\Identifier; +use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; +use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; use PHPStan\Type\IterableType; use PHPStan\Type\Type; -use Rector\Exception\NotImplementedException; +use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareUnionTypeNode; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; +use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper; final class IterableTypeMapper implements TypeMapperInterface { + /** + * @var PHPStanStaticTypeMapper + */ + private $phpStanStaticTypeMapper; + + /** + * @required + */ + public function autowire(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void + { + $this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper; + } + public function getNodeClass(): string { return IterableType::class; @@ -24,7 +40,12 @@ public function getNodeClass(): string */ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode { - throw new NotImplementedException(); + $itemTypeNode = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($type->getItemType()); + if ($itemTypeNode instanceof UnionTypeNode) { + return $this->convertUnionArrayTypeNodesToArrayTypeOfUnionTypeNodes($itemTypeNode); + } + + return new ArrayTypeNode($itemTypeNode); } /** @@ -34,4 +55,24 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { return new Identifier('iterable'); } + + private function convertUnionArrayTypeNodesToArrayTypeOfUnionTypeNodes( + UnionTypeNode $unionTypeNode + ): AttributeAwareUnionTypeNode { + $unionedArrayType = []; + foreach ($unionTypeNode->types as $unionedType) { + if ($unionedType instanceof UnionTypeNode) { + foreach ($unionedType->types as $key => $subUnionedType) { + $unionedType->types[$key] = new ArrayTypeNode($subUnionedType); + } + + $unionedArrayType[] = $unionedType; + continue; + } + + $unionedArrayType[] = new ArrayTypeNode($unionedType); + } + + return new AttributeAwareUnionTypeNode($unionedArrayType); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/UnionTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/UnionTypeMapper.php index 57cb57441730..bdebec8c0a40 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/UnionTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/UnionTypeMapper.php @@ -18,13 +18,12 @@ use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareUnionTypeNode; use Rector\Exception\ShouldNotHappenException; use Rector\Php\PhpVersionProvider; -use Rector\PHPStanStaticTypeMapper\Contract\PHPStanStaticTypeMapperAwareInterface; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper; use Rector\PHPStanStaticTypeMapper\TypeAnalyzer\UnionTypeAnalyzer; use Rector\ValueObject\PhpVersionFeature; -final class UnionTypeMapper implements TypeMapperInterface, PHPStanStaticTypeMapperAwareInterface +final class UnionTypeMapper implements TypeMapperInterface { /** * @var PHPStanStaticTypeMapper @@ -71,7 +70,7 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode /** * @required */ - public function setPHPStanStaticTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void + public function autowire(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void { $this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper; } From 71cdc8fe40d74f55ea53cbb603e282913523a78a Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Wed, 15 Jan 2020 03:16:22 +0100 Subject: [PATCH 2/3] add mapToDocString() --- .../src/Contract/TypeMapperInterface.php | 2 +- .../src/PHPStanStaticTypeMapper.php | 114 ++---------------- .../src/TypeMapper/BooleanTypeMapper.php | 8 ++ .../src/TypeMapper/CallableTypeMapper.php | 6 + .../src/TypeMapper/ClassStringTypeMapper.php | 6 + .../src/TypeMapper/ClosureTypeMapper.php | 6 + .../src/TypeMapper/FloatTypeMapper.php | 6 + .../src/TypeMapper/IntegerTypeMapper.php | 6 + .../src/TypeMapper/IntersectionTypeMapper.php | 77 ++++++++++++ .../src/TypeMapper/IterableTypeMapper.php | 28 ++++- .../src/TypeMapper/MixedTypeMapper.php | 6 + .../src/TypeMapper/NeverTypeMapper.php | 5 + .../src/TypeMapper/NullTypeMapper.php | 6 + .../src/TypeMapper/ObjectTypeMapper.php | 34 ++++++ .../ObjectWithoutClassTypeMapper.php | 6 + .../src/TypeMapper/ParentStaticTypeMapper.php | 6 + .../src/TypeMapper/ResourceTypeMapper.php | 6 + .../src/TypeMapper/StringTypeMapper.php | 6 + .../src/TypeMapper/ThisTypeMapper.php | 9 ++ .../src/TypeMapper/UnionTypeMapper.php | 34 ++++-- .../src/TypeMapper/VoidTypeMapper.php | 11 ++ 21 files changed, 271 insertions(+), 117 deletions(-) create mode 100644 packages/PHPStanStaticTypeMapper/src/TypeMapper/IntersectionTypeMapper.php diff --git a/packages/PHPStanStaticTypeMapper/src/Contract/TypeMapperInterface.php b/packages/PHPStanStaticTypeMapper/src/Contract/TypeMapperInterface.php index 8b595b19f7ef..d77e02f4c39a 100644 --- a/packages/PHPStanStaticTypeMapper/src/Contract/TypeMapperInterface.php +++ b/packages/PHPStanStaticTypeMapper/src/Contract/TypeMapperInterface.php @@ -23,5 +23,5 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode; */ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node; - public function mapToDocString(Type $phpStanType, ?Type $parentType = null): string; + public function mapToDocString(Type $type, ?Type $parentType = null): string; } diff --git a/packages/PHPStanStaticTypeMapper/src/PHPStanStaticTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/PHPStanStaticTypeMapper.php index 04f0942c8b84..53b62e72aefe 100644 --- a/packages/PHPStanStaticTypeMapper/src/PHPStanStaticTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/PHPStanStaticTypeMapper.php @@ -4,7 +4,6 @@ namespace Rector\PHPStanStaticTypeMapper; -use Closure; use PhpParser\Node; use PhpParser\Node\Identifier; use PhpParser\Node\Name; @@ -15,44 +14,17 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; use PHPStan\Type\ArrayType; -use PHPStan\Type\BooleanType; -use PHPStan\Type\CallableType; -use PHPStan\Type\ClosureType; -use PHPStan\Type\FloatType; -use PHPStan\Type\IntegerType; -use PHPStan\Type\IntersectionType; -use PHPStan\Type\IterableType; -use PHPStan\Type\MixedType; -use PHPStan\Type\NeverType; -use PHPStan\Type\NullType; -use PHPStan\Type\ObjectType; -use PHPStan\Type\ObjectWithoutClassType; -use PHPStan\Type\ResourceType; use PHPStan\Type\StaticType; -use PHPStan\Type\StringType; use PHPStan\Type\Type; use PHPStan\Type\TypeWithClassName; use PHPStan\Type\UnionType; -use PHPStan\Type\VerbosityLevel; -use PHPStan\Type\VoidType; use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareUnionTypeNode; use Rector\Exception\NotImplementedException; -use Rector\NodeTypeResolver\ClassExistenceStaticHelper; -use Rector\Php\PhpVersionProvider; -use Rector\PHPStan\Type\AliasedObjectType; -use Rector\PHPStan\Type\FullyQualifiedObjectType; use Rector\PHPStan\Type\SelfObjectType; -use Rector\PHPStan\Type\ShortenedObjectType; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; -use Rector\ValueObject\PhpVersionFeature; final class PHPStanStaticTypeMapper { - /** - * @var PhpVersionProvider - */ - private $phpVersionProvider; - /** * @var TypeMapperInterface[] */ @@ -61,14 +33,14 @@ final class PHPStanStaticTypeMapper /** * @param TypeMapperInterface[] $typeMappers */ - public function __construct(PhpVersionProvider $phpVersionProvider, array $typeMappers) + public function __construct(array $typeMappers) { - $this->phpVersionProvider = $phpVersionProvider; $this->typeMappers = $typeMappers; } public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode { + // @todo move to ArrayTypeMapper if ($type instanceof ArrayType) { $itemTypeNode = $this->mapToPHPStanPhpDocTypeNode($type->getItemType()); if ($itemTypeNode instanceof UnionTypeNode) { @@ -94,10 +66,6 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode */ public function mapToPhpParserNode(Type $phpStanType, ?string $kind = null): ?Node { - if ($phpStanType instanceof SelfObjectType) { - return new Identifier('self'); - } - foreach ($this->typeMappers as $typeMapper) { // it cannot be is_a for SelfObjectType, because type classes inherit from each other if (! is_a($phpStanType, $typeMapper->getNodeClass(), true)) { @@ -141,54 +109,13 @@ public function mapToPhpParserNode(Type $phpStanType, ?string $kind = null): ?No public function mapToDocString(Type $phpStanType, ?Type $parentType = null): string { - if ($phpStanType instanceof UnionType || $phpStanType instanceof IntersectionType) { - $stringTypes = []; - - foreach ($phpStanType->getTypes() as $unionedType) { - $stringTypes[] = $this->mapToDocString($unionedType); - } - - // remove empty values, e.g. void/iterable - $stringTypes = array_unique($stringTypes); - $stringTypes = array_filter($stringTypes); - - $joinCharacter = $phpStanType instanceof IntersectionType ? '&' : '|'; - - return implode($joinCharacter, $stringTypes); - } - - if ($phpStanType instanceof AliasedObjectType) { - // no preslash for alias - return $phpStanType->getClassName(); - } - - if ($phpStanType instanceof ShortenedObjectType) { - return '\\' . $phpStanType->getFullyQualifiedName(); - } - - if ($phpStanType instanceof FullyQualifiedObjectType) { - // always prefixed with \\ - return '\\' . $phpStanType->getClassName(); - } - - if ($phpStanType instanceof ObjectType) { - if (ClassExistenceStaticHelper::doesClassLikeExist($phpStanType->getClassName())) { - return '\\' . $phpStanType->getClassName(); + foreach ($this->typeMappers as $typeMapper) { + // it cannot be is_a for SelfObjectType, because type classes inherit from each other + if (! is_a($phpStanType, $typeMapper->getNodeClass(), true)) { + continue; } - return $phpStanType->getClassName(); - } - - if ($phpStanType instanceof ObjectWithoutClassType) { - return 'object'; - } - - if ($phpStanType instanceof ClosureType) { - return '\\' . Closure::class; - } - - if ($phpStanType instanceof StringType || $phpStanType instanceof NullType || $phpStanType instanceof IntegerType || $phpStanType instanceof MixedType || $phpStanType instanceof FloatType || $phpStanType instanceof CallableType || $phpStanType instanceof ResourceType) { - return $phpStanType->describe(VerbosityLevel::typeOnly()); + return $typeMapper->mapToDocString($phpStanType, $parentType); } if ($phpStanType instanceof ArrayType) { @@ -217,33 +144,6 @@ public function mapToDocString(Type $phpStanType, ?Type $parentType = null): str return implode('|', $docStringTypes); } - if ($phpStanType instanceof VoidType) { - if ($this->phpVersionProvider->isAtLeast(PhpVersionFeature::SCALAR_TYPES)) { - // the void type is better done in PHP code - return ''; - } - - // fallback for PHP 7.0 and older, where void type was only in docs - return 'void'; - } - - if ($phpStanType instanceof IterableType) { - if ($this->phpVersionProvider->isAtLeast(PhpVersionFeature::SCALAR_TYPES)) { - // the void type is better done in PHP code - return ''; - } - - return 'iterable'; - } - - if ($phpStanType instanceof BooleanType) { - return 'bool'; - } - - if ($phpStanType instanceof NeverType) { - return 'mixed'; - } - throw new NotImplementedException(__METHOD__ . ' for ' . get_class($phpStanType)); } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/BooleanTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/BooleanTypeMapper.php index ab8caa17b195..8ce5526ea49c 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/BooleanTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/BooleanTypeMapper.php @@ -50,4 +50,12 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new Identifier('bool'); } + + /** + * @param BooleanType $type + */ + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return 'bool'; + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/CallableTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/CallableTypeMapper.php index 7f64a40d1829..102e988dad62 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/CallableTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/CallableTypeMapper.php @@ -9,6 +9,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\CallableType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\Exception\NotImplementedException; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; @@ -38,4 +39,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new Identifier('callable'); } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ClassStringTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ClassStringTypeMapper.php index e321997b4135..f519f353d550 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ClassStringTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ClassStringTypeMapper.php @@ -9,6 +9,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\ClassStringType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; final class ClassStringTypeMapper implements TypeMapperInterface @@ -33,4 +34,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { return null; } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ClosureTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ClosureTypeMapper.php index ecc01e23b39b..30ffaf65780e 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ClosureTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ClosureTypeMapper.php @@ -4,6 +4,7 @@ namespace Rector\PHPStanStaticTypeMapper\TypeMapper; +use Closure; use PhpParser\Node; use PhpParser\Node\Identifier; use PHPStan\PhpDocParser\Ast\Type\TypeNode; @@ -38,4 +39,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new Identifier('callable'); } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return '\\' . Closure::class; + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/FloatTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/FloatTypeMapper.php index 6c0292ee0ba2..d01f6d079c1e 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/FloatTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/FloatTypeMapper.php @@ -10,6 +10,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\FloatType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\Php\PhpVersionProvider; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; use Rector\ValueObject\PhpVersionFeature; @@ -50,4 +51,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new Identifier('float'); } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/IntegerTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/IntegerTypeMapper.php index 988e5c362a5f..3d3107328ae6 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/IntegerTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/IntegerTypeMapper.php @@ -10,6 +10,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\IntegerType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\Php\PhpVersionProvider; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; use Rector\ValueObject\PhpVersionFeature; @@ -50,4 +51,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new Identifier('int'); } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/IntersectionTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/IntersectionTypeMapper.php new file mode 100644 index 000000000000..dd6e5ca38c3c --- /dev/null +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/IntersectionTypeMapper.php @@ -0,0 +1,77 @@ +phpStanStaticTypeMapper = $phpStanStaticTypeMapper; + } + + public function getNodeClass(): string + { + return IntersectionType::class; + } + + /** + * @param IntersectionType $type + */ + public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode + { + $intersectionTypesNodes = []; + + foreach ($type->getTypes() as $unionedType) { + $intersectionTypesNodes[] = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($unionedType); + } + + $intersectionTypesNodes = array_unique($intersectionTypesNodes); + + return new AttributeAwareIntersectionTypeNode($intersectionTypesNodes); + } + + /** + * @param IntersectionType $type + */ + public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node + { + throw new NotImplementedException(); + } + + /** + * @param IntersectionType $type + */ + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + $stringTypes = []; + + foreach ($type->getTypes() as $unionedType) { + $stringTypes[] = $this->phpStanStaticTypeMapper->mapToDocString($unionedType); + } + + // remove empty values, e.g. void/iterable + $stringTypes = array_unique($stringTypes); + $stringTypes = array_filter($stringTypes); + + return implode('&', $stringTypes); + } +} diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/IterableTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/IterableTypeMapper.php index a524b87d91c5..bb065976479d 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/IterableTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/IterableTypeMapper.php @@ -11,9 +11,12 @@ use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; use PHPStan\Type\IterableType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareUnionTypeNode; +use Rector\Php\PhpVersionProvider; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper; +use Rector\ValueObject\PhpVersionFeature; final class IterableTypeMapper implements TypeMapperInterface { @@ -22,10 +25,20 @@ final class IterableTypeMapper implements TypeMapperInterface */ private $phpStanStaticTypeMapper; + /** + * @var PhpVersionProvider + */ + private $phpVersionProvider; + + public function __construct(PhpVersionProvider $phpVersionProvider) + { + $this->phpVersionProvider = $phpVersionProvider; + } + /** * @required */ - public function autowire(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void + public function autowireIterableTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void { $this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper; } @@ -56,6 +69,19 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new Identifier('iterable'); } + /** + * @param IterableType $type + */ + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + if ($this->phpVersionProvider->isAtLeast(PhpVersionFeature::SCALAR_TYPES)) { + // iterable type is better done in PHP code, than in doc + return ''; + } + + return $type->describe(VerbosityLevel::typeOnly()); + } + private function convertUnionArrayTypeNodesToArrayTypeOfUnionTypeNodes( UnionTypeNode $unionTypeNode ): AttributeAwareUnionTypeNode { diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/MixedTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/MixedTypeMapper.php index d990fe0ff3ae..28163ef5233c 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/MixedTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/MixedTypeMapper.php @@ -9,6 +9,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\MixedType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; final class MixedTypeMapper implements TypeMapperInterface @@ -33,4 +34,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { return null; } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/NeverTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/NeverTypeMapper.php index 8ed8dd9b6037..60fdeae440f4 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/NeverTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/NeverTypeMapper.php @@ -33,4 +33,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { return null; } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return 'mixed'; + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/NullTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/NullTypeMapper.php index 2915d0c3233e..1182fe43f90a 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/NullTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/NullTypeMapper.php @@ -9,6 +9,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\NullType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; final class NullTypeMapper implements TypeMapperInterface @@ -33,4 +34,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { return null; } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ObjectTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ObjectTypeMapper.php index 650a1faaa54c..ba7cd27d29d8 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ObjectTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ObjectTypeMapper.php @@ -13,8 +13,11 @@ use PHPStan\Type\Generic\GenericObjectType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; +use Rector\NodeTypeResolver\ClassExistenceStaticHelper; use Rector\PHPStan\Type\AliasedObjectType; use Rector\PHPStan\Type\FullyQualifiedObjectType; +use Rector\PHPStan\Type\SelfObjectType; use Rector\PHPStan\Type\ShortenedObjectType; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; @@ -38,6 +41,10 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode */ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { + if ($type instanceof SelfObjectType) { + return new Identifier('self'); + } + if ($type instanceof ShortenedObjectType) { return new FullyQualified($type->getFullyQualifiedName()); } @@ -59,4 +66,31 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node // fallback return new FullyQualified($type->getClassName()); } + + /** + * @param ObjectType $type + */ + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + if ($type instanceof AliasedObjectType) { + // no preslash for alias + return $type->getClassName(); + } + + if ($type instanceof ShortenedObjectType) { + return '\\' . $type->getFullyQualifiedName(); + } + + if ($type instanceof FullyQualifiedObjectType) { + // always prefixed with \\ + return '\\' . $type->getClassName(); + } + + if (ClassExistenceStaticHelper::doesClassLikeExist($type->getClassName())) { + // FQN by default + return '\\' . $type->describe(VerbosityLevel::typeOnly()); + } + + return $type->getClassName(); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ObjectWithoutClassTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ObjectWithoutClassTypeMapper.php index 0f980d0d93e6..d57f5d41837b 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ObjectWithoutClassTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ObjectWithoutClassTypeMapper.php @@ -10,6 +10,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\ObjectWithoutClassType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\Php\PhpVersionProvider; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; use Rector\ValueObject\PhpVersionFeature; @@ -50,4 +51,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new Identifier('object'); } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ParentStaticTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ParentStaticTypeMapper.php index da6fb13f278c..6e9b42ff241a 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ParentStaticTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ParentStaticTypeMapper.php @@ -9,6 +9,7 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\PHPStan\Type\ParentStaticType; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; @@ -34,4 +35,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { return new Identifier('parent'); } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ResourceTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ResourceTypeMapper.php index 67c46764c4c7..864936607451 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ResourceTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ResourceTypeMapper.php @@ -9,6 +9,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\ResourceType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; final class ResourceTypeMapper implements TypeMapperInterface @@ -33,4 +34,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { return null; } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/StringTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/StringTypeMapper.php index 409c5e1ad7e7..409c897a1c67 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/StringTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/StringTypeMapper.php @@ -10,6 +10,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\StringType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\Php\PhpVersionProvider; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; use Rector\ValueObject\PhpVersionFeature; @@ -47,4 +48,9 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new Identifier('string'); } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ThisTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ThisTypeMapper.php index d8af6a281ba0..279576026fdc 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ThisTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ThisTypeMapper.php @@ -10,6 +10,7 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Type\ThisType; use PHPStan\Type\Type; +use PHPStan\Type\VerbosityLevel; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; final class ThisTypeMapper implements TypeMapperInterface @@ -34,4 +35,12 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node { return new Identifier('self'); } + + /** + * @param ThisType $type + */ + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/UnionTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/UnionTypeMapper.php index bdebec8c0a40..21bb291be8c7 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/UnionTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/UnionTypeMapper.php @@ -46,6 +46,14 @@ public function __construct(PhpVersionProvider $phpVersionProvider, UnionTypeAna $this->unionTypeAnalyzer = $unionTypeAnalyzer; } + /** + * @required + */ + public function autowireUnionTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void + { + $this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper; + } + public function getNodeClass(): string { return UnionType::class; @@ -67,14 +75,6 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode return new AttributeAwareUnionTypeNode($unionTypesNodes); } - /** - * @required - */ - public function autowire(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void - { - $this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper; - } - /** * @param UnionType $type */ @@ -109,6 +109,24 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new NullableType($nullabledTypeNode); } + /** + * @param UnionType $type + */ + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + $docStrings = []; + + foreach ($type->getTypes() as $unionedType) { + $docStrings[] = $this->phpStanStaticTypeMapper->mapToDocString($unionedType); + } + + // remove empty values, e.g. void/iterable + $docStrings = array_unique($docStrings); + $docStrings = array_filter($docStrings); + + return implode('|', $docStrings); + } + private function matchArrayTypes(UnionType $unionType): ?Identifier { $unionTypeAnalysis = $this->unionTypeAnalyzer->analyseForNullableAndIterable($unionType); diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/VoidTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/VoidTypeMapper.php index d6b35fa1436f..46b0ed002556 100644 --- a/packages/PHPStanStaticTypeMapper/src/TypeMapper/VoidTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/VoidTypeMapper.php @@ -54,4 +54,15 @@ public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node return new Identifier('void'); } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + if ($this->phpVersionProvider->isAtLeast(PhpVersionFeature::SCALAR_TYPES)) { + // the void type is better done in PHP code + return ''; + } + + // fallback for PHP 7.0 and older, where void type was only in docs + return 'void'; + } } From ccc63bbb75c81f517a4395ac21084f9e594cda9a Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Wed, 15 Jan 2020 14:51:15 +0100 Subject: [PATCH 3/3] decopule ArrayTypeMapper and TypeWithClassNameTypeMapper --- .../src/PHPStanStaticTypeMapper.php | 70 ---------- .../src/TypeMapper/ArrayTypeMapper.php | 124 ++++++++++++++++++ .../TypeWithClassNameTypeMapper.php | 56 ++++++++ 3 files changed, 180 insertions(+), 70 deletions(-) create mode 100644 packages/PHPStanStaticTypeMapper/src/TypeMapper/ArrayTypeMapper.php create mode 100644 packages/PHPStanStaticTypeMapper/src/TypeMapper/TypeWithClassNameTypeMapper.php diff --git a/packages/PHPStanStaticTypeMapper/src/PHPStanStaticTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/PHPStanStaticTypeMapper.php index 53b62e72aefe..327bc7b8b0d2 100644 --- a/packages/PHPStanStaticTypeMapper/src/PHPStanStaticTypeMapper.php +++ b/packages/PHPStanStaticTypeMapper/src/PHPStanStaticTypeMapper.php @@ -10,17 +10,11 @@ use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\NullableType; use PhpParser\Node\UnionType as PhpParserUnionType; -use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; -use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; -use PHPStan\Type\ArrayType; use PHPStan\Type\StaticType; use PHPStan\Type\Type; use PHPStan\Type\TypeWithClassName; -use PHPStan\Type\UnionType; -use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareUnionTypeNode; use Rector\Exception\NotImplementedException; -use Rector\PHPStan\Type\SelfObjectType; use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; final class PHPStanStaticTypeMapper @@ -40,16 +34,6 @@ public function __construct(array $typeMappers) public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode { - // @todo move to ArrayTypeMapper - if ($type instanceof ArrayType) { - $itemTypeNode = $this->mapToPHPStanPhpDocTypeNode($type->getItemType()); - if ($itemTypeNode instanceof UnionTypeNode) { - return $this->convertUnionArrayTypeNodesToArrayTypeOfUnionTypeNodes($itemTypeNode); - } - - return new ArrayTypeNode($itemTypeNode); - } - foreach ($this->typeMappers as $typeMapper) { if (! is_a($type, $typeMapper->getNodeClass(), true)) { continue; @@ -75,20 +59,12 @@ public function mapToPhpParserNode(Type $phpStanType, ?string $kind = null): ?No return $typeMapper->mapToPhpParserNode($phpStanType, $kind); } - if ($phpStanType instanceof ArrayType) { - return new Identifier('array'); - } - if ($phpStanType instanceof StaticType) { return null; } if ($phpStanType instanceof TypeWithClassName) { $lowerCasedClassName = strtolower($phpStanType->getClassName()); - if ($lowerCasedClassName === 'callable') { - return new Identifier('callable'); - } - if ($lowerCasedClassName === 'self') { return new Identifier('self'); } @@ -118,52 +94,6 @@ public function mapToDocString(Type $phpStanType, ?Type $parentType = null): str return $typeMapper->mapToDocString($phpStanType, $parentType); } - if ($phpStanType instanceof ArrayType) { - if ($phpStanType->getItemType() instanceof UnionType) { - $unionedTypesAsString = []; - foreach ($phpStanType->getItemType()->getTypes() as $unionedArrayItemType) { - $unionedTypesAsString[] = $this->mapToDocString($unionedArrayItemType, $phpStanType) . '[]'; - } - - $unionedTypesAsString = array_values($unionedTypesAsString); - $unionedTypesAsString = array_unique($unionedTypesAsString); - - return implode('|', $unionedTypesAsString); - } - - $docString = $this->mapToDocString($phpStanType->getItemType(), $parentType); - - // @todo improve this - $docStringTypes = explode('|', $docString); - $docStringTypes = array_filter($docStringTypes); - - foreach ($docStringTypes as $key => $docStringType) { - $docStringTypes[$key] = $docStringType . '[]'; - } - - return implode('|', $docStringTypes); - } - throw new NotImplementedException(__METHOD__ . ' for ' . get_class($phpStanType)); } - - private function convertUnionArrayTypeNodesToArrayTypeOfUnionTypeNodes( - UnionTypeNode $unionTypeNode - ): AttributeAwareUnionTypeNode { - $unionedArrayType = []; - foreach ($unionTypeNode->types as $unionedType) { - if ($unionedType instanceof UnionTypeNode) { - foreach ($unionedType->types as $key => $subUnionedType) { - $unionedType->types[$key] = new ArrayTypeNode($subUnionedType); - } - - $unionedArrayType[] = $unionedType; - continue; - } - - $unionedArrayType[] = new ArrayTypeNode($unionedType); - } - - return new AttributeAwareUnionTypeNode($unionedArrayType); - } } diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/ArrayTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ArrayTypeMapper.php new file mode 100644 index 000000000000..9ef44f736146 --- /dev/null +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/ArrayTypeMapper.php @@ -0,0 +1,124 @@ +phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($type->getItemType()); + + if ($itemTypeNode instanceof UnionTypeNode) { + return $this->convertUnionArrayTypeNodesToArrayTypeOfUnionTypeNodes($itemTypeNode); + } + + return new ArrayTypeNode($itemTypeNode); + } + + /** + * @param ArrayType $type + */ + public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node + { + return new Identifier('array'); + } + + /** + * @param ArrayType $type + */ + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + $itemType = $type->getItemType(); + + if ($itemType instanceof UnionType) { + return $this->mapArrayUnionTypeToDocString($type, $itemType); + } + + $docString = $this->phpStanStaticTypeMapper->mapToDocString($type->getItemType(), $parentType); + + // @todo improve this + $docStringTypes = explode('|', $docString); + $docStringTypes = array_filter($docStringTypes); + + foreach ($docStringTypes as $key => $docStringType) { + $docStringTypes[$key] = $docStringType . '[]'; + } + + return implode('|', $docStringTypes); + } + + /** + * @required + */ + public function autowireArrayTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void + { + $this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper; + } + + private function mapArrayUnionTypeToDocString(ArrayType $arrayType, UnionType $unionType): string + { + $unionedTypesAsString = []; + + foreach ($unionType->getTypes() as $unionedArrayItemType) { + $unionedTypesAsString[] = $this->phpStanStaticTypeMapper->mapToDocString( + $unionedArrayItemType, + $arrayType + ) . '[]'; + } + + $unionedTypesAsString = array_values($unionedTypesAsString); + $unionedTypesAsString = array_unique($unionedTypesAsString); + + return implode('|', $unionedTypesAsString); + } + + /** + * @todo improve + */ + private function convertUnionArrayTypeNodesToArrayTypeOfUnionTypeNodes( + UnionTypeNode $unionTypeNode + ): AttributeAwareUnionTypeNode { + $unionedArrayType = []; + foreach ($unionTypeNode->types as $unionedType) { + if ($unionedType instanceof UnionTypeNode) { + foreach ($unionedType->types as $key => $subUnionedType) { + $unionedType->types[$key] = new ArrayTypeNode($subUnionedType); + } + + $unionedArrayType[] = $unionedType; + continue; + } + + $unionedArrayType[] = new ArrayTypeNode($unionedType); + } + + return new AttributeAwareUnionTypeNode($unionedArrayType); + } +} diff --git a/packages/PHPStanStaticTypeMapper/src/TypeMapper/TypeWithClassNameTypeMapper.php b/packages/PHPStanStaticTypeMapper/src/TypeMapper/TypeWithClassNameTypeMapper.php new file mode 100644 index 000000000000..aa8fd75e83e4 --- /dev/null +++ b/packages/PHPStanStaticTypeMapper/src/TypeMapper/TypeWithClassNameTypeMapper.php @@ -0,0 +1,56 @@ +phpVersionProvider = $phpVersionProvider; + } + + public function getNodeClass(): string + { + return StringType::class; + } + + /** + * @param StringType $type + */ + public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode + { + return new IdentifierTypeNode('string'); + } + + public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node + { + if (! $this->phpVersionProvider->isAtLeast(PhpVersionFeature::SCALAR_TYPES)) { + return null; + } + + return new Identifier('string'); + } + + public function mapToDocString(Type $type, ?Type $parentType = null): string + { + return $type->describe(VerbosityLevel::typeOnly()); + } +}