Remove type logic from this package

This commit is contained in:
Jaapio
2022-11-11 12:30:14 +01:00
parent d6e90a3238
commit 6a92bc3ce9
28 changed files with 108 additions and 844 deletions
@@ -50,6 +50,10 @@ class AbstractPHPStanFactory implements Factory
$tokens = $this->lexer->tokenize($tagLine);
$ast = $this->parser->parseTag(new TokenIterator($tokens));
if ($context === null) {
$context = new TypeContext('');
}
foreach ($this->factories as $factory) {
if ($factory->supports($ast, $context)) {
return $factory->create($ast, $context);
+9 -8
View File
@@ -9,6 +9,7 @@ use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tags\Method;
use phpDocumentor\Reflection\DocBlock\Tags\MethodParameter;
use phpDocumentor\Reflection\Type;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\Context;
use phpDocumentor\Reflection\Types\Mixed_;
use phpDocumentor\Reflection\Types\Void_;
@@ -25,16 +26,16 @@ use function trim;
*/
final class MethodFactory implements PHPStanFactory
{
private TypeFactory $typeFactory;
private DescriptionFactory $descriptionFactory;
private TypeResolver $typeResolver;
public function __construct(TypeFactory $typeFactory, DescriptionFactory $descriptionFactory)
public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
{
$this->typeFactory = $typeFactory;
$this->descriptionFactory = $descriptionFactory;
$this->typeResolver = $typeResolver;
}
public function create(PhpDocTagNode $node, ?Context $context): Tag
public function create(PhpDocTagNode $node, Context $context): Tag
{
$tagValue = $node->value;
Assert::isInstanceOf($tagValue, MethodTagValueNode::class);
@@ -50,7 +51,7 @@ final class MethodFactory implements PHPStanFactory
function (MethodTagValueParameterNode $param) use ($context) {
return new MethodParameter(
trim($param->parameterName, '$'),
$this->typeFactory->createType($param->type, $context) ?? new Mixed_(),
$this->typeResolver->createType($param->type, $context) ?? new Mixed_(),
$param->isReference,
$param->isVariadic,
(string) $param->defaultValue
@@ -61,13 +62,13 @@ final class MethodFactory implements PHPStanFactory
);
}
public function supports(PhpDocTagNode $node, ?Context $context): bool
public function supports(PhpDocTagNode $node, Context $context): bool
{
return $node->value instanceof MethodTagValueNode;
}
private function createReturnType(MethodTagValueNode $tagValue, ?Context $context): Type
private function createReturnType(MethodTagValueNode $tagValue, Context $context): Type
{
return $this->typeFactory->createType($tagValue->returnType, $context) ?? new Void_();
return $this->typeResolver->createType($tagValue->returnType, $context) ?? new Void_();
}
}
+2 -2
View File
@@ -10,7 +10,7 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
interface PHPStanFactory
{
public function create(PhpDocTagNode $node, ?Context $context): Tag;
public function create(PhpDocTagNode $node, Context $context): Tag;
public function supports(PhpDocTagNode $node, ?Context $context): bool;
public function supports(PhpDocTagNode $node, Context $context): bool;
}
+7 -6
View File
@@ -7,6 +7,7 @@ namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tags\Param;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\Context;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
@@ -19,30 +20,30 @@ use function trim;
*/
final class ParamFactory implements PHPStanFactory
{
private TypeFactory $typeFactory;
private DescriptionFactory $descriptionFactory;
private TypeResolver $typeResolver;
public function __construct(TypeFactory $typeFactory, DescriptionFactory $descriptionFactory)
public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
{
$this->typeFactory = $typeFactory;
$this->descriptionFactory = $descriptionFactory;
$this->typeResolver = $typeResolver;
}
public function create(PhpDocTagNode $node, ?Context $context): Tag
public function create(PhpDocTagNode $node, Context $context): Tag
{
$tagValue = $node->value;
Assert::isInstanceOf($tagValue, ParamTagValueNode::class);
return new Param(
trim($tagValue->parameterName, '$'),
$this->typeFactory->createType($tagValue->type, $context),
$this->typeResolver->createType($tagValue->type, $context),
$tagValue->isVariadic,
$this->descriptionFactory->create($tagValue->description, $context),
$tagValue->isReference
);
}
public function supports(PhpDocTagNode $node, ?Context $context): bool
public function supports(PhpDocTagNode $node, Context $context): bool
{
return $node->value instanceof ParamTagValueNode;
}
@@ -7,6 +7,7 @@ namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tags\Property;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\Context;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
@@ -19,28 +20,28 @@ use function trim;
*/
final class PropertyFactory implements PHPStanFactory
{
private TypeFactory $typeFactory;
private DescriptionFactory $descriptionFactory;
private TypeResolver $typeResolver;
public function __construct(TypeFactory $typeFactory, DescriptionFactory $descriptionFactory)
public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
{
$this->typeFactory = $typeFactory;
$this->descriptionFactory = $descriptionFactory;
$this->typeResolver = $typeResolver;
}
public function create(PhpDocTagNode $node, ?Context $context): Tag
public function create(PhpDocTagNode $node, Context $context): Tag
{
$tagValue = $node->value;
Assert::isInstanceOf($tagValue, PropertyTagValueNode::class);
return new Property(
trim($tagValue->propertyName, '$'),
$this->typeFactory->createType($tagValue->type, $context),
$this->typeResolver->createType($tagValue->type, $context),
$this->descriptionFactory->create($tagValue->description, $context)
);
}
public function supports(PhpDocTagNode $node, ?Context $context): bool
public function supports(PhpDocTagNode $node, Context $context): bool
{
return $node->value instanceof PropertyTagValueNode && $node->name === '@property';
}
@@ -7,6 +7,7 @@ namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tags\PropertyRead;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\Context;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
@@ -19,28 +20,28 @@ use function trim;
*/
final class PropertyReadFactory implements PHPStanFactory
{
private TypeFactory $typeFactory;
private DescriptionFactory $descriptionFactory;
private TypeResolver $typeResolver;
public function __construct(TypeFactory $typeFactory, DescriptionFactory $descriptionFactory)
public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
{
$this->typeFactory = $typeFactory;
$this->typeResolver = $typeResolver;
$this->descriptionFactory = $descriptionFactory;
}
public function create(PhpDocTagNode $node, ?Context $context): Tag
public function create(PhpDocTagNode $node, Context $context): Tag
{
$tagValue = $node->value;
Assert::isInstanceOf($tagValue, PropertyTagValueNode::class);
return new PropertyRead(
trim($tagValue->propertyName, '$'),
$this->typeFactory->createType($tagValue->type, $context),
$this->typeResolver->createType($tagValue->type, $context),
$this->descriptionFactory->create($tagValue->description, $context)
);
}
public function supports(PhpDocTagNode $node, ?Context $context): bool
public function supports(PhpDocTagNode $node, Context $context): bool
{
return $node->value instanceof PropertyTagValueNode && $node->name === '@property-read';
}
@@ -7,6 +7,7 @@ namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\Context;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
@@ -19,28 +20,28 @@ use function trim;
*/
final class PropertyWriteFactory implements PHPStanFactory
{
private TypeFactory $typeFactory;
private DescriptionFactory $descriptionFactory;
private TypeResolver $typeResolver;
public function __construct(TypeFactory $typeFactory, DescriptionFactory $descriptionFactory)
public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
{
$this->typeFactory = $typeFactory;
$this->descriptionFactory = $descriptionFactory;
$this->typeResolver = $typeResolver;
}
public function create(PhpDocTagNode $node, ?Context $context): Tag
public function create(PhpDocTagNode $node, Context $context): Tag
{
$tagValue = $node->value;
Assert::isInstanceOf($tagValue, PropertyTagValueNode::class);
return new PropertyWrite(
trim($tagValue->propertyName, '$'),
$this->typeFactory->createType($tagValue->type, $context),
$this->typeResolver->createType($tagValue->type, $context),
$this->descriptionFactory->create($tagValue->description, $context)
);
}
public function supports(PhpDocTagNode $node, ?Context $context): bool
public function supports(PhpDocTagNode $node, Context $context): bool
{
return $node->value instanceof PropertyTagValueNode && $node->name === '@property-write';
}
+7 -6
View File
@@ -7,6 +7,7 @@ namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tags\Return_;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\Context;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
@@ -17,27 +18,27 @@ use Webmozart\Assert\Assert;
*/
final class ReturnFactory implements PHPStanFactory
{
private TypeFactory $typeFactory;
private DescriptionFactory $descriptionFactory;
private TypeResolver $typeResolver;
public function __construct(TypeFactory $typeFactory, DescriptionFactory $descriptionFactory)
public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
{
$this->typeFactory = $typeFactory;
$this->descriptionFactory = $descriptionFactory;
$this->typeResolver = $typeResolver;
}
public function create(PhpDocTagNode $node, ?Context $context): Tag
public function create(PhpDocTagNode $node, Context $context): Tag
{
$tagValue = $node->value;
Assert::isInstanceOf($tagValue, ReturnTagValueNode::class);
return new Return_(
$this->typeFactory->createType($tagValue->type, $context),
$this->typeResolver->createType($tagValue->type, $context),
$this->descriptionFactory->create($tagValue->description, $context)
);
}
public function supports(PhpDocTagNode $node, ?Context $context): bool
public function supports(PhpDocTagNode $node, Context $context): bool
{
return $node->value instanceof ReturnTagValueNode;
}
-230
View File
@@ -1,230 +0,0 @@
<?php
declare(strict_types=1);
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
use phpDocumentor\Reflection\FqsenResolver;
use phpDocumentor\Reflection\PseudoTypes\ArrayShape;
use phpDocumentor\Reflection\PseudoTypes\ArrayShapeItem;
use phpDocumentor\Reflection\PseudoTypes\ConstExpression;
use phpDocumentor\Reflection\PseudoTypes\FloatValue;
use phpDocumentor\Reflection\PseudoTypes\IntegerRange;
use phpDocumentor\Reflection\PseudoTypes\IntegerValue;
use phpDocumentor\Reflection\PseudoTypes\List_;
use phpDocumentor\Reflection\PseudoTypes\StringValue;
use phpDocumentor\Reflection\Type;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\Array_;
use phpDocumentor\Reflection\Types\Callable_;
use phpDocumentor\Reflection\Types\CallableParameter;
use phpDocumentor\Reflection\Types\ClassString;
use phpDocumentor\Reflection\Types\Collection;
use phpDocumentor\Reflection\Types\Compound;
use phpDocumentor\Reflection\Types\Context;
use phpDocumentor\Reflection\Types\InterfaceString;
use phpDocumentor\Reflection\Types\Intersection;
use phpDocumentor\Reflection\Types\Nullable;
use phpDocumentor\Reflection\Types\This;
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprFloatNode;
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode;
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
use PHPStan\PhpDocParser\Ast\Type\CallableTypeNode;
use PHPStan\PhpDocParser\Ast\Type\CallableTypeParameterNode;
use PHPStan\PhpDocParser\Ast\Type\ConditionalTypeForParameterNode;
use PHPStan\PhpDocParser\Ast\Type\ConditionalTypeNode;
use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode;
use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
use PHPStan\PhpDocParser\Ast\Type\OffsetAccessTypeNode;
use PHPStan\PhpDocParser\Ast\Type\ThisTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use function array_filter;
use function array_map;
use function array_reverse;
use function get_class;
use function strtolower;
/**
* @internal This class is not part of the BC promise of this library.
*/
final class TypeFactory
{
private TypeResolver $resolver;
private FqsenResolver $fqsenResolver;
public function __construct(TypeResolver $resolver, FqsenResolver $fqsenResolver)
{
$this->resolver = $resolver;
$this->fqsenResolver = $fqsenResolver;
}
public function createType(?TypeNode $type, ?Context $context): ?Type
{
if ($type === null) {
return null;
}
switch (get_class($type)) {
case ArrayTypeNode::class:
return new Array_(
$this->createType($type->type, $context)
);
case ArrayShapeNode::class:
return new ArrayShape(
...array_map(
fn (ArrayShapeItemNode $item) => new ArrayShapeItem(
(string) $item->keyName,
$this->createType($item->valueType, $context),
$item->optional
),
$type->items
)
);
case CallableTypeNode::class:
return $this->createFromCallable($type, $context);
case ConstTypeNode::class:
return $this->createFromConst($type, $context);
case GenericTypeNode::class:
return $this->createFromGeneric($type, $context);
case IdentifierTypeNode::class:
return $this->resolver->resolve($type->name, $context);
case IntersectionTypeNode::class:
return new Intersection(
array_filter(
array_map(
fn (TypeNode $nestedType) => $this->createType($nestedType, $context),
$type->types
)
)
);
case NullableTypeNode::class:
$nestedType = $this->createType($type->type, $context);
if ($nestedType === null) {
return null;
}
return new Nullable($nestedType);
case UnionTypeNode::class:
return new Compound(
array_filter(
array_map(
fn (TypeNode $nestedType) => $this->createType($nestedType, $context),
$type->types
)
)
);
case ThisTypeNode::class:
return new This();
case ConditionalTypeNode::class:
case ConditionalTypeForParameterNode::class:
case OffsetAccessTypeNode::class:
default:
return null;
}
}
private function createFromGeneric(GenericTypeNode $type, ?Context $context): Type
{
switch (strtolower($type->type->name)) {
case 'array':
return new Array_(
...array_reverse(
array_map(
fn (TypeNode $genericType) => $this->createType($genericType, $context),
$type->genericTypes
)
)
);
case 'class-string':
return new ClassString(
$this->fqsenResolver->resolve((string) $type->genericTypes[0], $context)
);
case 'interface-string':
return new InterfaceString(
$this->fqsenResolver->resolve((string) $type->genericTypes[0], $context)
);
case 'list':
return new List_(
$this->createType($type->genericTypes[0], $context)
);
case 'int':
return new IntegerRange(
(string) $type->genericTypes[0],
(string) ($type->genericTypes[1] ?? ''),
);
default:
return new Collection(
$this->createType($type->type, $context)->getFqsen(),
...array_reverse(
array_map(
fn (TypeNode $genericType) => $this->createType($genericType, $context),
$type->genericTypes
)
)
);
}
}
private function createFromCallable(CallableTypeNode $type, ?Context $context): Callable_
{
return new Callable_(
array_map(
function (CallableTypeParameterNode $param) use ($context) {
return new CallableParameter(
$param->parameterName !== '' ? trim($param->parameterName, '$') : null,
$this->createType($param->type, $context),
$param->isReference,
$param->isVariadic,
$param->isOptional
);
},
$type->parameters
),
$this->createType($type->returnType, $context),
);
}
private function createFromConst(ConstTypeNode $type, ?Context $context): ?Type
{
switch (get_class($type->constExpr)) {
case ConstExprIntegerNode::class:
return new IntegerValue((int) $type->constExpr->value);
case ConstExprFloatNode::class:
return new FloatValue((float) $type->constExpr->value);
case ConstExprStringNode::class:
return new StringValue($type->constExpr->value);
case ConstFetchNode::class:
return new ConstExpression(
$this->fqsenResolver->resolve($type->constExpr->className, $context),
$type->constExpr->name
);
}
}
}
+7 -6
View File
@@ -7,6 +7,7 @@ namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
use phpDocumentor\Reflection\TypeResolver;
use phpDocumentor\Reflection\Types\Context;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
@@ -19,28 +20,28 @@ use function trim;
*/
final class VarFactory implements PHPStanFactory
{
private TypeFactory $typeFactory;
private DescriptionFactory $descriptionFactory;
private TypeResolver $typeResolver;
public function __construct(TypeFactory $typeFactory, DescriptionFactory $descriptionFactory)
public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
{
$this->typeFactory = $typeFactory;
$this->descriptionFactory = $descriptionFactory;
$this->typeResolver = $typeResolver;
}
public function create(PhpDocTagNode $node, ?Context $context): Tag
public function create(PhpDocTagNode $node, Context $context): Tag
{
$tagValue = $node->value;
Assert::isInstanceOf($tagValue, VarTagValueNode::class);
return new Var_(
trim($tagValue->variableName, '$'),
$this->typeFactory->createType($tagValue->type, $context),
$this->typeResolver->createType($tagValue->type, $context),
$this->descriptionFactory->create($tagValue->description, $context)
);
}
public function supports(PhpDocTagNode $node, ?Context $context): bool
public function supports(PhpDocTagNode $node, Context $context): bool
{
return $node->value instanceof VarTagValueNode;
}