Skip to content

Commit 29173be

Browse files
committed
Add reducers to factories to support attributes
To make it easier to add reused paths reducers are introduced. These will allow us to move steps in the production of elements to a separate class that will make it easier to reuse the logic between factories.
1 parent 99926d6 commit 29173be

32 files changed

+270
-43
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Reflection\Php;
6+
7+
use phpDocumentor\Reflection\Element;
8+
use phpDocumentor\Reflection\Fqsen;
9+
10+
final class Attribute implements Element
11+
{
12+
private Fqsen $fqsen;
13+
14+
/** @var CallArgument[] */
15+
private array $arguments;
16+
17+
/** @param CallArgument[] $arguments */
18+
public function __construct(Fqsen $fqsen, array $arguments)
19+
{
20+
$this->fqsen = $fqsen;
21+
$this->arguments = $arguments;
22+
}
23+
24+
public function getFqsen(): Fqsen
25+
{
26+
return $this->fqsen;
27+
}
28+
29+
/** @return CallArgument[] */
30+
public function getArguments(): array
31+
{
32+
return $this->arguments;
33+
}
34+
35+
public function getName(): string
36+
{
37+
return $this->fqsen->getName();
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Reflection\Php;
6+
7+
interface AttributeContainer
8+
{
9+
public function addAttribute(Attribute $attribute): void;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Reflection\Php;
6+
7+
final class CallArgument
8+
{
9+
private string $value;
10+
11+
private ?string $name;
12+
13+
public function __construct(
14+
string $value,
15+
?string $name = null
16+
) {
17+
$this->value = $value;
18+
$this->name = $name;
19+
}
20+
21+
public function getValue(): string
22+
{
23+
return $this->value;
24+
}
25+
26+
public function getName(): ?string
27+
{
28+
return $this->name;
29+
}
30+
}

src/phpDocumentor/Reflection/Php/Class_.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@
2323
* Descriptor representing a Class.
2424
*/
2525
// @codingStandardsIgnoreStart
26-
final class Class_ implements Element, MetaDataContainerInterface
26+
final class Class_ implements Element, MetaDataContainerInterface, AttributeContainer
2727
// @codingStandardsIgnoreEnd
2828
{
2929
use MetadataContainer;
30+
use HasAttributes;
3031

3132
/** @var Fqsen Full Qualified Structural Element Name */
3233
private Fqsen $fqsen;

src/phpDocumentor/Reflection/Php/Constant.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@
2222
/**
2323
* Descriptor representing a constant
2424
*/
25-
final class Constant implements Element, MetaDataContainerInterface
25+
final class Constant implements Element, MetaDataContainerInterface, AttributeContainer
2626
{
2727
use MetadataContainer;
28+
use HasAttributes;
2829

2930
private Fqsen $fqsen;
3031

src/phpDocumentor/Reflection/Php/EnumCase.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
use phpDocumentor\Reflection\Location;
1111
use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface;
1212

13-
final class EnumCase implements Element, MetaDataContainerInterface
13+
final class EnumCase implements Element, MetaDataContainerInterface, AttributeContainer
1414
{
1515
use MetadataContainer;
16+
use HasAttributes;
1617

1718
private Fqsen $fqsen;
1819

src/phpDocumentor/Reflection/Php/Enum_.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020
use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface;
2121
use phpDocumentor\Reflection\Type;
2222

23-
final class Enum_ implements Element, MetaDataContainerInterface
23+
final class Enum_ implements Element, MetaDataContainerInterface, AttributeContainer
2424
{
2525
use MetadataContainer;
26+
use HasAttributes;
2627

2728
/** @var Fqsen Full Qualified Structural Element Name */
2829
private Fqsen $fqsen;

src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php

+12-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use InvalidArgumentException;
1717
use phpDocumentor\Reflection\DocBlock;
1818
use phpDocumentor\Reflection\DocBlockFactoryInterface;
19+
use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer;
1920
use phpDocumentor\Reflection\Php\ProjectFactoryStrategy;
2021
use phpDocumentor\Reflection\Php\StrategyContainer;
2122
use phpDocumentor\Reflection\Types\Context;
@@ -31,9 +32,14 @@ abstract class AbstractFactory implements ProjectFactoryStrategy
3132
{
3233
private DocBlockFactoryInterface $docBlockFactory;
3334

34-
public function __construct(DocBlockFactoryInterface $docBlockFactory)
35+
/** @var iterable<Reducer> */
36+
private iterable $reducers;
37+
38+
/** @param iterable<Reducer> $recuders */
39+
public function __construct(DocBlockFactoryInterface $docBlockFactory, iterable $recuders = [])
3540
{
3641
$this->docBlockFactory = $docBlockFactory;
42+
$this->reducers = $recuders;
3743
}
3844

3945
/**
@@ -55,7 +61,10 @@ public function create(ContextStack $context, object $object, StrategyContainer
5561
);
5662
}
5763

58-
$this->doCreate($context, $object, $strategies);
64+
$element = $this->doCreate($context, $object, $strategies);
65+
foreach ($this->reducers as $reducer) {
66+
$element = $reducer->reduce($context, $object, $strategies, $element);
67+
}
5968
}
6069

6170
/**
@@ -66,7 +75,7 @@ public function create(ContextStack $context, object $object, StrategyContainer
6675
*
6776
* @param NodeAbstract|object $object object to convert to an Element
6877
*/
69-
abstract protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): void;
78+
abstract protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): ?object;
7079

7180
protected function createDocBlock(?Doc $docBlock = null, ?Context $context = null): ?DocBlock
7281
{

src/phpDocumentor/Reflection/Php/Factory/Argument.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* @see ArgumentDescriptor
3030
* @see \PhpParser\Node\Arg
3131
*/
32-
final class Argument extends AbstractFactory implements ProjectFactoryStrategy
32+
final class Argument implements ProjectFactoryStrategy
3333
{
3434
private PrettyPrinter $valueConverter;
3535

@@ -56,7 +56,7 @@ public function matches(ContextStack $context, object $object): bool
5656
* @param Param $object object to convert to an Element
5757
* @param StrategyContainer $strategies used to convert nested objects.
5858
*/
59-
protected function doCreate(
59+
public function create(
6060
ContextStack $context,
6161
object $object,
6262
StrategyContainer $strategies

src/phpDocumentor/Reflection/Php/Factory/ClassConstant.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ protected function doCreate(
6161
ContextStack $context,
6262
object $object,
6363
StrategyContainer $strategies
64-
): void {
64+
): ?object {
6565
$constantContainer = $context->peek();
6666
Assert::isInstanceOfAny(
6767
$constantContainer,
@@ -86,6 +86,8 @@ protected function doCreate(
8686
$const->isFinal()
8787
));
8888
}
89+
90+
return null;
8991
}
9092

9193
/**

src/phpDocumentor/Reflection/Php/Factory/Class_.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
use phpDocumentor\Reflection\Location;
1818
use phpDocumentor\Reflection\Php\Class_ as ClassElement;
1919
use phpDocumentor\Reflection\Php\File as FileElement;
20-
use phpDocumentor\Reflection\Php\ProjectFactoryStrategy;
2120
use phpDocumentor\Reflection\Php\StrategyContainer;
2221
use PhpParser\Node\Stmt\Class_ as ClassNode;
2322

@@ -26,7 +25,7 @@
2625
/**
2726
* Strategy to create a ClassElement including all sub elements.
2827
*/
29-
final class Class_ extends AbstractFactory implements ProjectFactoryStrategy
28+
final class Class_ extends AbstractFactory
3029
{
3130
public function matches(ContextStack $context, object $object): bool
3231
{
@@ -42,7 +41,7 @@ public function matches(ContextStack $context, object $object): bool
4241
* @param ContextStack $context of the created object
4342
* @param ClassNode $object
4443
*/
45-
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): void
44+
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): ?object
4645
{
4746
$docBlock = $this->createDocBlock($object->getDocComment(), $context->getTypeContext());
4847

@@ -72,5 +71,7 @@ protected function doCreate(ContextStack $context, object $object, StrategyConta
7271
$strategy = $strategies->findMatching($thisContext, $stmt);
7372
$strategy->create($thisContext, $stmt, $strategies);
7473
}
74+
75+
return $classElement;
7576
}
7677
}

src/phpDocumentor/Reflection/Php/Factory/ConstructorPromotion.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function matches(ContextStack $context, object $object): bool
4949
/**
5050
* @param ClassMethod $object
5151
*/
52-
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): void
52+
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): ?object
5353
{
5454
$this->methodStrategy->create($context, $object, $strategies);
5555

@@ -60,6 +60,8 @@ protected function doCreate(ContextStack $context, object $object, StrategyConta
6060

6161
$this->promoteParameterToProperty($context, $param);
6262
}
63+
64+
return $context->peek();
6365
}
6466

6567
private function promoteParameterToProperty(ContextStack $context, Param $param): void

src/phpDocumentor/Reflection/Php/Factory/Define.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -88,23 +88,23 @@ protected function doCreate(
8888
ContextStack $context,
8989
object $object,
9090
StrategyContainer $strategies
91-
): void {
91+
): ?object {
9292
$expression = $object->expr;
9393
assert($expression instanceof FuncCall);
9494

9595
[$name, $value] = $expression->args;
9696

9797
//We cannot calculate the name of a variadic consuming define.
9898
if ($name instanceof VariadicPlaceholder || $value instanceof VariadicPlaceholder) {
99-
return;
99+
return null;
100100
}
101101

102102
$file = $context->search(FileElement::class);
103103
assert($file instanceof FileElement);
104104

105105
$fqsen = $this->determineFqsen($name, $context);
106106
if ($fqsen === null) {
107-
return;
107+
return null;
108108
}
109109

110110
$constant = new ConstantElement(
@@ -116,6 +116,8 @@ protected function doCreate(
116116
);
117117

118118
$file->addConstant($constant);
119+
120+
return $constant;
119121
}
120122

121123
private function determineValue(?Arg $value): ?string

src/phpDocumentor/Reflection/Php/Factory/EnumCase.php

+8-3
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,22 @@ public function matches(ContextStack $context, object $object): bool
3232
/**
3333
* @param EnumCaseNode $object
3434
*/
35-
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): void
35+
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): ?object
3636
{
3737
$docBlock = $this->createDocBlock($object->getDocComment(), $context->getTypeContext());
3838
$enum = $context->peek();
3939
assert($enum instanceof EnumElement);
40-
$enum->addCase(new EnumCaseElement(
40+
41+
$case = new EnumCaseElement(
4142
$object->getAttribute('fqsen'),
4243
$docBlock,
4344
new Location($object->getLine()),
4445
new Location($object->getEndLine()),
4546
$object->expr !== null ? $this->prettyPrinter->prettyPrintExpr($object->expr) : null
46-
));
47+
);
48+
49+
$enum->addCase($case);
50+
51+
return $case;
4752
}
4853
}

src/phpDocumentor/Reflection/Php/Factory/Enum_.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function matches(ContextStack $context, object $object): bool
2929
}
3030

3131
/** @param EnumNode $object */
32-
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): void
32+
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): ?object
3333
{
3434
$docBlock = $this->createDocBlock($object->getDocComment(), $context->getTypeContext());
3535

@@ -56,5 +56,7 @@ protected function doCreate(ContextStack $context, object $object, StrategyConta
5656
$strategy = $strategies->findMatching($thisContext, $stmt);
5757
$strategy->create($thisContext, $stmt, $strategies);
5858
}
59+
60+
return $enum;
5961
}
6062
}

