Skip to content

Commit 5112cf3

Browse files
authored
Merge pull request #477 from phpDocumentor/attribute-reducers
Add reducers to factories to support attributes
2 parents 99926d6 + 659a9a8 commit 5112cf3

32 files changed

+282
-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)