mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Cleanup and var implementation
This commit is contained in:
@@ -76,7 +76,7 @@ final class StandardTagFactory implements TagFactory
|
||||
public const REGEX_TAGNAME = '[\w\-\_\\\\:]+';
|
||||
|
||||
/**
|
||||
* @var array<class-string<Tag>> An array with a tag as a key, and an
|
||||
* @var array<class-string<Tag>|Factory> An array with a tag as a key, and an
|
||||
* FQCN to a class that handles it as an array value.
|
||||
*/
|
||||
private $tagHandlerMappings = [
|
||||
@@ -177,7 +177,7 @@ final class StandardTagFactory implements TagFactory
|
||||
}
|
||||
|
||||
if (is_object($handler)) {
|
||||
Assert::implementsInterface($handler, TagFactory::class);
|
||||
Assert::implementsInterface($handler, Factory::class);
|
||||
$this->tagHandlerMappings[$tagName] = $handler;
|
||||
|
||||
return;
|
||||
@@ -283,12 +283,12 @@ final class StandardTagFactory implements TagFactory
|
||||
}
|
||||
}
|
||||
|
||||
$parameterName = $parameter->getName();
|
||||
if (isset($locator[$typeHint])) {
|
||||
$arguments[] = $locator[$typeHint];
|
||||
$arguments[$parameterName] = $locator[$typeHint];
|
||||
continue;
|
||||
}
|
||||
|
||||
$parameterName = $parameter->getName();
|
||||
if (isset($locator[$parameterName])) {
|
||||
$arguments[$parameterName] = $locator[$parameterName];
|
||||
continue;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ final class ParamFactory implements PHPStanFactory
|
||||
$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, ParamTagValueNode::class);
|
||||
|
||||
@@ -44,7 +44,7 @@ use function strtolower;
|
||||
/**
|
||||
* @internal This class is not part of the BC promise of this library.
|
||||
*/
|
||||
class TypeFactory
|
||||
final class TypeFactory
|
||||
{
|
||||
private TypeResolver $resolver;
|
||||
|
||||
@@ -53,7 +53,7 @@ class TypeFactory
|
||||
$this->resolver = $resolver;
|
||||
}
|
||||
|
||||
public function createType(TypeNode $type, Context $context): ?Type
|
||||
public function createType(TypeNode $type, ?Context $context): ?Type
|
||||
{
|
||||
switch (get_class($type)) {
|
||||
case ArrayTypeNode::class:
|
||||
@@ -77,6 +77,7 @@ class TypeFactory
|
||||
return $this->createFromCallable($type, $context);
|
||||
|
||||
case ConstTypeNode::class:
|
||||
return null;
|
||||
case GenericTypeNode::class:
|
||||
return $this->createFromGeneric($type, $context);
|
||||
|
||||
@@ -85,23 +86,30 @@ class TypeFactory
|
||||
|
||||
case IntersectionTypeNode::class:
|
||||
return new Intersection(
|
||||
array_filter(
|
||||
array_map(
|
||||
fn (TypeNode $nestedType) => $this->createType($nestedType, $context),
|
||||
$type->types
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
case NullableTypeNode::class:
|
||||
return new Nullable(
|
||||
$this->createType($type->type, $context)
|
||||
);
|
||||
$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:
|
||||
@@ -115,7 +123,7 @@ class TypeFactory
|
||||
}
|
||||
}
|
||||
|
||||
private function createFromGeneric(GenericTypeNode $type, Context $context): Type
|
||||
private function createFromGeneric(GenericTypeNode $type, ?Context $context): Type
|
||||
{
|
||||
switch (strtolower($type->type->name)) {
|
||||
case 'array':
|
||||
@@ -162,7 +170,7 @@ class TypeFactory
|
||||
}
|
||||
}
|
||||
|
||||
private function createFromCallable(CallableTypeNode $type, Context $context): Callable_
|
||||
private function createFromCallable(CallableTypeNode $type, ?Context $context): Callable_
|
||||
{
|
||||
return new Callable_();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
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\Types\Context;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
use function trim;
|
||||
|
||||
/**
|
||||
* @internal This class is not part of the BC promise of this library.
|
||||
*/
|
||||
final class VarFactory implements PHPStanFactory
|
||||
{
|
||||
private TypeFactory $typeFactory;
|
||||
private DescriptionFactory $descriptionFactory;
|
||||
|
||||
public function __construct(TypeFactory $typeFactory, DescriptionFactory $descriptionFactory)
|
||||
{
|
||||
$this->typeFactory = $typeFactory;
|
||||
$this->descriptionFactory = $descriptionFactory;
|
||||
}
|
||||
|
||||
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->descriptionFactory->create($tagValue->description, $context)
|
||||
);
|
||||
}
|
||||
|
||||
public function supports(PhpDocTagNode $node, ?Context $context): bool
|
||||
{
|
||||
return $node->value instanceof VarTagValueNode;
|
||||
}
|
||||
}
|
||||
@@ -42,13 +42,13 @@ final class DocBlockFactory implements DocBlockFactoryInterface
|
||||
/** @var DocBlock\DescriptionFactory */
|
||||
private $descriptionFactory;
|
||||
|
||||
/** @var Factory */
|
||||
/** @var TagFactory */
|
||||
private $tagFactory;
|
||||
|
||||
/**
|
||||
* Initializes this factory with the required subcontractors.
|
||||
*/
|
||||
public function __construct(DescriptionFactory $descriptionFactory, Factory $tagFactory)
|
||||
public function __construct(DescriptionFactory $descriptionFactory, TagFactory $tagFactory)
|
||||
{
|
||||
$this->descriptionFactory = $descriptionFactory;
|
||||
$this->tagFactory = $tagFactory;
|
||||
@@ -57,7 +57,7 @@ final class DocBlockFactory implements DocBlockFactoryInterface
|
||||
/**
|
||||
* Factory method for easy instantiation.
|
||||
*
|
||||
* @param array<string, class-string<Tag>|TagFactory> $additionalTags
|
||||
* @param array<string, class-string<Tag>|Factory> $additionalTags
|
||||
*/
|
||||
public static function createInstance(array $additionalTags = []): self
|
||||
{
|
||||
@@ -74,6 +74,7 @@ final class DocBlockFactory implements DocBlockFactoryInterface
|
||||
$tagFactory->addService($descriptionFactory);
|
||||
$tagFactory->addService($typeResolver);
|
||||
$tagFactory->registerTagHandler('param', $phpstanTagFactory);
|
||||
$tagFactory->registerTagHandler('var', $phpstanTagFactory);
|
||||
|
||||
$docBlockFactory = new self($descriptionFactory, $tagFactory);
|
||||
foreach ($additionalTags as $tagName => $tagHandler) {
|
||||
@@ -122,9 +123,9 @@ final class DocBlockFactory implements DocBlockFactoryInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<Tag> $handler
|
||||
* @param class-string<Tag>|Factory $handler
|
||||
*/
|
||||
public function registerTagHandler(string $tagName, string $handler): void
|
||||
public function registerTagHandler(string $tagName, $handler): void
|
||||
{
|
||||
$this->tagFactory->registerTagHandler($tagName, $handler);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace phpDocumentor\Reflection\PseudoTypes;
|
||||
|
||||
use phpDocumentor\Reflection\Type;
|
||||
|
||||
use phpDocumentor\Reflection\Types\Mixed_;
|
||||
use function sprintf;
|
||||
|
||||
final class ArrayShapeItem
|
||||
@@ -14,10 +15,10 @@ final class ArrayShapeItem
|
||||
private Type $value;
|
||||
private bool $optional;
|
||||
|
||||
public function __construct(?string $key, Type $value, bool $optional)
|
||||
public function __construct(?string $key, ?Type $value, bool $optional)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
$this->value = $value ?? new Mixed_();
|
||||
$this->optional = $optional;
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ final class ArrayShapeItem
|
||||
return $this->optional;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
public function __toString(): string
|
||||
{
|
||||
if ($this->key !== null) {
|
||||
return sprintf(
|
||||
|
||||
@@ -14,34 +14,18 @@ declare(strict_types=1);
|
||||
namespace phpDocumentor\Reflection\Assets;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\DocBlock\TagFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\Factory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
|
||||
class CustomTagFactory implements TagFactory
|
||||
class CustomTagFactory implements Factory
|
||||
{
|
||||
public $class;
|
||||
|
||||
public function addParameter(string $name, $value): void
|
||||
{
|
||||
// TODO: Implement addParameter() method.
|
||||
}
|
||||
|
||||
public function create(string $tagLine, ?Context $context = null, CustomServiceClass $class = null): Tag
|
||||
{
|
||||
$this->class = $class;
|
||||
|
||||
return new Generic('custom');
|
||||
}
|
||||
|
||||
public function addService(object $service): void
|
||||
{
|
||||
// TODO: Implement addService() method.
|
||||
}
|
||||
|
||||
public function registerTagHandler(string $tagName, string $handler): void
|
||||
{
|
||||
// TODO: Implement registerTagHandler() method.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Param;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\String_;
|
||||
|
||||
final class ParamFactoryTest extends TagFactoryTestCase
|
||||
{
|
||||
/**
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory::create
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory::supports
|
||||
*/
|
||||
public function testParamIsCreated(): void
|
||||
{
|
||||
$ast = $this->parseTag('@param string $var');
|
||||
$factory = new ParamFactory($this->giveTypeFactory(), $this->givenDescriptionFactory());
|
||||
$context = new Context('global');
|
||||
|
||||
self::assertTrue($factory->supports($ast, $context));
|
||||
self::assertEquals(
|
||||
new Param(
|
||||
'var',
|
||||
new String_(),
|
||||
false,
|
||||
new Description(''),
|
||||
false
|
||||
),
|
||||
$factory->create($ast, $context)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use Mockery as m;
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use PHPStan\PhpDocParser\Parser\ConstExprParser;
|
||||
use PHPStan\PhpDocParser\Parser\PhpDocParser;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use PHPStan\PhpDocParser\Parser\TypeParser;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
abstract class TagFactoryTestCase extends TestCase
|
||||
{
|
||||
public function parseTag(string $tag): PhpDocTagNode
|
||||
{
|
||||
$lexer = new Lexer();
|
||||
$tokens = $lexer->tokenize($tag);
|
||||
$constParser = new ConstExprParser();
|
||||
|
||||
return (new PhpDocParser(new TypeParser($constParser), $constParser))->parseTag(new TokenIterator($tokens));
|
||||
}
|
||||
|
||||
public function giveTypeFactory(): TypeFactory
|
||||
{
|
||||
return new TypeFactory(new TypeResolver(new FqsenResolver()));
|
||||
}
|
||||
|
||||
public function givenDescriptionFactory(): DescriptionFactory
|
||||
{
|
||||
$factory = m::mock(DescriptionFactory::class);
|
||||
$factory->shouldReceive('create')->andReturn(new Description(''));
|
||||
|
||||
return $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call Mockery::close after each test.
|
||||
*
|
||||
* @after
|
||||
*/
|
||||
public function closeMockery(): void
|
||||
{
|
||||
m::close();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
@@ -56,6 +65,9 @@ final class TypeFactoryTest extends TestCase
|
||||
self::assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<array{0: string, 1: Type}>
|
||||
*/
|
||||
public function typeProvider(): array
|
||||
{
|
||||
return [
|
||||
@@ -126,6 +138,9 @@ final class TypeFactoryTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<array{0: string, 1: Type}>
|
||||
*/
|
||||
public function genericsProvider(): array
|
||||
{
|
||||
return [
|
||||
@@ -169,6 +184,9 @@ final class TypeFactoryTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<array{0: string, 1: Type}>
|
||||
*/
|
||||
public function callableProvider(): array
|
||||
{
|
||||
return [
|
||||
@@ -195,6 +213,9 @@ final class TypeFactoryTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<array{0: string, 1: Type}>
|
||||
*/
|
||||
public function constExpressions(): array
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\String_;
|
||||
|
||||
final class VarFactoryTest extends TagFactoryTestCase
|
||||
{
|
||||
/**
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory::create
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory::supports
|
||||
*/
|
||||
public function testParamIsCreated(): void
|
||||
{
|
||||
$ast = $this->parseTag('@var string $var');
|
||||
$factory = new VarFactory($this->giveTypeFactory(), $this->givenDescriptionFactory());
|
||||
$context = new Context('global');
|
||||
|
||||
self::assertTrue($factory->supports($ast, $context));
|
||||
self::assertEquals(
|
||||
new Var_(
|
||||
'var',
|
||||
new String_(),
|
||||
new Description('')
|
||||
),
|
||||
$factory->create($ast, $context)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user