Skip to content

Commit 8099cda

Browse files
[Config] Add generics on the config builder API
1 parent a6f969d commit 8099cda

19 files changed

+261
-59
lines changed

src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,40 @@
1919
/**
2020
* This class provides a fluent interface for defining an array node.
2121
*
22+
* @template TParent of NodeParentInterface|null
23+
*
24+
* @extends NodeDefinition<TParent>
25+
*
2226
* @author Johannes M. Schmitt <[email protected]>
2327
*/
2428
class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface
2529
{
2630
protected bool $performDeepMerging = true;
2731
protected bool $ignoreExtraKeys = false;
2832
protected bool $removeExtraKeys = true;
33+
/**
34+
* @var NodeDefinition<$this>[]
35+
*/
2936
protected array $children = [];
37+
/**
38+
* @var NodeDefinition<$this>
39+
*/
3040
protected NodeDefinition $prototype;
3141
protected bool $atLeastOne = false;
3242
protected bool $allowNewKeys = true;
3343
protected ?string $key = null;
3444
protected bool $removeKeyItem = false;
3545
protected bool $addDefaults = false;
3646
protected int|string|array|false|null $addDefaultChildren = false;
47+
/**
48+
* @var NodeBuilder<static>
49+
*/
3750
protected NodeBuilder $nodeBuilder;
3851
protected bool $normalizeKeys = true;
3952

53+
/**
54+
* @param TParent $parent
55+
*/
4056
public function __construct(?string $name, ?NodeParentInterface $parent = null)
4157
{
4258
parent::__construct($name, $parent);
@@ -45,18 +61,27 @@ public function __construct(?string $name, ?NodeParentInterface $parent = null)
4561
$this->trueEquivalent = [];
4662
}
4763

64+
/**
65+
* @return $this
66+
*/
4867
public function defaultValue(mixed $value): static
4968
{
5069
$this->nullEquivalent = null === $value ? null : [];
5170

5271
return parent::defaultValue($value);
5372
}
5473

74+
/**
75+
* @param NodeBuilder<static> $builder
76+
*/
5577
public function setBuilder(NodeBuilder $builder): void
5678
{
5779
$this->nodeBuilder = $builder;
5880
}
5981

82+
/**
83+
* @return NodeBuilder<static>
84+
*/
6085
public function children(): NodeBuilder
6186
{
6287
return $this->getNodeBuilder();
@@ -70,57 +95,81 @@ public function children(): NodeBuilder
7095
* @param T $type
7196
*
7297
* @return (
73-
* T is 'array' ? ArrayNodeDefinition
74-
* : (T is 'variable' ? VariableNodeDefinition
75-
* : (T is 'scalar' ? ScalarNodeDefinition
76-
* : (T is 'string' ? StringNodeDefinition
77-
* : (T is 'boolean' ? BooleanNodeDefinition
78-
* : (T is 'integer' ? IntegerNodeDefinition
79-
* : (T is 'float' ? FloatNodeDefinition
80-
* : (T is 'enum' ? EnumNodeDefinition
81-
* : NodeDefinition)))))))
98+
* T is 'array' ? ArrayNodeDefinition<$this>
99+
* : (T is 'variable' ? VariableNodeDefinition<$this>
100+
* : (T is 'scalar' ? ScalarNodeDefinition<$this>
101+
* : (T is 'string' ? StringNodeDefinition<$this>
102+
* : (T is 'boolean' ? BooleanNodeDefinition<$this>
103+
* : (T is 'integer' ? IntegerNodeDefinition<$this>
104+
* : (T is 'float' ? FloatNodeDefinition<$this>
105+
* : (T is 'enum' ? EnumNodeDefinition<$this>
106+
* : NodeDefinition<$this>)))))))
82107
* )
83108
*/
84109
public function prototype(string $type): NodeDefinition
85110
{
86111
return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
87112
}
88113

114+
/**
115+
* @return VariableNodeDefinition<$this>
116+
*/
89117
public function variablePrototype(): VariableNodeDefinition
90118
{
91119
return $this->prototype('variable');
92120
}
93121

122+
/**
123+
* @return ScalarNodeDefinition<$this>
124+
*/
94125
public function scalarPrototype(): ScalarNodeDefinition
95126
{
96127
return $this->prototype('scalar');
97128
}
98129

130+
/**
131+
* @return StringNodeDefinition<$this>
132+
*/
99133
public function stringPrototype(): StringNodeDefinition
100134
{
101135
return $this->prototype('string');
102136
}
103137

138+
/**
139+
* @return BooleanNodeDefinition<$this>
140+
*/
104141
public function booleanPrototype(): BooleanNodeDefinition
105142
{
106143
return $this->prototype('boolean');
107144
}
108145

146+
/**
147+
* @return IntegerNodeDefinition<$this>
148+
*/
109149
public function integerPrototype(): IntegerNodeDefinition
110150
{
111151
return $this->prototype('integer');
112152
}
113153

154+
/**
155+
* @return FloatNodeDefinition<$this>
156+
*/
114157
public function floatPrototype(): FloatNodeDefinition
115158
{
116159
return $this->prototype('float');
117160
}
118161

162+
/**
163+
* @return self<$this>
164+
*/
119165
public function arrayPrototype(): self
120166
{
121167
return $this->prototype('array');
122168
}
123169

170+
/**
171+
* @return EnumNodeDefinition<$this>
172+
*/
124173
public function enumPrototype(): EnumNodeDefinition
125174
{
126175
return $this->prototype('enum');
@@ -377,6 +426,8 @@ public function append(NodeDefinition $node): static
377426

378427
/**
379428
* Returns a node builder to be used to add children and prototype.
429+
*
430+
* @return NodeBuilder<static>
380431
*/
381432
protected function getNodeBuilder(): NodeBuilder
382433
{
@@ -423,7 +474,7 @@ protected function createNode(): NodeInterface
423474

424475
if (false !== $this->addDefaultChildren) {
425476
$node->setAddChildrenIfNoneSet($this->addDefaultChildren);
426-
if ($this->prototype instanceof static && !isset($this->prototype->prototype)) {
477+
if ($this->prototype instanceof self && !isset($this->prototype->prototype)) {
427478
$this->prototype->addDefaultsIfNotSet();
428479
}
429480
}
@@ -522,7 +573,7 @@ protected function validatePrototypeNode(PrototypedArrayNode $node): void
522573
}
523574

524575
/**
525-
* @return NodeDefinition[]
576+
* @return NodeDefinition<$this>[]
526577
*/
527578
public function getChildNodeDefinitions(): array
528579
{

src/Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,24 @@
1717
/**
1818
* This class provides a fluent interface for defining a node.
1919
*
20+
* @template TParent of NodeParentInterface|null
21+
*
22+
* @extends ScalarNodeDefinition<TParent>
23+
*
2024
* @author Johannes M. Schmitt <[email protected]>
2125
*/
2226
class BooleanNodeDefinition extends ScalarNodeDefinition
2327
{
28+
/**
29+
* @param TParent $parent
30+
*/
2431
public function __construct(?string $name, ?NodeParentInterface $parent = null)
2532
{
2633
parent::__construct($name, $parent);
2734

2835
$this->nullEquivalent = true;
2936
}
3037

31-
/**
32-
* Instantiate a Node.
33-
*/
3438
protected function instantiateNode(): BooleanNode
3539
{
3640
return new BooleanNode($this->name, $this->parent, $this->pathSeparator, null === $this->nullEquivalent);
@@ -44,6 +48,9 @@ public function cannotBeEmpty(): static
4448
throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to BooleanNodeDefinition.');
4549
}
4650

51+
/**
52+
* @return $this
53+
*/
4754
public function defaultValue(mixed $value): static
4855
{
4956
$this->nullEquivalent = null === $value ? null : true;

src/Symfony/Component/Config/Definition/Builder/BuilderAwareInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ interface BuilderAwareInterface
2020
{
2121
/**
2222
* Sets a custom children builder.
23+
*
24+
* @param NodeBuilder<static> $builder
2325
*/
2426
public function setBuilder(NodeBuilder $builder): void;
2527
}

src/Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
/**
1717
* Enum Node Definition.
1818
*
19+
* @template TParent of NodeParentInterface|null
20+
*
21+
* @extends ScalarNodeDefinition<TParent>
22+
*
1923
* @author Johannes M. Schmitt <[email protected]>
2024
*/
2125
class EnumNodeDefinition extends ScalarNodeDefinition
@@ -54,9 +58,7 @@ public function enumFqcn(string $enumFqcn): static
5458
}
5559

5660
/**
57-
* Instantiate a Node.
58-
*
59-
* @throws \RuntimeException
61+
* @throws \RuntimeException when no values or enumFqcn is set
6062
*/
6163
protected function instantiateNode(): EnumNode
6264
{

src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
/**
1717
* This class builds an if expression.
1818
*
19+
* @template T of NodeDefinition
20+
*
1921
* @author Johannes M. Schmitt <[email protected]>
2022
* @author Christophe Coevoet <[email protected]>
2123
*/
@@ -30,6 +32,9 @@ class ExprBuilder
3032
public ?\Closure $ifPart = null;
3133
public ?\Closure $thenPart = null;
3234

35+
/**
36+
* @param T $node
37+
*/
3338
public function __construct(
3439
protected NodeDefinition $node,
3540
) {
@@ -231,9 +236,11 @@ public function thenUnset(): static
231236
/**
232237
* Returns the related node.
233238
*
239+
* @return T
240+
*
234241
* @throws \RuntimeException
235242
*/
236-
public function end(): NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition
243+
public function end(): NodeDefinition
237244
{
238245
if (null === $this->ifPart) {
239246
throw new \RuntimeException('You must specify an if part.');
@@ -248,7 +255,9 @@ public function end(): NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition
248255
/**
249256
* Builds the expressions.
250257
*
251-
* @param ExprBuilder[] $expressions An array of ExprBuilder instances to build
258+
* @param (ExprBuilder|\Closure)[] $expressions
259+
*
260+
* @return \Closure[]
252261
*/
253262
public static function buildExpressions(array $expressions): array
254263
{

src/Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
/**
1717
* This class provides a fluent interface for defining a float node.
1818
*
19+
* @template TParent of NodeParentInterface|null
20+
*
21+
* @extends NumericNodeDefinition<TParent>
22+
*
1923
* @author Jeanmonod David <[email protected]>
2024
*/
2125
class FloatNodeDefinition extends NumericNodeDefinition
2226
{
23-
/**
24-
* Instantiates a Node.
25-
*/
2627
protected function instantiateNode(): FloatNode
2728
{
2829
return new FloatNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator);

src/Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
/**
1717
* This class provides a fluent interface for defining an integer node.
1818
*
19+
* @template TParent of NodeParentInterface|null
20+
*
21+
* @extends NumericNodeDefinition<TParent>
22+
*
1923
* @author Jeanmonod David <[email protected]>
2024
*/
2125
class IntegerNodeDefinition extends NumericNodeDefinition
2226
{
23-
/**
24-
* Instantiates a Node.
25-
*/
2627
protected function instantiateNode(): IntegerNode
2728
{
2829
return new IntegerNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator);

src/Symfony/Component/Config/Definition/Builder/MergeBuilder.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@
1414
/**
1515
* This class builds merge conditions.
1616
*
17+
* @template T of NodeDefinition
18+
*
1719
* @author Johannes M. Schmitt <[email protected]>
1820
*/
1921
class MergeBuilder
2022
{
2123
public bool $allowFalse = false;
2224
public bool $allowOverwrite = true;
2325

26+
/**
27+
* @param T $node
28+
*/
2429
public function __construct(
2530
protected NodeDefinition $node,
2631
) {
@@ -52,8 +57,10 @@ public function denyOverwrite(bool $deny = true): static
5257

5358
/**
5459
* Returns the related node.
60+
*
61+
* @return T
5562
*/
56-
public function end(): NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition
63+
public function end(): NodeDefinition
5764
{
5865
return $this->node;
5966
}

0 commit comments

Comments
 (0)