Skip to content

Commit

Permalink
Merge pull request #367 from dedoc/fix/deeper-request-params
Browse files Browse the repository at this point in the history
Fixed inferring params from request method calls
  • Loading branch information
romalytvynenko committed May 15, 2024
2 parents 5520b59 + 4b4de4d commit f2ac696
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 14 deletions.
34 changes: 22 additions & 12 deletions src/Support/IndexBuilders/RequestParametersBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Illuminate\Support\Str;
use PhpParser\Comment;
use PhpParser\Node;
use PhpParser\NodeAbstract;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;

class RequestParametersBuilder
Expand All @@ -33,16 +34,25 @@ public function __construct(public Bag $bag)

public function afterAnalyzedNode(Scope $scope, Node $node)
{
if (! $node instanceof Node\Stmt\Expression) {
// @todo: Find more general approach to get a comment related to the node
[$commentHolderNode, $methodCallNode] = match ($node::class) {
Node\Stmt\Expression::class => [
$node,
$node->expr instanceof Node\Expr\Assign ? $node->expr->expr : $node->expr,
],
Node\Arg::class => [$node, $node->value],
Node\ArrayItem::class => [$node, $node->value],
default => [null, null],
};

if (! $commentHolderNode) {
return;
}

if (! $node->expr instanceof Node\Expr\MethodCall) {
if (! $methodCallNode instanceof Node\Expr\MethodCall) {
return;
}

$methodCallNode = $node->expr;

$varType = $scope->getType($methodCallNode->var);

if (! $varType->isInstanceOf(Request::class)) {
Expand All @@ -57,7 +67,7 @@ public function afterAnalyzedNode(Scope $scope, Node $node)
return;
}

if ($this->shouldIgnoreParameter($node)) {
if ($this->shouldIgnoreParameter($commentHolderNode)) {
return;
}

Expand All @@ -77,14 +87,14 @@ public function afterAnalyzedNode(Scope $scope, Node $node)
return;
}

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

$this->checkExplicitParameterPlacementInQuery($node, $parameter);
$this->checkExplicitParameterPlacementInQuery($commentHolderNode, $parameter);

$parameter
->description($this->makeDescriptionFromComments($node))
->description($this->makeDescriptionFromComments($commentHolderNode))
->setSchema(Schema::fromType(
app(TypeTransformer::class)->transform($parameterType)
))
Expand Down Expand Up @@ -161,7 +171,7 @@ private function makeQueryParameter(Scope $scope, Node $node, Parameter $paramet
];
}

private function makeDescriptionFromComments(Node\Stmt\Expression $node)
private function makeDescriptionFromComments(NodeAbstract $node)
{
/*
* @todo: consider adding only @param annotation support,
Expand All @@ -182,23 +192,23 @@ private function makeDescriptionFromComments(Node\Stmt\Expression $node)
return '';
}

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

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

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

return ExamplesExtractor::make($phpDoc, '@default')->extract()[0] ?? null;
}

private function checkExplicitParameterPlacementInQuery(Node\Stmt\Expression $node, Parameter $parameter)
private function checkExplicitParameterPlacementInQuery(NodeAbstract $node, Parameter $parameter)
{
/** @var PhpDocNode|null $phpDoc */
$phpDoc = $node->getAttribute('parsedPhpDoc');
Expand Down
10 changes: 9 additions & 1 deletion src/Support/OperationExtensions/RequestBodyExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,15 @@ public function handle(Operation $operation, RouteInfo $routeInfo)
try {
$bodyParams = $this->extractParamsFromRequestValidationRules($routeInfo->route, $routeInfo->methodNode());

$allParams = [...$bodyParams, ...array_values($routeInfo->requestParametersFromCalls->data)];
$bodyParamsNames = array_map(fn ($p) => $p->name, $bodyParams);

$allParams = [
...$bodyParams,
...array_filter(
array_values($routeInfo->requestParametersFromCalls->data),
fn ($p) => ! in_array($p->name, $bodyParamsNames),
),
];
[$queryParams, $bodyParams] = collect($allParams)
->partition(function (Parameter $parameter) {
return $parameter->getAttribute('isInQuery');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class RequestBodyExtensionTest__extracts_parameters_from_retrieving_methods_with
public function index(Illuminate\Http\Request $request)
{
// How many things are there.
$request->integer('count', 10);
$param = $request->integer('count', 10);

$request->float('weight', 0.5);

Expand Down

0 comments on commit f2ac696

Please sign in to comment.