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 bf92724

Browse files
committed
Add parameter type guessing by default value
1 parent 40cc8a5 commit bf92724

File tree

3 files changed

+165
-9
lines changed

3 files changed

+165
-9
lines changed

‎src/Extractors/ExtractorDefinitionBuilder.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,6 @@ protected function buildArrayDefinition(?ExtractorDefinitionInterface $definitio
181181
return $definition;
182182
}
183183

184-
/**
185-
* @param array $matches
186-
*
187-
* @return int
188-
*/
189184
private function getDepth(array $matches): int
190185
{
191186
if (!isset($matches['arr']) || '' === $matches['arr']) {

‎src/Specs/Builder/ParameterSpecBuilder.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
use Pinepain\JsSandbox\Specs\Parameters\OptionalParameterSpec;
2525
use Pinepain\JsSandbox\Specs\Parameters\ParameterSpecInterface;
2626
use Pinepain\JsSandbox\Specs\Parameters\VariadicParameterSpec;
27-
use function strlen;
2827

2928

3029
class ParameterSpecBuilder implements ParameterSpecBuilderInterface
@@ -138,6 +137,10 @@ protected function buildOptionalParameterSpec(array $matches, ?string $default):
138137
} catch (ArgumentValueBuilderException $e) {
139138
throw new ParameterSpecBuilderException("Unknown or unsupported default value format '{$default_definition}'");
140139
}
140+
141+
if (!$this->hasType($matches)) {
142+
$matches['type'] = $this->guessTypeFromDefault($default);
143+
}
141144
}
142145

143146
return new OptionalParameterSpec($matches['name'], $this->extractor->build($matches['type']), $default);
@@ -162,8 +165,9 @@ protected function prepareDefinition(array $matches): array
162165
throw new ParameterSpecBuilderException('Variadic parameter could have no default value');
163166
}
164167

165-
if (!$this->hasType($matches)) {
166-
$matches['type'] = 'any'; // special case
168+
if (!$this->hasDefault($matches) && !$this->hasType($matches)) {
169+
// special case when no default value set and no type provided
170+
$matches['type'] = 'any';
167171
}
168172

169173
return $matches;
@@ -188,4 +192,27 @@ private function hasDefault(array $matches): bool
188192
{
189193
return isset($matches['default']) && '' !== $matches['default'];
190194
}
195+
196+
private function guessTypeFromDefault($default): string
197+
{
198+
if (is_array($default)) {
199+
return '[]';
200+
}
201+
202+
if (is_numeric($default)) {
203+
return 'number';
204+
}
205+
206+
if (is_bool($default)) {
207+
return 'bool';
208+
}
209+
210+
if (is_string($default)) {
211+
return 'string';
212+
}
213+
214+
// it looks like we have nullable parameter which could be anything
215+
216+
return 'any';
217+
}
191218
}

‎tests/Specs/Builder/ParameterSpecBuilderTest.php

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,118 @@ public function testBuildingNullableParameter()
210210
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
211211
}
212212

