Skip to content

Commit 25d6965

Browse files
committed
Cleanup and var implementation
1 parent b66b6dc commit 25d6965

File tree

12 files changed

+259
-45
lines changed

12 files changed

+259
-45
lines changed

src/DocBlock/StandardTagFactory.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ final class StandardTagFactory implements TagFactory
7676
public const REGEX_TAGNAME = '[\w\-\_\\\\:]+';
7777

7878
/**
79-
* @var array<class-string<Tag>> An array with a tag as a key, and an
79+
* @var array<class-string<Tag>|Factory> An array with a tag as a key, and an
8080
* FQCN to a class that handles it as an array value.
8181
*/
8282
private $tagHandlerMappings = [
@@ -177,7 +177,7 @@ public function registerTagHandler(string $tagName, $handler): void
177177
}
178178

179179
if (is_object($handler)) {
180-
Assert::implementsInterface($handler, TagFactory::class);
180+
Assert::implementsInterface($handler, Factory::class);
181181
$this->tagHandlerMappings[$tagName] = $handler;
182182

183183
return;
@@ -283,12 +283,12 @@ private function getArgumentsForParametersFromWiring(array $parameters, array $l
283283
}
284284
}
285285

286+
$parameterName = $parameter->getName();
286287
if (isset($locator[$typeHint])) {
287-
$arguments[] = $locator[$typeHint];
288+
$arguments[$parameterName] = $locator[$typeHint];
288289
continue;
289290
}
290291

291-
$parameterName = $parameter->getName();
292292
if (isset($locator[$parameterName])) {
293293
$arguments[$parameterName] = $locator[$parameterName];
294294
continue;

src/DocBlock/Tags/Factory/PHPStanFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
interface PHPStanFactory
1212
{
13-
public function create(PhpDocTagNode $node, Context $context): Tag;
13+
public function create(PhpDocTagNode $node, ?Context $context): Tag;
1414

1515
public function supports(PhpDocTagNode $node, ?Context $context): bool;
1616
}

src/DocBlock/Tags/Factory/ParamFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public function __construct(TypeFactory $typeFactory, DescriptionFactory $descri
2828
$this->descriptionFactory = $descriptionFactory;
2929
}
3030

31-
public function create(PhpDocTagNode $node, Context $context): Tag
31+
public function create(PhpDocTagNode $node, ?Context $context): Tag
3232
{
3333
$tagValue = $node->value;
3434
Assert::isInstanceOf($tagValue, ParamTagValueNode::class);

src/DocBlock/Tags/Factory/TypeFactory.php

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
/**
4545
* @internal This class is not part of the BC promise of this library.
4646
*/
47-
class TypeFactory
47+
final class TypeFactory
4848
{
4949
private TypeResolver $resolver;
5050

@@ -53,7 +53,7 @@ public function __construct(TypeResolver $resolver)
5353
$this->resolver = $resolver;
5454
}
5555

56-
public function createType(TypeNode $type, Context $context): ?Type
56+
public function createType(TypeNode $type, ?Context $context): ?Type
5757
{
5858
switch (get_class($type)) {
5959
case ArrayTypeNode::class:
@@ -77,6 +77,7 @@ public function createType(TypeNode $type, Context $context): ?Type
7777
return $this->createFromCallable($type, $context);
7878

7979
case ConstTypeNode::class:
80+
return null;
8081
case GenericTypeNode::class:
8182
return $this->createFromGeneric($type, $context);
8283

@@ -85,22 +86,29 @@ public function createType(TypeNode $type, Context $context): ?Type
8586

8687
case IntersectionTypeNode::class:
8788
return new Intersection(
88-
array_map(
89-
fn (TypeNode $nestedType) => $this->createType($nestedType, $context),
90-
$type->types
89+
array_filter(
90+
array_map(
91+
fn (TypeNode $nestedType) => $this->createType($nestedType, $context),
92+
$type->types
93+
)
9194
)
9295
);
9396

9497
case NullableTypeNode::class:
95-
return new Nullable(
96-
$this->createType($type->type, $context)
97-
);
98+
$nestedType = $this->createType($type->type, $context);
99+
if ($nestedType === null) {
100+
return null;
101+
}
102+
103+
return new Nullable($nestedType);
98104

99105
case UnionTypeNode::class:
100106
return new Compound(
101-
array_map(
102-
fn (TypeNode $nestedType) => $this->createType($nestedType, $context),
103-
$type->types
107+
array_filter(
108+
array_map(
109+
fn (TypeNode $nestedType) => $this->createType($nestedType, $context),
110+
$type->types
111+
)
104112
)
105113
);
106114

@@ -115,7 +123,7 @@ public function createType(TypeNode $type, Context $context): ?Type
115123
}
116124
}
117125

118-
private function createFromGeneric(GenericTypeNode $type, Context $context): Type
126+
private function createFromGeneric(GenericTypeNode $type, ?Context $context): Type
119127
{
120128
switch (strtolower($type->type->name)) {
121129
case 'array':
@@ -162,7 +170,7 @@ private function createFromGeneric(GenericTypeNode $type, Context $context): Typ
162170
}
163171
}
164172

165-
private function createFromCallable(CallableTypeNode $type, Context $context): Callable_
173+
private function createFromCallable(CallableTypeNode $type, ?Context $context): Callable_
166174
{
167175
return new Callable_();
168176
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
6+
7+
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
8+
use phpDocumentor\Reflection\DocBlock\Tag;
9+
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
10+
use phpDocumentor\Reflection\Types\Context;
11+
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
12+
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
13+
use Webmozart\Assert\Assert;
14+
15+
use function trim;
16+
17+
/**
18+
* @internal This class is not part of the BC promise of this library.
19+
*/
20+
final class VarFactory implements PHPStanFactory
21+
{
22+
private TypeFactory $typeFactory;
23+
private DescriptionFactory $descriptionFactory;
24+
25+
public function __construct(TypeFactory $typeFactory, DescriptionFactory $descriptionFactory)
26+
{
27+
$this->typeFactory = $typeFactory;
28+
$this->descriptionFactory = $descriptionFactory;
29+
}
30+
31+
public function create(PhpDocTagNode $node, ?Context $context): Tag
32+
{
33+
$tagValue = $node->value;
34+
Assert::isInstanceOf($tagValue, VarTagValueNode::class);
35+
36+
return new Var_(
37+
trim($tagValue->variableName, '$'),
38+
$this->typeFactory->createType($tagValue->type, $context),
39+
$this->descriptionFactory->create($tagValue->description, $context)
40+
);
41+
}
42+
43+
public function supports(PhpDocTagNode $node, ?Context $context): bool
44+
{
45+
return $node->value instanceof VarTagValueNode;
46+
}
47+
}

src/DocBlockFactory.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ final class DocBlockFactory implements DocBlockFactoryInterface
4242
/** @var DocBlock\DescriptionFactory */
4343
private $descriptionFactory;
4444

45-
/** @var Factory */
45+
/** @var TagFactory */
4646
private $tagFactory;
4747

4848
/**
4949
* Initializes this factory with the required subcontractors.
5050
*/
51-
public function __construct(DescriptionFactory $descriptionFactory, Factory $tagFactory)
51+
public function __construct(DescriptionFactory $descriptionFactory, TagFactory $tagFactory)
5252
{
5353
$this->descriptionFactory = $descriptionFactory;
5454
$this->tagFactory = $tagFactory;
@@ -57,7 +57,7 @@ public function __construct(DescriptionFactory $descriptionFactory, Factory $tag
5757
/**
5858
* Factory method for easy instantiation.
5959
*
60-
* @param array<string, class-string<Tag>|TagFactory> $additionalTags
60+
* @param array<string, class-string<Tag>|Factory> $additionalTags
6161
*/
6262
public static function createInstance(array $additionalTags = []): self
6363
{
@@ -74,6 +74,7 @@ public static function createInstance(array $additionalTags = []): self
7474
$tagFactory->addService($descriptionFactory);
7575
$tagFactory->addService($typeResolver);
7676
$tagFactory->registerTagHandler('param', $phpstanTagFactory);
77+
$tagFactory->registerTagHandler('var', $phpstanTagFactory);
7778

7879
$docBlockFactory = new self($descriptionFactory, $tagFactory);
7980
foreach ($additionalTags as $tagName => $tagHandler) {
@@ -122,9 +123,9 @@ public function create($docblock, ?Types\Context $context = null, ?Location $loc
122123
}
123124

124125
/**
125-
* @param class-string<Tag> $handler
126+
* @param class-string<Tag>|Factory $handler
126127
*/
127-
public function registerTagHandler(string $tagName, string $handler): void
128+
public function registerTagHandler(string $tagName, $handler): void
128129
{
129130
$this->tagFactory->registerTagHandler($tagName, $handler);
130131
}

src/PseudoTypes/ArrayShapeItem.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use phpDocumentor\Reflection\Type;
88

9+
use phpDocumentor\Reflection\Types\Mixed_;
910
use function sprintf;
1011

1112
final class ArrayShapeItem
@@ -14,10 +15,10 @@ final class ArrayShapeItem
1415
private Type $value;
1516
private bool $optional;
1617

17-
public function __construct(?string $key, Type $value, bool $optional)
18+
public function __construct(?string $key, ?Type $value, bool $optional)
1819
{
1920
$this->key = $key;
20-
$this->value = $value;
21+
$this->value = $value ?? new Mixed_();
2122
$this->optional = $optional;
2223
}
2324

@@ -36,7 +37,7 @@ public function isOptional(): bool
3637
return $this->optional;
3738
}
3839

39-
public function __toString()
40+
public function __toString(): string
4041
{
4142
if ($this->key !== null) {
4243
return sprintf(

tests/unit/Assets/CustomTagFactory.php

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,18 @@
1414
namespace phpDocumentor\Reflection\Assets;
1515

1616
use phpDocumentor\Reflection\DocBlock\Tag;
17-
use phpDocumentor\Reflection\DocBlock\TagFactory;
17+
use phpDocumentor\Reflection\DocBlock\Tags\Factory\Factory;
1818
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
1919
use phpDocumentor\Reflection\Types\Context;
20-
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
2120

22-
class CustomTagFactory implements TagFactory
21+
class CustomTagFactory implements Factory
2322
{
2423
public $class;
2524

26-
public function addParameter(string $name, $value): void
27-
{
28-
// TODO: Implement addParameter() method.
29-
}
30-
3125
public function create(string $tagLine, ?Context $context = null, CustomServiceClass $class = null): Tag
3226
{
3327
$this->class = $class;
3428

3529
return new Generic('custom');
3630
}
37-
38-
public function addService(object $service): void
39-
{
40-
// TODO: Implement addService() method.
41-
}
42-
43-
public function registerTagHandler(string $tagName, string $handler): void
44-
{
45-
// TODO: Implement registerTagHandler() method.
46-
}
4731
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link http://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
15+
16+
use phpDocumentor\Reflection\DocBlock\Description;
17+
use phpDocumentor\Reflection\DocBlock\Tags\Param;
18+
use phpDocumentor\Reflection\Types\Context;
19+
use phpDocumentor\Reflection\Types\String_;
20+
21+
final class ParamFactoryTest extends TagFactoryTestCase
22+
{
23+
/**
24+
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory::__construct
25+
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory::create
26+
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory::supports
27+
*/
28+
public function testParamIsCreated(): void
29+
{
30+
$ast = $this->parseTag('@param string $var');
31+
$factory = new ParamFactory($this->giveTypeFactory(), $this->givenDescriptionFactory());
32+
$context = new Context('global');
33+
34+
self::assertTrue($factory->supports($ast, $context));
35+
self::assertEquals(
36+
new Param(
37+
'var',
38+
new String_(),
39+
false,
40+
new Description(''),
41+
false
42+
),
43+
$factory->create($ast, $context)
44+
);
45+
}
46+
}

0 commit comments

Comments
 (0)