Skip to content

Commit 637872c

Browse files
committed
WIP: fixes
1 parent e5eec9a commit 637872c

File tree

4 files changed

+49
-23
lines changed

4 files changed

+49
-23
lines changed

src/Compiler/Php/PhpCodeBuilder.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,12 @@
6767
use function is_array;
6868
use function is_object;
6969
use function ksort;
70+
use function serialize;
7071
use function str_ends_with;
7172
use function strrpos;
7273
use function substr;
74+
use function unserialize;
75+
7376

7477
class PhpCodeBuilder extends BuilderFactory
7578
{
@@ -430,8 +433,18 @@ public function mapperMethod(string $methodName, MapperCompiler $mapperCompiler)
430433
$this->importType($inputType);
431434
$this->importType($outputType);
432435

433-
$nativeInputType = PhpDocTypeUtils::toNativeType($inputType, $phpDocInputTypeUseful);
434-
$nativeOutputType = PhpDocTypeUtils::toNativeType($outputType, $phpDocOutputTypeUseful);
436+
$clonedGenericParameters = [];
437+
foreach ($this->genericParameters as $genericParameter) {
438+
$clonedGenericParameter = unserialize(serialize($genericParameter));
439+
$clonedGenericParameters[] = $clonedGenericParameter;
440+
441+
if ($clonedGenericParameter->bound !== null) {
442+
$this->importType($clonedGenericParameter->bound);
443+
}
444+
}
445+
446+
$nativeInputType = PhpDocTypeUtils::toNativeType($inputType, $clonedGenericParameters, $phpDocInputTypeUseful);
447+
$nativeOutputType = PhpDocTypeUtils::toNativeType($outputType, $clonedGenericParameters, $phpDocOutputTypeUseful);
435448

436449
$phpDoc = $this->phpDoc([
437450
$phpDocInputTypeUseful ? "@param {$inputType} \${$dataVarName}" : null,

src/Compiler/Type/PhpDocTypeUtils.php

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use ReflectionNamedType;
3434
use ReflectionType;
3535
use ReflectionUnionType;
36+
use ShipMonk\InputMapper\Compiler\Mapper\GenericMapperParameter;
3637
use ShipMonk\InputMapper\Runtime\Optional;
3738
use ShipMonk\InputMapper\Runtime\OptionalNone;
3839
use ShipMonk\InputMapper\Runtime\OptionalSome;
@@ -133,13 +134,24 @@ public static function fromReflectionType(ReflectionType $reflectionType): TypeN
133134
return new IdentifierTypeNode('mixed');
134135
}
135136

136-
public static function toNativeType(TypeNode $type, ?bool &$phpDocUseful): ComplexType|Identifier|Name
137+
138+
/**
139+
* @param list<GenericMapperParameter> $genericParameters
140+
*/
141+
public static function toNativeType(TypeNode $type, array $genericParameters, ?bool &$phpDocUseful): ComplexType|Identifier|Name
137142
{
138143
if ($phpDocUseful === null) {
139144
$phpDocUseful = false;
140145
}
141146

142147
if ($type instanceof IdentifierTypeNode) {
148+
foreach ($genericParameters as $genericParameter) {
149+
if ($genericParameter->name === $type->name) {
150+
$phpDocUseful = true;
151+
return self::toNativeType($genericParameter->bound ?? new IdentifierTypeNode('mixed'), $genericParameters, $phpDocUseful);
152+
}
153+
}
154+
143155
if (!self::isKeyword($type)) {
144156
return new Name($type->name);
145157
}
@@ -161,7 +173,7 @@ public static function toNativeType(TypeNode $type, ?bool &$phpDocUseful): Compl
161173
}
162174

163175
if ($type instanceof NullableTypeNode) {
164-
return NativeTypeUtils::createNullable(self::toNativeType($type->type, $phpDocUseful));
176+
return NativeTypeUtils::createNullable(self::toNativeType($type->type, $genericParameters, $phpDocUseful));
165177
}
166178

167179
if ($type instanceof ArrayTypeNode || $type instanceof ArrayShapeNode) {
@@ -181,14 +193,14 @@ public static function toNativeType(TypeNode $type, ?bool &$phpDocUseful): Compl
181193

182194
if ($type instanceof GenericTypeNode) {
183195
$phpDocUseful = true;
184-
return self::toNativeType($type->type, $phpDocUseful);
196+
return self::toNativeType($type->type, $genericParameters, $phpDocUseful);
185197
}
186198

187199
if ($type instanceof UnionTypeNode) {
188200
$types = [];
189201

190202
foreach ($type->types as $inner) {
191-
$types[] = self::toNativeType($inner, $phpDocUseful);
203+
$types[] = self::toNativeType($inner, $genericParameters, $phpDocUseful);
192204
}
193205

194206
return NativeTypeUtils::createUnion(...$types);
@@ -198,7 +210,7 @@ public static function toNativeType(TypeNode $type, ?bool &$phpDocUseful): Compl
198210
$types = [];
199211

200212
foreach ($type->types as $inner) {
201-
$types[] = self::toNativeType($inner, $phpDocUseful);
213+
$types[] = self::toNativeType($inner, $genericParameters, $phpDocUseful);
202214
}
203215

204216
return NativeTypeUtils::createIntersection(...$types);

src/Runtime/MapperProvider.php

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use LogicException;
66
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
7+
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
78
use RuntimeException;
89
use ShipMonk\InputMapper\Compiler\MapperFactory\DefaultMapperCompilerFactoryProvider;
910
use ShipMonk\InputMapper\Compiler\MapperFactory\MapperCompilerFactoryProvider;
@@ -79,6 +80,16 @@ public function getGeneric(string $inputClassName, array $innerMappers): Mapper
7980
return $mapper;
8081
}
8182

83+
// /**
84+
// * @return Mapper<mixed>
85+
// */
86+
// public function getForTypeNode(TypeNode $typeNode): Mapper
87+
// {
88+
// $key = (string) $typeNode;
89+
// $mapper = $this->mappers[$key] ??= $this->create($inputClassName, $innerMappers);
90+
// return $mapper;
91+
// }
92+
8293
/**
8394
* @template T of object
8495
* @param class-string<T> $inputClassName
@@ -114,18 +125,13 @@ private function create(string $inputClassName, array $innerMappers): Mapper
114125
$mapperClassName = $this->getMapperClass($inputClassName);
115126

116127
if (!class_exists($mapperClassName, autoload: false)) {
117-
$this->load($inputClassName, $mapperClassName);
128+
$this->load(new IdentifierTypeNode($inputClassName), $mapperClassName);
118129
}
119130

120131
return new $mapperClassName($this, $innerMappers);
121132
}
122133

123-
/**
124-
* @template T of object
125-
* @param class-string<T> $inputClassName
126-
* @param class-string<Mapper<T>> $mapperClassName
127-
*/
128-
private function load(string $inputClassName, string $mapperClassName): void
134+
private function load(TypeNode $type, string $mapperClassName): void
129135
{
130136
$path = $this->getMapperPath($mapperClassName);
131137

@@ -148,7 +154,7 @@ private function load(string $inputClassName, string $mapperClassName): void
148154
}
149155

150156
if (!is_file($path) || $this->autoRefresh) {
151-
$code = $this->compile($inputClassName, $mapperClassName);
157+
$code = $this->compile($type, $mapperClassName);
152158

153159
if (file_put_contents("$path.tmp", $code) !== strlen($code) || !rename("$path.tmp", $path)) {
154160
@unlink("$path.tmp"); // @ file may not exist
@@ -163,15 +169,10 @@ private function load(string $inputClassName, string $mapperClassName): void
163169
flock($handle, LOCK_UN);
164170
}
165171

166-
/**
167-
* @template T of object
168-
* @param class-string<T> $inputClassName
169-
* @param class-string<Mapper<T>> $mapperClassName
170-
*/
171-
private function compile(string $inputClassName, string $mapperClassName): string
172+
private function compile(TypeNode $type, string $mapperClassName): string
172173
{
173174
$mapperCompilerFactory = $this->mapperCompilerFactoryProvider->get();
174-
$mapperCompiler = $mapperCompilerFactory->create(new IdentifierTypeNode($inputClassName));
175+
$mapperCompiler = $mapperCompilerFactory->create($type);
175176

176177
$codeBuilder = new PhpCodeBuilder();
177178
$codePrinter = new PhpCodePrinter();

tests/Compiler/Type/PhpDocTypeUtilsTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public function testToNativeType(
147147
bool $expectedIsPhpDocUseful
148148
): void
149149
{
150-
$nativeType = PhpDocTypeUtils::toNativeType($type, $phpDocUseful);
150+
$nativeType = PhpDocTypeUtils::toNativeType($type, [], $phpDocUseful);
151151

152152
self::assertEquals($expectedNative, $nativeType);
153153
self::assertSame($expectedIsPhpDocUseful, $phpDocUseful);

0 commit comments

Comments
 (0)