Skip to content

Commit 2cb3adf

Browse files
mvrieljaapio
authored andcommitted
Started reworking expression strings into Expression objects
Values of constants, named arguments, etc, should be parsed to include types and FQSENs that can be used in phpDocumentor to display links with. Since these are now simple strings, I have refactored this into a template string system with placeholder values that a consumer could replace with its own values.
1 parent d91b327 commit 2cb3adf

File tree

15 files changed

+283
-28
lines changed

15 files changed

+283
-28
lines changed

src/phpDocumentor/Reflection/Php/Argument.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function __construct(
3434
private readonly string $name,
3535
Type|null $type = null,
3636
/** @var string|null the default value for an argument or null if none is provided */
37-
private readonly string|null $default = null,
37+
private Expression|string|null $default = null,
3838
/** @var bool whether the argument passes the parameter by reference instead of by value */
3939
private readonly bool $byReference = false,
4040
/** @var bool Determines if this Argument represents a variadic argument */
@@ -44,6 +44,15 @@ public function __construct(
4444
$type = new Mixed_();
4545
}
4646

47+
if (is_string($this->default)) {
48+
trigger_error(
49+
'Default values for arguments should be of type Expression, support for strings will be '
50+
. 'removed in 7.x',
51+
E_USER_DEPRECATED
52+
);
53+
$this->default = new Expression($this->default, []);
54+
}
55+
4756
$this->type = $type;
4857
}
4958

@@ -60,8 +69,18 @@ public function getType(): Type|null
6069
return $this->type;
6170
}
6271

63-
public function getDefault(): string|null
72+
/** */
73+
public function getDefault(bool $asString = true): string|null
6474
{
75+
if ($asString) {
76+
trigger_error(
77+
'The Default value will become of type Expression by default',
78+
E_USER_DEPRECATED
79+
);
80+
81+
return (string) $this->default;
82+
}
83+
6584
return $this->default;
6685
}
6786

