Add support for constant types.

phpstan supports contant definitions and expressions to
link to constants.
This commit is contained in:
Jaapio
2022-11-04 11:21:53 +01:00
parent 8d57d3da2d
commit 50bf16734e
8 changed files with 206 additions and 62 deletions
+35 -4
View File
@@ -4,10 +4,15 @@ 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_;
@@ -20,6 +25,10 @@ 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;
@@ -48,10 +57,12 @@ use function strtolower;
final class TypeFactory
{
private TypeResolver $resolver;
private FqsenResolver $fqsenResolver;
public function __construct(TypeResolver $resolver)
public function __construct(TypeResolver $resolver, FqsenResolver $fqsenResolver)
{
$this->resolver = $resolver;
$this->fqsenResolver = $fqsenResolver;
}
public function createType(?TypeNode $type, ?Context $context): ?Type
@@ -82,7 +93,7 @@ final class TypeFactory
return $this->createFromCallable($type, $context);
case ConstTypeNode::class:
return null;
return $this->createFromConst($type, $context);
case GenericTypeNode::class:
return $this->createFromGeneric($type, $context);
@@ -144,12 +155,12 @@ final class TypeFactory
case 'class-string':
return new ClassString(
$this->createType($type->genericTypes[0], $context)->getFqsen()
$this->fqsenResolver->resolve((string) $type->genericTypes[0], $context)
);
case 'interface-string':
return new InterfaceString(
$this->createType($type->genericTypes[0], $context)->getFqsen()
$this->fqsenResolver->resolve((string) $type->genericTypes[0], $context)
);
case 'list':
@@ -180,4 +191,24 @@ final class TypeFactory
{
return new Callable_();
}
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
);
}
}
}
+1 -1
View File
@@ -70,7 +70,7 @@ final class DocBlockFactory implements DocBlockFactoryInterface
$tagFactory = new StandardTagFactory($fqsenResolver);
$descriptionFactory = new DescriptionFactory($tagFactory);
$typeResolver = new TypeResolver($fqsenResolver);
$typeFactory = new TypeFactory($typeResolver);
$typeFactory = new TypeFactory($typeResolver, $fqsenResolver);
$phpstanTagFactory = new AbstractPHPStanFactory(
new ParamFactory($typeFactory, $descriptionFactory),
+44
View File
@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace phpDocumentor\Reflection\PseudoTypes;
use phpDocumentor\Reflection\Fqsen;
use phpDocumentor\Reflection\PseudoType;
use phpDocumentor\Reflection\Type;
use phpDocumentor\Reflection\Types\Mixed_;
use function sprintf;
final class ConstExpression implements PseudoType
{
private Fqsen $owner;
private string $expression;
public function __construct(Fqsen $owner, string $expression)
{
$this->owner = $owner;
$this->expression = $expression;
}
public function getOwner(): Fqsen
{
return $this->owner;
}
public function getExpression(): string
{
return $this->expression;
}
public function underlyingType(): Type
{
return new Mixed_();
}
public function __toString(): string
{
return sprintf('%s::%s', $this->owner, $this->expression);
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace phpDocumentor\Reflection\PseudoTypes;
use phpDocumentor\Reflection\PseudoType;
use phpDocumentor\Reflection\Type;
use phpDocumentor\Reflection\Types\Float_;
class FloatValue implements PseudoType
{
private float $value;
public function __construct(float $value)
{
$this->value = $value;
}
public function getValue(): float
{
return $this->value;
}
public function underlyingType(): Type
{
return new Float_();
}
public function __toString(): string
{
return (string) $this->value;
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace phpDocumentor\Reflection\PseudoTypes;
use phpDocumentor\Reflection\PseudoType;
use phpDocumentor\Reflection\Type;
use phpDocumentor\Reflection\Types\Integer;
final class IntegerValue implements PseudoType
{
private int $value;
public function __construct(int $value)
{
$this->value = $value;
}
public function getValue(): int
{
return $this->value;
}
public function underlyingType(): Type
{
return new Integer();
}
public function __toString(): string
{
return (string) $this->value;
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace phpDocumentor\Reflection\PseudoTypes;
use phpDocumentor\Reflection\PseudoType;
use phpDocumentor\Reflection\Type;
use phpDocumentor\Reflection\Types\Float_;
use function sprintf;
class StringValue implements PseudoType
{
private string $value;
public function __construct(string $value)
{
$this->value = $value;
}
public function getValue(): string
{
return $this->value;
}
public function underlyingType(): Type
{
return new Float_();
}
public function __toString(): string
{
return sprintf('"%s"', $this->value);
}
}