diff --git a/src/Support/IndexBuilders/RequestParametersBuilder.php b/src/Support/IndexBuilders/RequestParametersBuilder.php index e02a737b..ca514cbf 100644 --- a/src/Support/IndexBuilders/RequestParametersBuilder.php +++ b/src/Support/IndexBuilders/RequestParametersBuilder.php @@ -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 @@ -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)) { @@ -57,7 +67,7 @@ public function afterAnalyzedNode(Scope $scope, Node $node) return; } - if ($this->shouldIgnoreParameter($node)) { + if ($this->shouldIgnoreParameter($commentHolderNode)) { return; } @@ -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) )) @@ -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, @@ -182,7 +192,7 @@ 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'); @@ -190,7 +200,7 @@ private function shouldIgnoreParameter(Node\Stmt\Expression $node) 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'); @@ -198,7 +208,7 @@ private function getParameterDefaultFromPhpDoc(Node\Stmt\Expression $node) 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'); diff --git a/src/Support/OperationExtensions/RequestBodyExtension.php b/src/Support/OperationExtensions/RequestBodyExtension.php index b61d4910..3d847883 100644 --- a/src/Support/OperationExtensions/RequestBodyExtension.php +++ b/src/Support/OperationExtensions/RequestBodyExtension.php @@ -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'); diff --git a/tests/Support/OperationExtensions/RequestBodyExtensionTest.php b/tests/Support/OperationExtensions/RequestBodyExtensionTest.php index ba7fdff2..3262dea1 100644 --- a/tests/Support/OperationExtensions/RequestBodyExtensionTest.php +++ b/tests/Support/OperationExtensions/RequestBodyExtensionTest.php @@ -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);