src/phpDocumentor/Reflection/Php/Constant.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ final class Constant implements Element, MetaDataContainerInterface, AttributeCo
4242
public function __construct(
4343
private readonly Fqsen $fqsen,
4444
private readonly DocBlock|null $docBlock = null,
45-
private readonly string|null $value = null,
45+
private Expression|string|null $value = null,
4646
Location|null $location = null,
4747
Location|null $endLocation = null,
4848
Visibility|null $visibility = null,
@@ -51,13 +51,31 @@ public function __construct(
5151
$this->location = $location ?: new Location(-1);
5252
$this->endLocation = $endLocation ?: new Location(-1);
5353
$this->visibility = $visibility ?: new Visibility(Visibility::PUBLIC_);
54+
55+
if (is_string($this->value)) {
56+
trigger_error(
57+
'Constant values should be of type Expression, support for strings will be '
58+
. 'removed in 6.x',
59+
E_USER_DEPRECATED
60+
);
61+
$this->value = new Expression($this->value, []);
62+
}
5463
}
5564

5665
/**
57-
* Returns the value of this constant.
66+
* Returns the expression value for this constant.
5867
*/
59-
public function getValue(): string|null
68+
public function getValue(bool $asString = true): Expression|string|null
6069
{
70+
if ($asString) {
71+
trigger_error(
72+
'The expression value will become of type Expression by default',
73+
E_USER_DEPRECATED
74+
);
75+
76+
return (string) $this->value;
77+
}
78+
6179
return $this->value;
6280
}
6381

src/phpDocumentor/Reflection/Php/EnumCase.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function __construct(
3030
private readonly DocBlock|null $docBlock,
3131
Location|null $location = null,
3232
Location|null $endLocation = null,
33-
private readonly string|null $value = null,
33+
private Expression|string|null $value = null,
3434
) {
3535
if ($location === null) {
3636
$location = new Location(-1);
@@ -42,6 +42,14 @@ public function __construct(
4242

4343
$this->location = $location;
4444
$this->endLocation = $endLocation;
45+
if (is_string($this->value)) {
46+
trigger_error(
47+
'Expression values for enum cases should be of type Expression, support for strings will be '
48+
. 'removed in 7.x',
49+
E_USER_DEPRECATED
50+
);
51+
$this->value = new Expression($this->value, []);
52+
}
4553
}
4654

4755
#[Override]
@@ -71,8 +79,20 @@ public function getEndLocation(): Location
7179
return $this->endLocation;
7280
}
7381

74-
public function getValue(): string|null
82+
/**
83+
* Returns the value for this enum case.
84+
*/
85+
public function getValue(bool $asString = true): Expression|string|null
7586
{
87+
if ($asString) {
88+
trigger_error(
89+
'The enum case value will become of type Expression by default',
90+
E_USER_DEPRECATED
91+
);
92+
93+
return (string) $this->value;
94+
}
95+
7696
return $this->value;
7797
}
7898
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Reflection\Php;
6+
7+
use phpDocumentor\Reflection\Fqsen;
8+
use phpDocumentor\Reflection\Type;
9+
10+
final class Expression
11+
{
12+
private string $expression;
13+
14+
/** @var array<string, Fqsen|Type> */
15+
private array $parts;
16+
17+
public function __construct(string $expression, array $parts)
18+
{
19+
$this->expression = $expression;
20+
$this->parts = $parts;
21+
}
22+
23+
public function getExpression(): string
24+
{
25+
return $this->expression;
26+
}
27+
28+
public function getParts(): array
29+
{
30+
return $this->parts;
31+
}
32+
33+
public function __toString(): string
34+
{
35+
$valuesAsStrings = array_map(
36+
static fn(object $part): string => (string)$part,
37+
$this->parts
38+
);
39+
40+
return str_replace(array_keys($this->parts), $valuesAsStrings, $this->expression);
41+
}
42+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Reflection\Php\Expression;
6+
7+
use phpDocumentor\Reflection\Fqsen;
8+
use PhpParser\Node\Name;
9+
use PhpParser\PrettyPrinter\Standard;
10+
11+
final class ExpressionPrinter extends Standard
12+
{
13+
/**
14+
* @var array<Fqsen>
15+
*/
16+
private array $parts = [];
17+
18+
protected function resetState(): void
19+
{
20+
parent::resetState();
21+
22+
$this->parts = [];
23+
}
24+
25+
protected function pName(Name $node): string
26+
{
27+
$renderedName = parent::pName($node);
28+
$code = md5($renderedName);
29+
30+
$placeholder = '{{ PHPDOC' . $code . ' }}';
31+
$this->parts[$placeholder] = new Fqsen('\\' . $node);
32+
33+
return $placeholder;
34+
}
35+
36+
/**
37+
* @return array<Fqsen>
38+
*/
39+
public function getParts(): array
40+
{
41+
return $this->parts;
42+
}
43+
}

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

Whitespace-only changes.

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
use phpDocumentor\Reflection\Php\Constant as ConstantElement;
2121
use phpDocumentor\Reflection\Php\Enum_;
2222
use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer;
23+
use phpDocumentor\Reflection\Php\Expression;
24+
use phpDocumentor\Reflection\Php\Expression\ExpressionPrinter;
2325
use phpDocumentor\Reflection\Php\Interface_;
2426
use phpDocumentor\Reflection\Php\StrategyContainer;
2527
use phpDocumentor\Reflection\Php\Trait_;
@@ -84,7 +86,7 @@ protected function doCreate(
8486
$constant = new ConstantElement(
8587
$const->getFqsen(),
8688
$this->createDocBlock($const->getDocComment(), $context->getTypeContext()),
87-
$const->getValue() !== null ? $this->valueConverter->prettyPrintExpr($const->getValue()) : null,
89+
$this->determineValue($const),
8890
new Location($const->getLine()),
8991
new Location($const->getEndLine()),
9092
$this->buildVisibility($const),
@@ -105,6 +107,19 @@ protected function doCreate(
105107
return null;
106108
}
107109

110+
private function determineValue(ClassConstantIterator $value): null|Expression
111+
{
112+
$expression = $value->getValue() !== null ? $this->valueConverter->prettyPrintExpr($value->getValue()) : null;
113+
if ($this->valueConverter instanceof ExpressionPrinter) {
114+
$expression = new Expression($expression, $this->valueConverter->getParts());
115+
}
116+
if (is_string($expression)) {
117+
$expression = new Expression($expression, []);
118+
}
119+
120+
return $expression;
121+
}
122+
108123
/**
109124
* Converts the visibility of the constant to a valid Visibility object.
110125
*/

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
use phpDocumentor\Reflection\Fqsen;
1919
use phpDocumentor\Reflection\Location;
2020
use phpDocumentor\Reflection\Php\Constant as ConstantElement;
21+
use phpDocumentor\Reflection\Php\Expression as ValueExpression;
22+
use phpDocumentor\Reflection\Php\Expression\ExpressionPrinter;
2123
use phpDocumentor\Reflection\Php\File as FileElement;
2224
use phpDocumentor\Reflection\Php\StrategyContainer;
2325
use phpDocumentor\Reflection\Php\ValueEvaluator\ConstantEvaluator;
@@ -118,13 +120,21 @@ protected function doCreate(
118120
return $constant;
119121
}
120122

121-
private function determineValue(Arg|null $value): string|null
123+
private function determineValue(Arg|null $value): ValueExpression|null
122124
{
123125
if ($value === null) {
124126
return null;
125127
}
126128

127-
return $this->valueConverter->prettyPrintExpr($value->value);
129+
$expression = $value->value !== null ? $this->valueConverter->prettyPrintExpr($value->value) : null;
130+
if ($this->valueConverter instanceof ExpressionPrinter) {
131+
$expression = new ValueExpression($expression, $this->valueConverter->getParts());
132+
}
133+
if (is_string($expression)) {
134+
$expression = new ValueExpression($expression, []);
135+
}
136+
137+
return $expression;
128138
}
129139

130140
private function determineFqsen(Arg $name, ContextStack $context): Fqsen|null

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use phpDocumentor\Reflection\Php\Enum_ as EnumElement;
1111
use phpDocumentor\Reflection\Php\EnumCase as EnumCaseElement;
1212
use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer;
13+
use phpDocumentor\Reflection\Php\Expression;
14+
use phpDocumentor\Reflection\Php\Expression\ExpressionPrinter;
1315
use phpDocumentor\Reflection\Php\StrategyContainer;
1416
use PhpParser\Node\Stmt\EnumCase as EnumCaseNode;
1517
use PhpParser\PrettyPrinter\Standard as PrettyPrinter;
@@ -41,12 +43,17 @@ protected function doCreate(ContextStack $context, object $object, StrategyConta
4143
$enum = $context->peek();
4244
assert($enum instanceof EnumElement);
4345

46+
$value = $object->expr !== null ? $this->prettyPrinter->prettyPrintExpr($object->expr) : null;
47+
if ($this->prettyPrinter instanceof ExpressionPrinter) {
48+
$value = new Expression($value, $this->prettyPrinter->getParts());
49+
}
50+
4451
$case = new EnumCaseElement(
4552
$object->getAttribute('fqsen'),
4653
$docBlock,
4754
new Location($object->getLine()),
4855
new Location($object->getEndLine()),
49-
$object->expr !== null ? $this->prettyPrinter->prettyPrintExpr($object->expr) : null,
56+
$value,
5057
);
5158

5259
$enum->addCase($case);

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
use phpDocumentor\Reflection\DocBlockFactoryInterface;
1818
use phpDocumentor\Reflection\Location;
1919
use phpDocumentor\Reflection\Php\Constant as ConstantElement;
20+
use phpDocumentor\Reflection\Php\Expression;
21+
use phpDocumentor\Reflection\Php\Expression\ExpressionPrinter;
2022
use phpDocumentor\Reflection\Php\File as FileElement;
2123
use phpDocumentor\Reflection\Php\StrategyContainer;
2224
use PhpParser\Node\Stmt\Const_;
@@ -70,7 +72,7 @@ protected function doCreate(
7072
new ConstantElement(
7173
$const->getFqsen(),
7274
$this->createDocBlock($const->getDocComment(), $context->getTypeContext()),
73-
$const->getValue() !== null ? $this->valueConverter->prettyPrintExpr($const->getValue()) : null,
75+
$this->determineValue($const),
7476
new Location($const->getLine()),
7577
new Location($const->getEndLine()),
7678
),
@@ -79,4 +81,17 @@ protected function doCreate(
7981

8082
return null;
8183
}
84+
85+
private function determineValue(GlobalConstantIterator $value): ?Expression
86+
{
87+
$expression = $value->getValue() !== null ? $this->valueConverter->prettyPrintExpr($value->getValue()) : null;
88+
if ($this->valueConverter instanceof ExpressionPrinter) {
89+
$expression = new Expression($expression, $this->valueConverter->getParts());
90+
}
91+
if (is_string($expression)) {
92+
$expression = new Expression($expression, []);
93+
}
94+
95+
return $expression;
96+
}
8297
}

0 commit comments

Comments
 (0)