Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Mar 29, 2024. It is now read-only.

Commit d60963f

Browse files
committed
Add shortcut for optional nullable param, closes #5
1 parent 7895d85 commit d60963f

File tree

3 files changed

+91
-10
lines changed

3 files changed

+91
-10
lines changed

‎src/Specs/Builder/ParameterSpecBuilder.php‎

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class ParameterSpecBuilder implements ParameterSpecBuilderInterface
3535
\s*
3636
)?
3737
(?<name>[_a-z]\w*)
38+
\s*
39+
(?<nullable>\?)?
40+
\s*
3841
(?:
3942
\s* = \s*
4043
(?<default>
@@ -86,13 +89,20 @@ public function build(string $definition): ParameterSpecInterface
8689
}
8790

8891
if (preg_match($this->regexp, $definition, $matches)) {
92+
93+
$this->validateDefinition($definition, $matches);
94+
8995
try {
90-
if ($matches['rest'] ?? false) {
96+
if ($this->hasRest($matches)) {
9197
return $this->buildVariadicParameterSpec($matches);
9298
}
9399

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);
96106
}
97107

98108
return $this->buildMandatoryParameterSpec($matches);
@@ -106,16 +116,14 @@ public function build(string $definition): ParameterSpecInterface
106116

107117
protected function buildVariadicParameterSpec(array $matches): VariadicParameterSpec
108118
{
109-
if (isset($matches['default']) && '' !== $matches['default']) {
110-
throw new ParameterSpecBuilderException('Variadic parameter should have no default value');
111-
}
112-
113119
return new VariadicParameterSpec($matches['name'], $this->builder->build($matches['type']));
114120
}
115121

116-
protected function buildOptionalParameterSpec(array $matches): OptionalParameterSpec
122+
protected function buildOptionalParameterSpec(array $matches, ?string$default): OptionalParameterSpec
117123
{
118-
$default = $this->buildDefaultValue($matches['default']);
124+
if (null !== $default) {
125+
$default = $this->buildDefaultValue($matches['default']);
126+
}
119127

120128
return new OptionalParameterSpec($matches['name'], $this->builder->build($matches['type']), $default);
121129
}
@@ -166,6 +174,7 @@ protected function buildDefaultValue(string $definition)
166174
}
167175
}
168176

177+
// UNEXPECTED
169178
// Less likely we will ever get here because it should fail at a parsing step, but just in case
170179
throw new ParameterSpecBuilderException("Unknown default value format '{$definition}'");
171180
}
@@ -176,4 +185,34 @@ private function wrappedWith(string $definition, string $starts, $ends)
176185

177186
return $starts == $definition[0] && $ends == $definition[-1];
178187
}
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+
}
179218
}

‎tests/Specs/Builder/FunctionSpecBuilderTest.php‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,18 @@ public function testBuildSpecWithParams()
117117
$this->assertFalse($spec->needsExecutionContext());
118118
$this->assertContainsOnlyInstancesOf(ParameterSpecInterface::class, $spec->getParameters()->getParameters());
119119
$this->assertCount(3, $spec->getParameters()->getParameters());
120+
}
121+
122+
public function testBuildSpecWithNullableParams()
123+
{
124+
$this->parameterSpecBuilderShouldBuildOn('one: param', 'two?: param');
125+
126+
$spec = $this->builder->build('(one: param, two?: param)');
120127

128+
$this->assertInstanceOf(FunctionSpecInterface::class, $spec);
129+
$this->assertFalse($spec->needsExecutionContext());
130+
$this->assertContainsOnlyInstancesOf(ParameterSpecInterface::class, $spec->getParameters()->getParameters());
131+
$this->assertCount(2, $spec->getParameters()->getParameters());
121132
}
122133

123134
// Test throws spec

‎tests/Specs/Builder/ParameterSpecBuilderTest.php‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,44 @@ public function testBuildingVariadicParameter()
134134

135135
/**
136136
* @expectedException \Pinepain\JsSandbox\Specs\Builder\Exceptions\ParameterSpecBuilderException
137-
* @expectedExceptionMessage Variadic parameter should have no default value
137+
* @expectedExceptionMessage Variadic parameter could have no default value
138138
*/
139139
public function testBuildingVariadicParameterWithDefaultValueShouldThrowException()
140140
{
141141
$this->builder->build('...param = []: type');
142142
}
143143

144+
/**
145+
* @expectedException \Pinepain\JsSandbox\Specs\Builder\Exceptions\ParameterSpecBuilderException
146+
* @expectedExceptionMessage Variadic parameter could not be nullable
147+
*/
148+
public function testBuildingVariadicParameterWithNullableShouldThrowException()
149+
{
150+
$this->builder->build('...param?: type');
151+
}
152+
153+
/**
154+
* @expectedException \Pinepain\JsSandbox\Specs\Builder\Exceptions\ParameterSpecBuilderException
155+
* @expectedExceptionMessage Nullable parameter could not have default value
156+
*/
157+
public function testBuildingNullableParameterWithDefaultValueShouldThrowException()
158+
{
159+
$this->builder->build('param? = "default": type');
160+
}
161+
162+
public function testBuildingNullableParameter()
163+
{
164+
$this->extractorDefinitionShouldBuildOn('type');
165+
166+
$spec = $this->builder->build('param? : type');
167+
168+
$this->assertInstanceOf(OptionalParameterSpec::class, $spec);
169+
170+
$this->assertSame('param', $spec->getName());
171+
$this->assertNull($spec->getDefaultValue());
172+
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
173+
}
174+
144175
/**
145176
* @expectedException \Pinepain\JsSandbox\Specs\Builder\Exceptions\ParameterSpecBuilderException
146177
* @expectedExceptionMessage Unable to parse definition because of extractor failure: ExtractorDefinitionBuilder exception for testing

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /