@@ -35,6 +35,9 @@ class ParameterSpecBuilder implements ParameterSpecBuilderInterface
35
35
\s*
36
36
)?
37
37
(?<name>[_a-z]\w*)
38
+ \s*
39
+ (?<nullable>\?)?
40
+ \s*
38
41
(?:
39
42
\s* = \s*
40
43
(?<default>
@@ -86,13 +89,20 @@ public function build(string $definition): ParameterSpecInterface
86
89
}
87
90
88
91
if (preg_match ($ this ->regexp , $ definition , $ matches )) {
92
+
93
+ $ this ->validateDefinition ($ definition , $ matches );
94
+
89
95
try {
90
- if ($ matches[ ' rest ' ] ?? false ) {
96
+ if ($ this -> hasRest ( $ matches) ) {
91
97
return $ this ->buildVariadicParameterSpec ($ matches );
92
98
}
93
99
94
- if ($ matches ['default ' ] ?? false ) {
95
- return $ this ->buildOptionalParameterSpec ($ matches );
100
+ if ($ this ->hasDefault ($ matches )) {
101
+ return $ this ->buildOptionalParameterSpec ($ matches , $ matches ['default ' ]);
102
+ }
103
+
104
+ if ($ this ->hasNullable ($ matches )) {
105
+ return $ this ->buildOptionalParameterSpec ($ matches , null );
96
106
}
97
107
98
108
return $ this ->buildMandatoryParameterSpec ($ matches );
@@ -106,16 +116,14 @@ public function build(string $definition): ParameterSpecInterface
106
116
107
117
protected function buildVariadicParameterSpec (array $ matches ): VariadicParameterSpec
108
118
{
109
- if (isset ($ matches ['default ' ]) && '' !== $ matches ['default ' ]) {
110
- throw new ParameterSpecBuilderException ('Variadic parameter should have no default value ' );
111
- }
112
-
113
119
return new VariadicParameterSpec ($ matches ['name ' ], $ this ->builder ->build ($ matches ['type ' ]));
114
120
}
115
121
116
- protected function buildOptionalParameterSpec (array $ matches ): OptionalParameterSpec
122
+ protected function buildOptionalParameterSpec (array $ matches, ? string $ default ): OptionalParameterSpec
117
123
{
118
- $ default = $ this ->buildDefaultValue ($ matches ['default ' ]);
124
+ if (null !== $ default ) {
125
+ $ default = $ this ->buildDefaultValue ($ matches ['default ' ]);
126
+ }
119
127
120
128
return new OptionalParameterSpec ($ matches ['name ' ], $ this ->builder ->build ($ matches ['type ' ]), $ default );
121
129
}
@@ -166,6 +174,7 @@ protected function buildDefaultValue(string $definition)
166
174
}
167
175
}
168
176
177
+ // UNEXPECTED
169
178
// Less likely we will ever get here because it should fail at a parsing step, but just in case
170
179
throw new ParameterSpecBuilderException ("Unknown default value format ' {$ definition }' " );
171
180
}
@@ -176,4 +185,34 @@ private function wrappedWith(string $definition, string $starts, $ends)
176
185
177
186
return $ starts == $ definition [0 ] && $ ends == $ definition [-1 ];
178
187
}
188
+
189
+ protected function validateDefinition (string $ definition , array $ matches ): void
190
+ {
191
+ if ($ this ->hasNullable ($ matches ) && $ this ->hasRest ($ matches )) {
192
+ throw new ParameterSpecBuilderException ("Variadic parameter could not be nullable " );
193
+ }
194
+
195
+ if ($ this ->hasNullable ($ matches ) && $ this ->hasDefault ($ matches )) {
196
+ throw new ParameterSpecBuilderException ("Nullable parameter could not have default value " );
197
+ }
198
+
199
+ if ($ this ->hasRest ($ matches ) && $ this ->hasDefault ($ matches )) {
200
+ throw new ParameterSpecBuilderException ('Variadic parameter could have no default value ' );
201
+ }
202
+ }
203
+
204
+ private function hasNullable (array $ matches ): bool
205
+ {
206
+ return isset ($ matches ['nullable ' ]) && '' !== $ matches ['nullable ' ];
207
+ }
208
+
209
+ private function hasRest (array $ matches ): bool
210
+ {
211
+ return isset ($ matches ['rest ' ]) && '' !== $ matches ['rest ' ];
212
+ }
213
+
214
+ private function hasDefault (array $ matches ): bool
215
+ {
216
+ return isset ($ matches ['default ' ]) && '' !== $ matches ['default ' ];
217
+ }
179
218
}
0 commit comments