Skip to content

Commit

Permalink
added @default doc support
Browse files Browse the repository at this point in the history
  • Loading branch information
romalytvynenko committed Apr 7, 2024
1 parent 74f5441 commit f368442
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 16 deletions.
13 changes: 9 additions & 4 deletions src/Support/Helpers/ExamplesExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@
class ExamplesExtractor
{
public function __construct(
private ?PhpDocNode $docNode
private ?PhpDocNode $docNode,
private string $tagName = '@example',
) {
}

public static function make(?PhpDocNode $docNode)
public static function make(?PhpDocNode $docNode, string $tagName = '@example')
{
return new self($docNode);
return new self($docNode, $tagName);
}

public function extract(bool $preferString = false)
{
if (! count($examples = $this->docNode->getTagsByName('@example'))) {
if (! count($examples = $this->docNode->getTagsByName($this->tagName))) {
return [];
}

Expand Down Expand Up @@ -52,6 +53,10 @@ private function getTypedExampleValue($exampleValue, bool $preferString = false)
$exampleValue = $exampleValue === 'true';
} elseif (is_numeric($exampleValue) && ! $preferString) {
$exampleValue = floatval($exampleValue);

if (floor($exampleValue) == $exampleValue) {
$exampleValue = intval($exampleValue);
}
}

return $exampleValue;
Expand Down
38 changes: 26 additions & 12 deletions src/Support/IndexBuilders/RequestParametersBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Dedoc\Scramble\Support\Generator\Parameter;
use Dedoc\Scramble\Support\Generator\Schema;
use Dedoc\Scramble\Support\Generator\TypeTransformer;
use Dedoc\Scramble\Support\Helpers\ExamplesExtractor;
use Dedoc\Scramble\Support\Type\BooleanType;
use Dedoc\Scramble\Support\Type\FloatType;
use Dedoc\Scramble\Support\Type\IntegerType;
Expand Down Expand Up @@ -62,7 +63,7 @@ public function afterAnalyzedNode(Scope $scope, Node $node)

$parameter = Parameter::make($parameterName, 'query'/* @todo: this is just a temp solution */);

[$parameterType, $parameterDefaultFromMethodCall] = match ($name) {
[$parameterType, $parameterDefault] = match ($name) {
'integer' => $this->makeIntegerParameter($scope, $methodCallNode),
'float' => $this->makeFloatParameter($scope, $methodCallNode),
'boolean' => $this->makeBooleanParameter($scope, $methodCallNode),
Expand All @@ -76,12 +77,16 @@ public function afterAnalyzedNode(Scope $scope, Node $node)
return;
}

if ($parameterDefaultFromDoc = $this->getParameterDefaultFromPhpDoc($node)) {
$parameterDefault = $parameterDefaultFromDoc;
}

$parameter
->description($this->makeDescriptionFromComments($node))
->setSchema(Schema::fromType(
app(TypeTransformer::class)->transform($parameterType)
))
->default($parameterDefaultFromMethodCall ?? new MissingExample);
->default($parameterDefault ?? new MissingExample);

// @todo: query
// @todo: get/input/post/?
Expand Down Expand Up @@ -159,6 +164,17 @@ private function makeQueryParameter(Scope $scope, Node $node, Parameter $paramet

private function makeDescriptionFromComments(Node\Stmt\Expression $node)
{
/*
* @todo: consider adding only @param annotation support,
* so when description is taken only if comment is marked with @param
*/
if ($node->getDocComment()) {
/** @var PhpDocNode $phpDoc */
$phpDoc = $node->getAttribute('parsedPhpDoc');

return trim($phpDoc->getAttribute('summary').' '.$phpDoc->getAttribute('description'));
}

if ($node->getComments()) {
$docText = collect($node->getComments())
->map(fn (Comment $c) => $c->getReformattedText())
Expand All @@ -167,16 +183,6 @@ private function makeDescriptionFromComments(Node\Stmt\Expression $node)
return (string) Str::of($docText)->replace(['//', ' * ', '/**', '/*', '*/'], '')->trim();
}

/*
* @todo: consider adding only @param annotation support,
* so when description is taken only if comment is marked with @param
*/
if ($node->getDocComment()) {
return (string) Str::of($node->getDocComment()->getReformattedText())
->replace(['//', ' * ', '/**', '/*', '*/'], '')
->trim();
}

return '';
}

Expand All @@ -187,4 +193,12 @@ private function shouldIgnoreParameter(Node\Stmt\Expression $node)

return !! $phpDoc->getTagsByName('@ignoreParam');
}

private function getParameterDefaultFromPhpDoc(Node\Stmt\Expression $node)
{
/** @var PhpDocNode $phpDoc */
$phpDoc = $node->getAttribute('parsedPhpDoc');

return ExamplesExtractor::make($phpDoc, '@default')->extract()[0] ?? null;
}
}
17 changes: 17 additions & 0 deletions tests/Support/OperationExtensions/RequestBodyExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,20 @@ public function index(Illuminate\Http\Request $request)
$request->integer('foo', 10);
}
}

it('uses and overrides default param value when it is provided manually in doc', function () {
$openApiDocument = generateForRoute(function () {
return RouteFacade::post('api/test', [RequestBodyExtensionTest__uses_and_overrides_default_param_value_when_it_is_provided_manually_in_doc::class, 'index']);
});

expect($openApiDocument['paths']['/test']['post']['requestBody']['content']['application/json']['schema']['properties']['foo']['default'])
->toBe(15);
});
class RequestBodyExtensionTest__uses_and_overrides_default_param_value_when_it_is_provided_manually_in_doc
{
public function index(Illuminate\Http\Request $request)
{
/** @default 15 */
$request->integer('foo', 10);
}
}

0 comments on commit f368442

Please sign in to comment.