Skip to content

Commit 5387d90

Browse files
committed
Fix type loading logic
1 parent 05dca00 commit 5387d90

29 files changed

+150
-159
lines changed

bench/src/Serializers/TypeLangAttributesBench.php

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@
1010
use PhpBench\Attributes\Warmup;
1111
use TypeLang\Mapper\Bench\Stub\ExampleRequestDTO;
1212
use TypeLang\Mapper\Mapper;
13-
use TypeLang\Mapper\Mapping\Provider\AttributeDriver;
14-
use TypeLang\Mapper\Mapping\Provider\Psr16CachedDriver;
15-
use TypeLang\Mapper\Mapping\Provider\ReflectionDriver;
13+
use TypeLang\Mapper\Mapping\Provider\Psr16CacheProvider;
14+
use TypeLang\Mapper\Mapping\Reader\AttributeReader;
1615
use TypeLang\Mapper\Platform\StandardPlatform;
1716

1817
#[Revs(30), Warmup(3), Iterations(5), BeforeMethods('prepare')]
@@ -25,14 +24,12 @@ public function prepare(): void
2524
{
2625
parent::prepare();
2726

28-
$driver = new AttributeDriver(
29-
delegate: new ReflectionDriver(),
30-
);
27+
$driver = new AttributeReader();
3128

3229
$this->cached = new Mapper(
3330
platform: new StandardPlatform(
34-
meta: new Psr16CachedDriver(
35-
cache: $this->psr16,
31+
meta: new Psr16CacheProvider(
32+
psr16: $this->psr16,
3633
delegate: $driver,
3734
),
3835
),

bench/src/Serializers/TypeLangDocBlockBench.php

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
use PhpBench\Attributes\Warmup;
1111
use TypeLang\Mapper\Bench\Stub\ExampleRequestDTO;
1212
use TypeLang\Mapper\Mapper;
13-
use TypeLang\Mapper\Mapping\Provider\DocBlockDriver;
14-
use TypeLang\Mapper\Mapping\Provider\Psr16CachedDriver;
15-
use TypeLang\Mapper\Mapping\Provider\ReflectionDriver;
13+
use TypeLang\Mapper\Mapping\Provider\Psr16CacheProvider;
14+
use TypeLang\Mapper\Mapping\Reader\PhpDocReader;
15+
use TypeLang\Mapper\Mapping\Reader\ReflectionReader;
1616
use TypeLang\Mapper\Platform\StandardPlatform;
1717

1818
#[Revs(30), Warmup(3), Iterations(5), BeforeMethods('prepare')]
@@ -25,14 +25,12 @@ public function prepare(): void
2525
{
2626
parent::prepare();
2727

28-
$driver = new DocBlockDriver(
29-
delegate: new ReflectionDriver(),
30-
);
28+
$driver = new PhpDocReader();
3129

3230
$this->cached = new Mapper(
3331
platform: new StandardPlatform(
34-
meta: new Psr16CachedDriver(
35-
cache: $this->psr16,
32+
meta: new Psr16CacheProvider(
33+
psr16: $this->psr16,
3634
delegate: $driver,
3735
),
3836
),

src/Mapper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use JetBrains\PhpStorm\Language;
88
use TypeLang\Mapper\Exception\Definition\TypeNotFoundException;
9+
use TypeLang\Mapper\Mapping\Reference\Reader\NativeReferencesReader;
910
use TypeLang\Mapper\Platform\PlatformInterface;
1011
use TypeLang\Mapper\Platform\StandardPlatform;
1112
use TypeLang\Mapper\Runtime\Configuration;
@@ -19,7 +20,6 @@
1920
use TypeLang\Mapper\Runtime\Parser\TypeParserInterface;
2021
use TypeLang\Mapper\Runtime\Repository\InMemoryTypeRepository;
2122
use TypeLang\Mapper\Runtime\Repository\LoggableTypeRepository;
22-
use TypeLang\Mapper\Runtime\Repository\Reference\Reader\NativeReferencesReader;
2323
use TypeLang\Mapper\Runtime\Repository\TraceableTypeRepository;
2424
use TypeLang\Mapper\Runtime\Repository\TypeRepository;
2525
use TypeLang\Mapper\Runtime\Repository\TypeRepositoryInterface;

src/Mapping/Metadata/ClassMetadata.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ public function __construct(
3030
* and denormalization.
3131
*
3232
* @readonly
33+
*
3334
* @psalm-readonly-allow-private-mutation
35+
*
3436
* @var array<non-empty-string, PropertyMetadata>
3537
*/
3638
public array $properties = [],
@@ -40,6 +42,7 @@ public function __construct(
4042
* has been registered in the {@see ClassMetadata} instance.
4143
*
4244
* @readonly
45+
*
4346
* @psalm-readonly-allow-private-mutation
4447
*/
4548
public ?DiscriminatorMetadata $discriminator = null,

src/Mapping/Provider/MetadataReaderProvider.php

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
use TypeLang\Mapper\Mapping\Metadata\TypeMetadata;
3333
use TypeLang\Mapper\Mapping\Reader\ReaderInterface;
3434
use TypeLang\Mapper\Mapping\Reader\ReflectionReader;
35+
use TypeLang\Mapper\Mapping\Reference\Reader\NativeReferencesReader;
36+
use TypeLang\Mapper\Mapping\Reference\Reader\ReferencesReaderInterface;
37+
use TypeLang\Mapper\Mapping\Reference\ReferencesResolver;
3538
use TypeLang\Mapper\Runtime\Parser\TypeParserInterface;
3639
use TypeLang\Mapper\Runtime\Repository\TypeRepositoryInterface;
3740

@@ -40,13 +43,18 @@ final class MetadataReaderProvider implements ProviderInterface
4043
/**
4144
* @var array<class-string, ClassMetadata<object>>
4245
*/
43-
private array $references = [];
46+
private array $metadata = [];
47+
48+
private readonly ReferencesResolver $references;
4449

4550
public function __construct(
4651
private readonly ReaderInterface $reader = new ReflectionReader(),
4752
private ?ExpressionLanguage $expression = null,
4853
private readonly ?ClockInterface $clock = null,
49-
) {}
54+
ReferencesReaderInterface $references = new NativeReferencesReader(),
55+
) {
56+
$this->references = new ReferencesResolver($references);
57+
}
5058

5159
private function now(): ?int
5260
{
@@ -61,7 +69,6 @@ private function now(): ?int
6169
* @param \ReflectionClass<TArg> $class
6270
*
6371
* @return ClassMetadata<TArg>
64-
*
6572
* @throws \Throwable
6673
*/
6774
public function getClassMetadata(
@@ -92,20 +99,22 @@ private function toProxyClassMetadata(
9299
TypeParserInterface $parser,
93100
): ClassMetadata {
94101
/** @var ClassMetadata<TArg> */
95-
return $this->references[$class->name] ??=
102+
return $this->metadata[$class->name] ??=
96103
(new \ReflectionClass(ClassMetadata::class))
97104
->newLazyProxy(function () use ($class, $types, $parser): ClassMetadata {
98105
$info = $this->reader->read($class);
99106

100107
$metadata = new ClassMetadata(
101108
name: $info->name,
102109
properties: $this->toPropertiesMetadata(
110+
context: $class,
103111
parent: $info,
104112
properties: $info->properties,
105113
types: $types,
106114
parser: $parser,
107115
),
108116
discriminator: $this->toOptionalDiscriminator(
117+
context: $class,
109118
parent: $info,
110119
info: $info->discriminator,
111120
types: $types,
@@ -116,7 +125,7 @@ private function toProxyClassMetadata(
116125
createdAt: $this->now(),
117126
);
118127

119-
unset($this->references[$class->name]);
128+
unset($this->metadata[$class->name]);
120129

121130
return $metadata;
122131
});
@@ -135,14 +144,14 @@ private function toLazyInitializedClassMetadata(
135144
TypeRepositoryInterface $types,
136145
TypeParserInterface $parser,
137146
): ClassMetadata {
138-
if (isset($this->references[$class->name])) {
147+
if (isset($this->metadata[$class->name])) {
139148
/** @var ClassMetadata<TArg> */
140-
return $this->references[$class->name];
149+
return $this->metadata[$class->name];
141150
}
142151

143152
$info = $this->reader->read($class);
144153

145-
$this->references[$class->name] = $metadata = new ClassMetadata(
154+
$this->metadata[$class->name] = $metadata = new ClassMetadata(
146155
name: $info->name,
147156
isNormalizeAsArray: $info->isNormalizeAsArray,
148157
typeErrorMessage: $info->typeErrorMessage,
@@ -151,6 +160,7 @@ private function toLazyInitializedClassMetadata(
151160

152161
/** @phpstan-ignore-next-line : Allow readonly writing */
153162
$metadata->properties = $this->toPropertiesMetadata(
163+
context: $class,
154164
parent: $info,
155165
properties: $info->properties,
156166
types: $types,
@@ -159,26 +169,29 @@ private function toLazyInitializedClassMetadata(
159169

160170
/** @phpstan-ignore-next-line : Allow readonly writing */
161171
$metadata->discriminator = $this->toOptionalDiscriminator(
172+
context: $class,
162173
parent: $info,
163174
info: $info->discriminator,
164175
types: $types,
165176
parser: $parser,
166177
);
167178

168-
unset($this->references[$class->name]);
179+
unset($this->metadata[$class->name]);
169180

170181
/** @var ClassMetadata<TArg> */
171182
return $metadata;
172183
}
173184

174185
/**
186+
* @param \ReflectionClass<object> $context
175187
* @param ClassInfo<object> $parent
176188
* @param iterable<mixed, PropertyInfo> $properties
177189
*
178190
* @return array<non-empty-string, PropertyMetadata>
179191
* @throws \Throwable
180192
*/
181193
private function toPropertiesMetadata(
194+
\ReflectionClass $context,
182195
ClassInfo $parent,
183196
iterable $properties,
184197
TypeRepositoryInterface $types,
@@ -187,31 +200,33 @@ private function toPropertiesMetadata(
187200
$result = [];
188201

189202
foreach ($properties as $property) {
190-
$result[$property->name] = $this->toPropertyMetadata($parent, $property, $types, $parser);
203+
$result[$property->name] = $this->toPropertyMetadata($context, $parent, $property, $types, $parser);
191204
}
192205

193206
return $result;
194207
}
195208

196209
/**
210+
* @param \ReflectionClass<object> $context
197211
* @param ClassInfo<object> $parent
198212
*
199213
* @throws \Throwable
200214
*/
201215
private function toPropertyMetadata(
216+
\ReflectionClass $context,
202217
ClassInfo $parent,
203218
PropertyInfo $property,
204219
TypeRepositoryInterface $types,
205220
TypeParserInterface $parser,
206221
): PropertyMetadata {
207222
try {
208-
$read = $this->toTypeMetadata($property->read, $types, $parser);
223+
$read = $this->toTypeMetadata($context, $property->read, $types, $parser);
209224
} catch (TypeNotFoundException $e) {
210225
throw $this->toPropertyTypeException($e, $parent, $property, $property->read);
211226
}
212227

213228
try {
214-
$write = $this->toTypeMetadata($property->write, $types, $parser);
229+
$write = $this->toTypeMetadata($context, $property->write, $types, $parser);
215230
} catch (TypeNotFoundException $e) {
216231
throw $this->toPropertyTypeException($e, $parent, $property, $property->write);
217232
}
@@ -309,11 +324,13 @@ private function toDefaultValueMetadata(DefaultValueInfo $info): DefaultValueMet
309324
}
310325

311326
/**
327+
* @param \ReflectionClass<object> $context
312328
* @param ClassInfo<object> $parent
313329
*
314330
* @throws \Throwable
315331
*/
316332
private function toOptionalDiscriminator(
333+
\ReflectionClass $context,
317334
ClassInfo $parent,
318335
?DiscriminatorInfo $info,
319336
TypeRepositoryInterface $types,
@@ -323,15 +340,17 @@ private function toOptionalDiscriminator(
323340
return null;
324341
}
325342

326-
return $this->toDiscriminator($parent, $info, $types, $parser);
343+
return $this->toDiscriminator($context, $parent, $info, $types, $parser);
327344
}
328345

329346
/**
347+
* @param \ReflectionClass<object> $context
330348
* @param ClassInfo<object> $parent
331349
*
332350
* @throws \Throwable
333351
*/
334352
private function toDiscriminator(
353+
\ReflectionClass $context,
335354
ClassInfo $parent,
336355
DiscriminatorInfo $info,
337356
TypeRepositoryInterface $types,
@@ -341,37 +360,42 @@ private function toDiscriminator(
341360

342361
return new DiscriminatorMetadata(
343362
field: $info->field,
344-
map: $this->toDiscriminatorMap($info->map, $types, $parser),
345-
default: $this->toOptionalTypeMetadata($info->default, $types, $parser),
363+
map: $this->toDiscriminatorMap($context, $info->map, $types, $parser),
364+
default: $this->toOptionalTypeMetadata($context, $info->default, $types, $parser),
346365
createdAt: $this->now(),
347366
);
348367
}
349368

350369
/**
370+
* @param \ReflectionClass<object> $context
351371
* @param non-empty-array<non-empty-string, TypeInfo> $map
352372
*
353373
* @return non-empty-array<non-empty-string, TypeMetadata>
354374
* @throws \Throwable
355375
*/
356376
private function toDiscriminatorMap(
377+
\ReflectionClass $context,
357378
array $map,
358379
TypeRepositoryInterface $types,
359380
TypeParserInterface $parser,
360381
): array {
361382
$result = [];
362383

363384
foreach ($map as $value => $type) {
364-
$result[$value] = $this->toTypeMetadata($type, $types, $parser);
385+
$result[$value] = $this->toTypeMetadata($context, $type, $types, $parser);
365386
}
366387

367388
/** @var non-empty-array<non-empty-string, TypeMetadata> $result */
368389
return $result;
369390
}
370391

371392
/**
393+
* @param \ReflectionClass<object> $context
394+
*
372395
* @throws \Throwable
373396
*/
374397
private function toOptionalTypeMetadata(
398+
\ReflectionClass $context,
375399
?TypeInfo $type,
376400
TypeRepositoryInterface $types,
377401
TypeParserInterface $parser,
@@ -380,13 +404,16 @@ private function toOptionalTypeMetadata(
380404
return null;
381405
}
382406

383-
return $this->toTypeMetadata($type, $types, $parser);
407+
return $this->toTypeMetadata($context, $type, $types, $parser);
384408
}
385409

386410
/**
411+
* @param \ReflectionClass<object> $context
412+
*
387413
* @throws \Throwable
388414
*/
389415
private function toTypeMetadata(
416+
\ReflectionClass $context,
390417
TypeInfo $info,
391418
TypeRepositoryInterface $types,
392419
TypeParserInterface $parser,
@@ -400,6 +427,8 @@ private function toTypeMetadata(
400427
))
401428
};
402429

430+
$statement = $this->references->resolve($statement, $context);
431+
403432
$type = $types->getTypeByStatement($statement);
404433

405434
return new TypeMetadata(

src/Runtime/Repository/Reference/Reader/NativeReferencesReader.php renamed to src/Mapping/Reference/Reader/NativeReferencesReader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace TypeLang\Mapper\Runtime\Repository\Reference\Reader;
5+
namespace TypeLang\Mapper\Mapping\Reference\Reader;
66

77
final class NativeReferencesReader implements ReferencesReaderInterface
88
{

src/Runtime/Repository/Reference/Reader/NullReferencesReader.php renamed to src/Mapping/Reference/Reader/NullReferencesReader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace TypeLang\Mapper\Runtime\Repository\Reference\Reader;
5+
namespace TypeLang\Mapper\Mapping\Reference\Reader;
66

77
final class NullReferencesReader implements ReferencesReaderInterface
88
{

src/Runtime/Repository/Reference/Reader/ReferencesReaderInterface.php renamed to src/Mapping/Reference/Reader/ReferencesReaderInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace TypeLang\Mapper\Runtime\Repository\Reference\Reader;
5+
namespace TypeLang\Mapper\Mapping\Reference\Reader;
66

77
interface ReferencesReaderInterface
88
{

0 commit comments

Comments
 (0)