Skip to content

Commit c72a5ea

Browse files
authored
Controller reference (Close #47) (#109)
* Controller reference (Close #47)
1 parent 505dddd commit c72a5ea

11 files changed

+55
-23
lines changed

src/Ast/Converter.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Riverwaysoft\PhpConverter\Ast;
66

77
use PhpParser\NodeTraverser;
8+
use PhpParser\NodeVisitor\ParentConnectingVisitor;
89
use PhpParser\Parser;
910
use PhpParser\ParserFactory;
1011

@@ -28,6 +29,7 @@ public function convert(iterable $listings): ConverterResult
2829
$converterResult = new ConverterResult();
2930

3031
$traverser = new NodeTraverser();
32+
$traverser->addVisitor(new ParentConnectingVisitor());
3133
foreach ($this->visitors as $visitor) {
3234
$traverser->addVisitor($visitor);
3335
}
@@ -38,7 +40,7 @@ public function convert(iterable $listings): ConverterResult
3840
}
3941

4042
foreach ($this->visitors as $visitor) {
41-
$converterResult->merge($visitor->popResult());
43+
$converterResult->merge($visitor->getResult());
4244
}
4345

4446
return $converterResult;

src/Ast/ConverterVisitor.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,5 @@
88

99
abstract class ConverterVisitor extends NodeVisitorAbstract
1010
{
11-
/** @phpstan-impure */
12-
abstract public function popResult(): ConverterResult;
11+
abstract public function getResult(): ConverterResult;
1312
}

src/Ast/DtoVisitor.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,8 @@ public function resolveExpressionType(Class_|Enum_ $node): ExpressionType
218218
: ExpressionType::class();
219219
}
220220

221-
public function popResult(): ConverterResult
221+
public function getResult(): ConverterResult
222222
{
223-
$result = $this->converterResult;
224-
$this->converterResult = new ConverterResult();
225-
return $result;
223+
return $this->converterResult;
226224
}
227225
}

src/Bridge/ApiPlatform/ApiPlatformDtoResourceVisitor.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -399,10 +399,8 @@ private function getAttributeArgumentByName(Attribute $attribute, string $name):
399399
return null;
400400
}
401401

402-
public function popResult(): ConverterResult
402+
public function getResult(): ConverterResult
403403
{
404-
$result = $this->converterResult;
405-
$this->converterResult = new ConverterResult();
406-
return $result;
404+
return $this->converterResult;
407405
}
408406
}

src/Bridge/Symfony/SymfonyControllerVisitor.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,22 @@ private function createApiEndpoint(ClassMethod $node): void
202202
$routeParams,
203203
),
204204
queryParams: $queryParams,
205+
codeReference: $this->generateCodeReference($node),
205206
));
206207
}
207208

208-
public function popResult(): ConverterResult
209+
private function generateCodeReference(ClassMethod $node): string|null
209210
{
210-
$result = $this->converterResult;
211-
$this->converterResult = new ConverterResult();
212-
return $result;
211+
$parent = $node->getAttribute('parent');
212+
if (!($parent instanceof Node\Stmt\Class_)) {
213+
return null;
214+
}
215+
216+
return sprintf("%s::%s", $parent->name->name, $node->name->name);
217+
}
218+
219+
public function getResult(): ConverterResult
220+
{
221+
return $this->converterResult;
213222
}
214223
}

src/Dto/ApiClient/ApiEndpoint.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public function __construct(
2121
public array $routeParams = [],
2222
/** @var ApiEndpointParam[] */
2323
public array $queryParams = [],
24+
public string|null $codeReference = null,
2425
) {
2526
if (str_contains($this->route, '.')) {
2627
throw new Exception(sprintf("Invalid character . in route %s", $this->route));
@@ -36,6 +37,7 @@ public function jsonSerialize(): mixed
3637
'input' => $this->input,
3738
'output' => $this->output,
3839
'queryParams' => $this->queryParams,
40+
'codeReference' => $this->codeReference,
3941
];
4042
}
4143
}

