Skip to content

Commit 6c8e76f

Browse files
wip
1 parent 67b2376 commit 6c8e76f

26 files changed

+116
-100
lines changed

.claude/settings.local.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(vendor/bin/pest:*)",
5+
"Bash(vendor/bin/phpstan analyse:*)"
6+
],
7+
"deny": []
8+
}
9+
}

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"scripts": {
5656
"post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi",
5757
"analyse": "vendor/bin/phpstan analyse",
58+
"baseline": "vendor/bin/phpstan analyse --generate-baseline",
5859
"test": "vendor/bin/pest",
5960
"test-coverage": "vendor/bin/pest --coverage",
6061
"format": "vendor/bin/pint"

phpstan-baseline.neon

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: '#^Instanceof between Closure and Closure will always evaluate to true\.$#'
5+
identifier: instanceof.alwaysTrue
6+
count: 1
7+
path: src/TypeScriptTransformerConfigFactory.php

phpstan.neon

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
includes:
2+
- phpstan-baseline.neon
3+
4+
parameters:
5+
level: 5
6+
paths:
7+
- src
8+
tmpDir: build/phpstan
9+
checkOctaneCompatibility: true
10+
checkModelProperties: true

src/Actions/TranspilePhpStanTypeToTypeScriptNodeAction.php

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
namespace Spatie\TypeScriptTransformer\Actions;
44

55
use Exception;
6+
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
67
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
78
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
8-
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode;
99
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
1010
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
1111
use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
1212
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
1313
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
1414
use PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode;
1515
use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode;
16-
use PHPStan\PhpDocParser\Ast\Type\ObjectShapeItemNode;
1716
use PHPStan\PhpDocParser\Ast\Type\ObjectShapeNode;
1817
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
1918
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
@@ -192,21 +191,28 @@ protected function arrayShapeNode(
192191
ArrayShapeNode|ObjectShapeNode $node,
193192
?PhpClassNode $phpClassNode
194193
): TypeScriptObject {
195-
return new TypeScriptObject(array_map(
196-
function (ArrayShapeItemNode|ObjectShapeItemNode $item) use ($phpClassNode) {
197-
$name = match ($item->keyName::class) {
198-
IdentifierTypeNode::class => $item->keyName->name,
199-
ConstExprStringNode::class => $item->keyName->value,
200-
};
201-
202-
return new TypeScriptProperty(
203-
$name,
204-
$this->execute($item->valueType, $phpClassNode),
205-
isOptional: $item->optional
206-
);
207-
},
208-
$node->items
209-
));
194+
$properties = [];
195+
196+
foreach ($node->items as $item) {
197+
$name = match ($item->keyName::class) {
198+
IdentifierTypeNode::class => $item->keyName->name,
199+
ConstExprStringNode::class => $item->keyName->value,
200+
ConstExprIntegerNode::class => (string) $item->keyName->value,
201+
default => null,
202+
};
203+
204+
if ($name === null) {
205+
continue;
206+
}
207+
208+
$properties[] = new TypeScriptProperty(
209+
$name,
210+
$this->execute($item->valueType, $phpClassNode),
211+
isOptional: $item->optional
212+
);
213+
}
214+
215+
return new TypeScriptObject($properties);
210216
}
211217

212218
protected function nullableNode(
@@ -301,22 +307,14 @@ protected function genericArrayNode(GenericTypeNode $node, ?PhpClassNode $phpCla
301307

302308
protected function keyOrValueOfGenericNode(GenericTypeNode $node, ?PhpClassNode $phpClassNode): TypeScriptNode
303309
{
304-
if (count($node->genericTypes) === 1
305-
&& $node->genericTypes[0] instanceof ConstTypeNode
306-
&& $node->genericTypes[0]->constExpr instanceof ConstFetchNode
310+
if (count($node->genericTypes) !== 1
311+
|| ! $node->genericTypes[0] instanceof ConstTypeNode
312+
|| ! $node->genericTypes[0]->constExpr instanceof ConstFetchNode
307313
) {
308-
return $this->keyOrValueOfArrayConstNode($node, $phpClassNode, $node->genericTypes[0]->constExpr);
314+
return $this->defaultGenericNode($node, $phpClassNode);
309315
}
310316

311-
312-
return $this->defaultGenericNode($node, $phpClassNode);
313-
}
314-
315-
protected function keyOrValueOfArrayConstNode(
316-
GenericTypeNode $node,
317-
?PhpClassNode $phpClassNode,
318-
ConstFetchNode $constFetchNode,
319-
): TypeScriptNode {
317+
$constFetchNode = $node->genericTypes[0]->constExpr;
320318
$class = $this->resolveClass($constFetchNode->className, $phpClassNode);
321319

322320
if ($class === null) {
@@ -343,6 +341,10 @@ protected function defaultGenericNode(GenericTypeNode $node, ?PhpClassNode $phpC
343341
return $type; // class-string<something> case
344342
}
345343

344+
if (! ($type instanceof TypeReference || $type instanceof TypeScriptIdentifier)) {
345+
return new TypeScriptUnknown();
346+
}
347+
346348
return new TypeScriptGeneric(
347349
$type,
348350
array_map(

src/Data/ImportLocation.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,8 @@ public function getAliasOrNameForReference(Reference $reference): ?string
3333
return null;
3434
}
3535

36-
public function toTypeScriptNode(): ?TypeScriptImport
36+
public function toTypeScriptNode(): TypeScriptImport
3737
{
38-
if ($this->relativePath === null) {
39-
// current path
40-
return null;
41-
}
42-
4338
return new TypeScriptImport($this->relativePath, $this->importNames);
4439
}
4540
}

src/Laravel/LaravelNamedRouteTypesProvider.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ protected function parseRouteCollection(RouteCollection $collection): TypeScript
139139

140140
if ($entity instanceof RouteController) {
141141
return collect($entity->actions)
142-
->filter(fn (RouteControllerAction $action) => $action->name)
142+
->filter(fn (RouteControllerAction $action) => $action->name !== null)
143143
->values()
144144
->map($mappingFunction);
145145
}
@@ -158,7 +158,7 @@ protected function parseRouteParameterCollection(RouteParameterCollection $colle
158158
}, $collection->parameters));
159159
}
160160

161-
protected function parseRouteParameter(RouteParameter $parameter): TypeScriptNode
161+
protected function parseRouteParameter(RouteParameter $parameter): TypeScriptProperty
162162
{
163163
return new TypeScriptProperty(
164164
$parameter->name,
@@ -183,7 +183,7 @@ protected function routeCollectionToJson(RouteCollection $collection): string
183183

184184
if ($controller instanceof RouteController) {
185185
return collect($controller->actions)
186-
->filter(fn (RouteControllerAction $action) => $action->name)
186+
->filter(fn (RouteControllerAction $action) => $action->name !== null)
187187
->values()
188188
->mapWithKeys($mappingFunction);
189189
}
@@ -192,7 +192,7 @@ protected function routeCollectionToJson(RouteCollection $collection): string
192192
});
193193

194194
$closures = collect($collection->closures)
195-
->filter(fn (RouteClosure $closure) => $closure->name)
195+
->filter(fn (RouteClosure $closure) => $closure->name !== null)
196196
->values()
197197
->mapWithKeys(function (RouteClosure $closure) use ($mappingFunction) {
198198
return $mappingFunction($closure);

src/Laravel/LaravelRouteActionTypesProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ protected function parseRouteParameterCollection(RouteParameterCollection $colle
249249
}, $collection->parameters));
250250
}
251251

252-
protected function parseRouteParameter(RouteParameter $parameter): TypeScriptNode
252+
protected function parseRouteParameter(RouteParameter $parameter): TypeScriptProperty
253253
{
254254
return new TypeScriptProperty(
255255
$parameter->name,

src/Laravel/Support/WithoutRoutes.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public function shouldHide(Route $route): bool
1919

2020
public static function satisfying(Closure $closure): self
2121
{
22-
return new static($closure);
22+
return new self($closure);
2323
}
2424

2525
public static function named(string ...$names): self

src/PhpNodes/PhpClassNode.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@ public function __construct(
2020
) {
2121
}
2222

23-
public static function fromClassString(string $classString): static
23+
public static function fromClassString(string $classString): self
2424
{
2525
return self::fromReflection(new ReflectionClass($classString));
2626
}
2727

28-
public static function fromReflection(ReflectionClass|RoaveReflectionClass $reflection): static
28+
public static function fromReflection(ReflectionClass|RoaveReflectionClass $reflection): self
2929
{
3030
if ($reflection instanceof RoaveReflectionEnum) {
3131
return new PhpEnumNode($reflection);
3232
}
3333

3434
if ($reflection->isEnum()) {
35-
return new PhpEnumNode(new ReflectionEnum($reflection->name));
35+
return new PhpEnumNode(new ReflectionEnum($reflection->getName()));
3636
}
3737

3838
return new self($reflection);

0 commit comments

Comments
 (0)