src/phpDocumentor/Reflection/Php/Factory/File.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,19 @@ public function matches(ContextStack $context, object $object): bool
8686
* @param FileSystemFile $object path to the file to convert to an File object.
8787
* @param StrategyContainer $strategies used to convert nested objects.
8888
*/
89-
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): void
89+
protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): ?object
9090
{
9191
$command = new CreateCommand($context, $object, $strategies);
9292
$middlewareChain = $this->middlewareChain;
9393

9494
$file = $middlewareChain($command);
9595
if ($file === null) {
96-
return;
96+
return null;
9797
}
9898

9999
$context->getProject()->addFile($file);
100+
101+
return $file;
100102
}
101103

102104
private function createFile(CreateCommand $command): FileElement

src/phpDocumentor/Reflection/Php/Factory/Function_.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected function doCreate(
4646
ContextStack $context,
4747
object $object,
4848
StrategyContainer $strategies
49-
): void {
49+
): ?object {
5050
$file = $context->peek();
5151
Assert::isInstanceOf($file, FileElement::class);
5252

@@ -68,12 +68,14 @@ protected function doCreate(
6868
}
6969

7070
if (!is_array($object->stmts)) {
71-
return;
71+
return null;
7272
}
7373

7474
foreach ($object->stmts as $stmt) {
7575
$strategy = $strategies->findMatching($thisContext, $stmt);
7676
$strategy->create($thisContext, $stmt, $strategies);
7777
}
78+
79+
return $function;
7880
}
7981
}

0 commit comments

Comments
 (0)