src/OutputGenerator/TypeScript/AxiosEndpointGenerator.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ public function __construct(
2020

2121
public function generate(ApiEndpoint $apiEndpoint, DtoList $dtoList): string
2222
{
23-
$string = "\nexport const %s = (%s): %s => {\n%s\n}\n";
23+
$string = "\n%sexport const %s = (%s): %s => {\n%s\n}\n";
24+
25+
$codeReference = '';
26+
if ($apiEndpoint->codeReference) {
27+
$codeReference = sprintf("/** @see %s */\n", $apiEndpoint->codeReference);
28+
}
2429

2530
$fullRoute = $apiEndpoint->route . '/' . $apiEndpoint->method->getType();
2631
$name = $this->normalizeEndpointName($fullRoute);
@@ -70,7 +75,7 @@ public function generate(ApiEndpoint $apiEndpoint, DtoList $dtoList): string
7075
.%s<%s>(`%s`%s)
7176
.then((response) => response.data);', $apiEndpoint->method->getType(), $outputType, $route, $formParamsAsString);
7277

73-
return sprintf($string, $name, $params, $returnType, $body);
78+
return sprintf($string, $codeReference, $name, $params, $returnType, $body);
7479
}
7580

7681
private function normalizeEndpointName(string $str): string

tests/__snapshots__/ConverterTest__testFilterClassesByPhpAnnotation__1.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"generics": []
1313
}
1414
},
15-
"queryParams": []
15+
"queryParams": [],
16+
"codeReference": "SomeController::getUserMethodsArray"
1617
}
1718
]
1819
}

tests/__snapshots__/ConverterTest__testFilterClassesByPhpAttribute__1.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"generics": []
1313
}
1414
},
15-
"queryParams": []
15+
"queryParams": [],
16+
"codeReference": "SomeController::getUserMethodsArray"
1617
},
1718
{
1819
"route": "\/api\/users",
@@ -31,7 +32,8 @@
3132
"context": [],
3233
"generics": []
3334
},
34-
"queryParams": []
35+
"queryParams": [],
36+
"codeReference": "SomeController::createUser"
3537
},
3638
{
3739
"route": "\/api\/users\/{id}",
@@ -50,7 +52,8 @@
5052
"context": [],
5153
"generics": []
5254
},
53-
"queryParams": []
55+
"queryParams": [],
56+
"codeReference": "SomeController::getUser"
5457
},
5558
{
5659
"route": "\/api\/users_methods_string",
@@ -62,7 +65,8 @@
6265
"context": [],
6366
"generics": []
6467
},
65-
"queryParams": []
68+
"queryParams": [],
69+
"codeReference": "SomeController::getUserMethodsString"
6670
},
6771
{
6872
"route": "\/api\/users_reversed_order",
@@ -76,7 +80,8 @@
7680
"generics": []
7781
}
7882
},
79-
"queryParams": []
83+
"queryParams": [],
84+
"codeReference": "SomeController::getUserMethodsArrayReversedOrder"
8085
}
8186
]
8287
}

tests/__snapshots__/TypeScriptGeneratorTest__testTypesWithApiClientAndOverrideReturn__1.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,35 @@ export type UserShortOutput = {
1414
id: string;
1515
};
1616

17+
/** @see UserController::annotationsReturn */
1718
export const apiAnnotationsReturnGet = (): Promise<UserOutput> => {
1819
return axios
1920
.get<UserOutput>(`/api/annotations-return`)
2021
.then((response) => response.data);
2122
}
2223

24+
/** @see UserController::annotationsReturnTakePrecedenceOverDtoEndpoint */
2325
export const apiAnnotationsReturnPrecedenceGet = (): Promise<UserShortOutput> => {
2426
return axios
2527
.get<UserShortOutput>(`/api/annotations-return-precedence`)
2628
.then((response) => response.data);
2729
}
2830

31+
/** @see UserController::nestedGenericsSimpleType */
2932
export const apiNestedGenericsSimpleTypeGet = (): Promise<JsonResponse<string[]>> => {
3033
return axios
3134
.get<JsonResponse<string[]>>(`/api/nested-generics-simple-type`)
3235
.then((response) => response.data);
3336
}
3437

38+
/** @see UserController::nestedGenericAnnotationReturn */
3539
export const apiRouteWithNestedGenericsAnnotationsReturnGet = (): Promise<JsonResponse<UserOutput>> => {
3640
return axios
3741
.get<JsonResponse<UserOutput>>(`/api/route-with-nested-generics-annotations-return`)
3842
.then((response) => response.data);
3943
}
4044

45+
/** @see UserController::nestedGenericAnnotationUnionReturn */
4146
export const apiRouteWithNestedGenericsUnionAnnotationsReturnGet = (): Promise<JsonResponse<UserOutput[]>> => {
4247
return axios
4348
.get<JsonResponse<UserOutput[]>>(`/api/route-with-nested-generics-union-annotations-return`)

0 commit comments

Comments
 (0)