213+
public function testBuildingParameterWithArrayTypeGuessing()
214+
{
215+
$this->argumentDefinitionShouldBuildOn('[]');
216+
$this->extractorDefinitionShouldBuildOn('[]');
217+
218+
$spec = $this->builder->build('param = []');
219+
220+
$this->assertInstanceOf(OptionalParameterSpec::class, $spec);
221+
222+
$this->assertSame('param', $spec->getName());
223+
$this->assertSame([], $spec->getDefaultValue());
224+
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
225+
}
226+
227+
public function testBuildingParameterWithBoolTrueTypeGuessing()
228+
{
229+
$this->argumentDefinitionShouldBuildOn('true');
230+
$this->extractorDefinitionShouldBuildOn('bool');
231+
232+
$spec = $this->builder->build('param = true');
233+
234+
$this->assertInstanceOf(OptionalParameterSpec::class, $spec);
235+
236+
$this->assertSame('param', $spec->getName());
237+
$this->assertSame(true, $spec->getDefaultValue());
238+
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
239+
}
240+
241+
public function testBuildingParameterWithBoolFalseTypeGuessing()
242+
{
243+
$this->argumentDefinitionShouldBuildOn('false');
244+
$this->extractorDefinitionShouldBuildOn('bool');
245+
246+
$spec = $this->builder->build('param = false');
247+
248+
$this->assertInstanceOf(OptionalParameterSpec::class, $spec);
249+
250+
$this->assertSame('param', $spec->getName());
251+
$this->assertSame(false, $spec->getDefaultValue());
252+
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
253+
}
254+
255+
public function testBuildingParameterWithNullableTypeGuessing()
256+
{
257+
$this->argumentDefinitionShouldBuildOn('null');
258+
$this->extractorDefinitionShouldBuildOn('any');
259+
260+
$spec = $this->builder->build('param?');
261+
262+
$this->assertInstanceOf(OptionalParameterSpec::class, $spec);
263+
264+
$this->assertSame('param', $spec->getName());
265+
$this->assertSame(null, $spec->getDefaultValue());
266+
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
267+
}
268+
269+
public function testBuildingParameterWithDefaultNullTypeGuessing()
270+
{
271+
$this->argumentDefinitionShouldBuildOn('null');
272+
$this->extractorDefinitionShouldBuildOn('any');
273+
274+
$spec = $this->builder->build('param = null');
275+
276+
$this->assertInstanceOf(OptionalParameterSpec::class, $spec);
277+
278+
$this->assertSame('param', $spec->getName());
279+
$this->assertSame(null, $spec->getDefaultValue());
280+
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
281+
}
282+
283+
public function testBuildingParameterWithDefaultIntNumberTypeGuessing()
284+
{
285+
$this->argumentDefinitionShouldBuildOn('123');
286+
$this->extractorDefinitionShouldBuildOn('number');
287+
288+
$spec = $this->builder->build('param = 123');
289+
290+
$this->assertInstanceOf(OptionalParameterSpec::class, $spec);
291+
292+
$this->assertSame('param', $spec->getName());
293+
$this->assertEquals(123, $spec->getDefaultValue());
294+
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
295+
}
296+
297+
public function testBuildingParameterWithDefaultFloatNumberTypeGuessing()
298+
{
299+
$this->argumentDefinitionShouldBuildOn('123.42');
300+
$this->extractorDefinitionShouldBuildOn('number');
301+
302+
$spec = $this->builder->build('param = 123.42');
303+
304+
$this->assertInstanceOf(OptionalParameterSpec::class, $spec);
305+
306+
$this->assertSame('param', $spec->getName());
307+
$this->assertSame(123.42, $spec->getDefaultValue());
308+
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
309+
}
310+
311+
public function testBuildingParameterWithDefaultStringTypeGuessing()
312+
{
313+
$this->argumentDefinitionShouldBuildOn('"test"');
314+
$this->extractorDefinitionShouldBuildOn('string');
315+
316+
$spec = $this->builder->build('param = "test"');
317+
318+
$this->assertInstanceOf(OptionalParameterSpec::class, $spec);
319+
320+
$this->assertSame('param', $spec->getName());
321+
$this->assertSame('"test"', $spec->getDefaultValue());
322+
$this->assertInstanceOf(ExtractorDefinitionInterface::class, $spec->getExtractorDefinition());
323+
}
324+
213325
/**
214326
* @expectedException \Pinepain\JsSandbox\Specs\Builder\Exceptions\ParameterSpecBuilderException
215327
* @expectedExceptionMessage Unable to parse definition because of extractor failure: ExtractorDefinitionBuilder exception for testing
@@ -223,9 +335,31 @@ public function testBuildingWhenExtractorFailsShouldAlsoFail()
223335

224336
protected function argumentDefinitionShouldBuildOn($name)
225337
{
338+
$retval = $name;
339+
340+
if ('[]' == $name) {
341+
$retval = [];
342+
}
343+
344+
if ('true' === $name) {
345+
$retval = true;
346+
}
347+
348+
if ('false' === $name) {
349+
$retval = false;
350+
}
351+
352+
if (is_numeric($name)) {
353+
$retval = is_int($name) ? (int)$name : (float) $name;
354+
}
355+
356+
if ('null' === $name) {
357+
$retval = null;
358+
}
359+
226360
$this->argument_builder->method('build')
227361
->with($name, false)
228-
->willReturn($name);
362+
->willReturn($retval);
229363
}
230364

231365
protected function argumentDefinitionShouldThrowOn($name)

0 commit comments

Comments
(0)

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