mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Add method support
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
<?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\Method;
|
||||||
|
use phpDocumentor\Reflection\DocBlock\Tags\MethodParameter;
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
use phpDocumentor\Reflection\Types\Context;
|
||||||
|
use phpDocumentor\Reflection\Types\Void_;
|
||||||
|
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;
|
||||||
|
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueParameterNode;
|
||||||
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||||
|
use Webmozart\Assert\Assert;
|
||||||
|
|
||||||
|
use function array_map;
|
||||||
|
use function trim;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal This class is not part of the BC promise of this library.
|
||||||
|
*/
|
||||||
|
final class MethodFactory 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, MethodTagValueNode::class);
|
||||||
|
|
||||||
|
return new Method(
|
||||||
|
$tagValue->methodName,
|
||||||
|
[],
|
||||||
|
$this->createReturnType($tagValue, $context),
|
||||||
|
$tagValue->isStatic,
|
||||||
|
$this->descriptionFactory->create($tagValue->description, $context),
|
||||||
|
false,
|
||||||
|
array_map(
|
||||||
|
function (MethodTagValueParameterNode $param) use ($context) {
|
||||||
|
return new MethodParameter(
|
||||||
|
trim($param->parameterName, '$'),
|
||||||
|
$this->typeFactory->createType($param->type, $context),
|
||||||
|
$param->isReference,
|
||||||
|
$param->isVariadic,
|
||||||
|
(string) $param->defaultValue
|
||||||
|
);
|
||||||
|
},
|
||||||
|
$tagValue->parameters
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supports(PhpDocTagNode $node, ?Context $context): bool
|
||||||
|
{
|
||||||
|
return $node->value instanceof MethodTagValueNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createReturnType(MethodTagValueNode $tagValue, ?Context $context): Type
|
||||||
|
{
|
||||||
|
return $this->typeFactory->createType($tagValue->returnType, $context) ?? new Void_();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,8 +54,12 @@ final class TypeFactory
|
|||||||
$this->resolver = $resolver;
|
$this->resolver = $resolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createType(TypeNode $type, ?Context $context): ?Type
|
public function createType(?TypeNode $type, ?Context $context): ?Type
|
||||||
{
|
{
|
||||||
|
if ($type === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
switch (get_class($type)) {
|
switch (get_class($type)) {
|
||||||
case ArrayTypeNode::class:
|
case ArrayTypeNode::class:
|
||||||
return new Array_(
|
return new Array_(
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ use phpDocumentor\Reflection\Types\Void_;
|
|||||||
use Webmozart\Assert\Assert;
|
use Webmozart\Assert\Assert;
|
||||||
|
|
||||||
use function array_keys;
|
use function array_keys;
|
||||||
|
use function array_map;
|
||||||
use function explode;
|
use function explode;
|
||||||
use function implode;
|
use function implode;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
@@ -63,6 +64,9 @@ final class Method extends BaseTag implements Factory\StaticMethod
|
|||||||
/** @var bool */
|
/** @var bool */
|
||||||
private $returnsReference;
|
private $returnsReference;
|
||||||
|
|
||||||
|
/** @var MethodParameter[] */
|
||||||
|
private array $parameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<int, array<string, Type|string>> $arguments
|
* @param array<int, array<string, Type|string>> $arguments
|
||||||
* @phpstan-param array<int, array{name: string, type: Type}|string> $arguments
|
* @phpstan-param array<int, array{name: string, type: Type}|string> $arguments
|
||||||
@@ -73,7 +77,8 @@ final class Method extends BaseTag implements Factory\StaticMethod
|
|||||||
?Type $returnType = null,
|
?Type $returnType = null,
|
||||||
bool $static = false,
|
bool $static = false,
|
||||||
?Description $description = null,
|
?Description $description = null,
|
||||||
bool $returnsReference = false
|
bool $returnsReference = false,
|
||||||
|
?array $parameters = null
|
||||||
) {
|
) {
|
||||||
Assert::stringNotEmpty($methodName);
|
Assert::stringNotEmpty($methodName);
|
||||||
|
|
||||||
@@ -81,12 +86,15 @@ final class Method extends BaseTag implements Factory\StaticMethod
|
|||||||
$returnType = new Void_();
|
$returnType = new Void_();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$arguments = $this->filterArguments($arguments);
|
||||||
|
|
||||||
$this->methodName = $methodName;
|
$this->methodName = $methodName;
|
||||||
$this->arguments = $this->filterArguments($arguments);
|
$this->arguments = $arguments;
|
||||||
$this->returnType = $returnType;
|
$this->returnType = $returnType;
|
||||||
$this->isStatic = $static;
|
$this->isStatic = $static;
|
||||||
$this->description = $description;
|
$this->description = $description;
|
||||||
$this->returnsReference = $returnsReference;
|
$this->returnsReference = $returnsReference;
|
||||||
|
$this->parameters = $parameters ?? $this->fromLegacyArguments($arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function create(
|
public static function create(
|
||||||
@@ -190,7 +198,14 @@ final class Method extends BaseTag implements Factory\StaticMethod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new static($methodName, $arguments, $returnType, $static, $description, $returnsReference);
|
return new static(
|
||||||
|
$methodName,
|
||||||
|
$arguments,
|
||||||
|
$returnType,
|
||||||
|
$static,
|
||||||
|
$description,
|
||||||
|
$returnsReference
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,6 +225,12 @@ final class Method extends BaseTag implements Factory\StaticMethod
|
|||||||
return $this->arguments;
|
return $this->arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return MethodParameter[] */
|
||||||
|
public function getParameters(): array
|
||||||
|
{
|
||||||
|
return $this->parameters;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the method tag describes a static method or not.
|
* Checks whether the method tag describes a static method or not.
|
||||||
*
|
*
|
||||||
@@ -233,8 +254,11 @@ final class Method extends BaseTag implements Factory\StaticMethod
|
|||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
$arguments = [];
|
$arguments = [];
|
||||||
foreach ($this->arguments as $argument) {
|
foreach ($this->parameters as $parameter) {
|
||||||
$arguments[] = $argument['type'] . ' $' . $argument['name'];
|
$arguments[] = ($parameter->getType() ?? new Mixed_()) . ' ' .
|
||||||
|
($parameter->isReference() ? '&' : '') .
|
||||||
|
($parameter->isVariadic() ? '...' : '') .
|
||||||
|
'$' . $parameter->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
$argumentStr = '(' . implode(', ', $arguments) . ')';
|
$argumentStr = '(' . implode(', ', $arguments) . ')';
|
||||||
@@ -301,4 +325,26 @@ final class Method extends BaseTag implements Factory\StaticMethod
|
|||||||
|
|
||||||
return $argument;
|
return $argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array{name: string, type: Type} $arguments
|
||||||
|
* @return MethodParameter[]
|
||||||
|
*/
|
||||||
|
private function fromLegacyArguments(array $arguments): array
|
||||||
|
{
|
||||||
|
trigger_error(
|
||||||
|
'Create method parameters via legacy format is deprecated add parameters via the constructor',
|
||||||
|
E_USER_DEPRECATED
|
||||||
|
);
|
||||||
|
|
||||||
|
return array_map(
|
||||||
|
static function ($arg) {
|
||||||
|
return new MethodParameter(
|
||||||
|
$arg['name'],
|
||||||
|
$arg['type']
|
||||||
|
);
|
||||||
|
},
|
||||||
|
$arguments
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
use phpDocumentor\Reflection\Type;
|
||||||
|
|
||||||
|
final class MethodParameter
|
||||||
|
{
|
||||||
|
/** @var Type */
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $isReference;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $isVariadic;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $defaultValue;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
string $name,
|
||||||
|
Type $type,
|
||||||
|
bool $isReference = false,
|
||||||
|
bool $isVariadic = false,
|
||||||
|
?string $defaultValue = null
|
||||||
|
) {
|
||||||
|
$this->type = $type;
|
||||||
|
$this->isReference = $isReference;
|
||||||
|
$this->isVariadic = $isVariadic;
|
||||||
|
$this->name = $name;
|
||||||
|
$this->defaultValue = $defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getType(): Type
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isReference(): bool
|
||||||
|
{
|
||||||
|
return $this->isReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isVariadic(): bool
|
||||||
|
{
|
||||||
|
return $this->isVariadic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDefaultValue(): ?string
|
||||||
|
{
|
||||||
|
return $this->defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -89,6 +89,7 @@ final class DocBlockFactory implements DocBlockFactoryInterface
|
|||||||
$tagFactory->registerTagHandler('property', $phpstanTagFactory);
|
$tagFactory->registerTagHandler('property', $phpstanTagFactory);
|
||||||
$tagFactory->registerTagHandler('property-read', $phpstanTagFactory);
|
$tagFactory->registerTagHandler('property-read', $phpstanTagFactory);
|
||||||
$tagFactory->registerTagHandler('property-write', $phpstanTagFactory);
|
$tagFactory->registerTagHandler('property-write', $phpstanTagFactory);
|
||||||
|
$tagFactory->registerTagHandler('method', $phpstanTagFactory);
|
||||||
|
|
||||||
$docBlockFactory = new self($descriptionFactory, $tagFactory);
|
$docBlockFactory = new self($descriptionFactory, $tagFactory);
|
||||||
foreach ($additionalTags as $tagName => $tagHandler) {
|
foreach ($additionalTags as $tagName => $tagHandler) {
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
<?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\Method;
|
||||||
|
use phpDocumentor\Reflection\DocBlock\Tags\MethodParameter;
|
||||||
|
use phpDocumentor\Reflection\Types\Context;
|
||||||
|
use phpDocumentor\Reflection\Types\Integer;
|
||||||
|
use phpDocumentor\Reflection\Types\String_;
|
||||||
|
use phpDocumentor\Reflection\Types\Void_;
|
||||||
|
|
||||||
|
final class MethodFactoryTest extends TagFactoryTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\MethodFactory::__construct
|
||||||
|
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\MethodFactory::create
|
||||||
|
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\MethodFactory::supports
|
||||||
|
* @dataProvider tagProvider
|
||||||
|
*/
|
||||||
|
public function testIsCreated(string $tagLine, Method $tag): void
|
||||||
|
{
|
||||||
|
$ast = $this->parseTag($tagLine);
|
||||||
|
$factory = new MethodFactory($this->giveTypeFactory(), $this->givenDescriptionFactory());
|
||||||
|
$context = new Context('global');
|
||||||
|
|
||||||
|
self::assertTrue($factory->supports($ast, $context));
|
||||||
|
self::assertEquals(
|
||||||
|
$tag,
|
||||||
|
$factory->create($ast, $context)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return array<array<string|Method>> */
|
||||||
|
public function tagProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'@method static string myMethod()',
|
||||||
|
new Method(
|
||||||
|
'myMethod',
|
||||||
|
[],
|
||||||
|
new String_(),
|
||||||
|
true,
|
||||||
|
new Description(''),
|
||||||
|
false,
|
||||||
|
[]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@method string myMethod()',
|
||||||
|
new Method(
|
||||||
|
'myMethod',
|
||||||
|
[],
|
||||||
|
new String_(),
|
||||||
|
false,
|
||||||
|
new Description(''),
|
||||||
|
false,
|
||||||
|
[]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@method myMethod()',
|
||||||
|
new Method(
|
||||||
|
'myMethod',
|
||||||
|
[],
|
||||||
|
new Void_(),
|
||||||
|
false,
|
||||||
|
new Description(''),
|
||||||
|
false,
|
||||||
|
[]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@method myMethod(int $a = 1)',
|
||||||
|
new Method(
|
||||||
|
'myMethod',
|
||||||
|
[],
|
||||||
|
new Void_(),
|
||||||
|
false,
|
||||||
|
new Description(''),
|
||||||
|
false,
|
||||||
|
[new MethodParameter('a', new Integer(), false, false, '1')]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@method myMethod(int ...$a)',
|
||||||
|
new Method(
|
||||||
|
'myMethod',
|
||||||
|
[],
|
||||||
|
new Void_(),
|
||||||
|
false,
|
||||||
|
new Description(''),
|
||||||
|
false,
|
||||||
|
[new MethodParameter('a', new Integer(), false, true)]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@method myMethod(int &$a, string $b)',
|
||||||
|
new Method(
|
||||||
|
'myMethod',
|
||||||
|
[],
|
||||||
|
new Void_(),
|
||||||
|
false,
|
||||||
|
new Description(''),
|
||||||
|
false,
|
||||||
|
[
|
||||||
|
new MethodParameter('a', new Integer(), true, false),
|
||||||
|
new MethodParameter('b', new String_(), false, false),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user