Skip to content

Commit 0e2d8c2

Browse files
committed
Add source info to class and property hooks
1 parent 3112466 commit 0e2d8c2

File tree

4 files changed

+87
-35
lines changed

4 files changed

+87
-35
lines changed

src/Mapping/Metadata/ClassInfo.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
/**
1111
* @template T of object
1212
*/
13-
final class ClassInfo
13+
final class ClassInfo extends MetadataInfo
1414
{
1515
/**
1616
* @var array<non-empty-string, PropertyInfo>
@@ -33,7 +33,10 @@ public function __construct(
3333
* @var class-string<T>
3434
*/
3535
public readonly string $name,
36-
) {}
36+
?SourceInfo $source = null,
37+
) {
38+
parent::__construct($source);
39+
}
3740

3841
/**
3942
* @param non-empty-string $name

src/Mapping/Provider/MetadataReaderProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public function getClassMetadata(
5454
): ClassMetadata {
5555
$info = $this->reader->read($class);
5656

57+
dd($info);
58+
5759
return $this->toClassMetadata($info, $types, $parser);
5860
}
5961

src/Mapping/Reader/MetadataReader.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace TypeLang\Mapper\Mapping\Reader;
66

77
use TypeLang\Mapper\Mapping\Metadata\ClassInfo;
8+
use TypeLang\Mapper\Mapping\Metadata\SourceInfo;
89
use TypeLang\Mapper\Mapping\Reader\MetadataReader\ClassMetadataLoaderInterface;
910
use TypeLang\Mapper\Mapping\Reader\MetadataReader\PropertyMetadataLoaderInterface;
1011

@@ -20,6 +21,15 @@ public function read(\ReflectionClass $class): ClassInfo
2021
{
2122
$classInfo = parent::read($class);
2223

24+
if ($classInfo->source === null) {
25+
$file = $class->getFileName();
26+
$line = $class->getStartLine();
27+
28+
if (\is_string($file) && $line > 0) {
29+
$classInfo->source = new SourceInfo($file, $line);
30+
}
31+
}
32+
2333
foreach ($this->classLoaders as $classLoader) {
2434
$classLoader->load($classInfo, $class);
2535
}

src/Mapping/Reader/ReflectionReader/TypePropertyReflectionLoader.php

Lines changed: 70 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,74 +17,105 @@ public function load(PropertyInfo $info, \ReflectionProperty $property): void
1717
$this->loadWriteType($property, $info);
1818
}
1919

20-
private function findSourceMap(\ReflectionProperty $property): ?SourceInfo
21-
{
22-
$class = $property->getDeclaringClass();
23-
24-
if ($class->isInternal()) {
25-
return null;
26-
}
27-
28-
$file = $class->getFileName();
29-
$line = $class->getStartLine();
30-
31-
if ($file === false || $line < 1) {
32-
return null;
33-
}
34-
35-
return new SourceInfo($file, $line);
36-
}
37-
3820
private function loadReadType(\ReflectionProperty $property, PropertyInfo $info): void
3921
{
40-
$definition = $this->getReadTypeDefinition($property);
22+
$definition = $this->getReadTypeInfo($property);
4123

42-
$info->read = $info->write = new TypeInfo($definition, $this->findSourceMap($property));
24+
$info->read = $info->write = $definition;
4325
}
4426

4527
private function loadWriteType(\ReflectionProperty $property, PropertyInfo $info): void
4628
{
47-
$definition = $this->findWriteTypeDefinition($property);
29+
$definition = $this->findWriteTypeInfo($property);
4830

4931
if ($definition === null) {
5032
return;
5133
}
5234

53-
$info->write = new TypeInfo($definition, $this->findSourceMap($property));
35+
$info->write = $definition;
5436
}
5537

5638
/**
57-
* @return non-empty-string
5839
* @throws \InvalidArgumentException
5940
*/
60-
private function findWriteTypeDefinition(\ReflectionProperty $property): ?string
41+
private function findWriteTypeInfo(\ReflectionProperty $property): ?TypeInfo
6142
{
6243
if (\PHP_VERSION_ID < 80400) {
6344
return null;
6445
}
6546

47+
// Force skip in case of setter is not defined
48+
if ($property->getHook(\PropertyHookType::Set) === null) {
49+
return null;
50+
}
51+
52+
$definition = $this->createMixedTypeDefinition();
6653
$type = $property->getSettableType();
6754

68-
if ($type === null) {
69-
return $this->createMixedTypeDefinition();
55+
if ($type !== null) {
56+
$definition = $this->createTypeDefinition($type);
57+
}
58+
59+
return new TypeInfo(
60+
definition: $definition,
61+
source: $this->getWriteHookSourceInfo($property),
62+
);
63+
}
64+
65+
private function getWriteHookSourceInfo(\ReflectionProperty $property): ?SourceInfo
66+
{
67+
if (\PHP_VERSION_ID < 80400) {
68+
return null;
7069
}
7170

72-
return $this->createTypeDefinition($type);
71+
return $this->getHookSourceInfo(
72+
hook: $property->getHook(\PropertyHookType::Set),
73+
);
7374
}
7475

7576
/**
76-
* @return non-empty-string
7777
* @throws \InvalidArgumentException
7878
*/
79-
private function getReadTypeDefinition(\ReflectionProperty $property): string
79+
private function getReadTypeInfo(\ReflectionProperty $property): TypeInfo
8080
{
81+
$definition = $this->createMixedTypeDefinition();
8182
$type = $property->getType();
8283

83-
if ($type === null) {
84-
return $this->createMixedTypeDefinition();
84+
if ($type !== null) {
85+
$definition = $this->createTypeDefinition($type);
8586
}
8687

87-
return $this->createTypeDefinition($type);
88+
return new TypeInfo(
89+
definition: $definition,
90+
source: $this->getReadHookSourceInfo($property),
91+
);
92+
}
93+
94+
private function getReadHookSourceInfo(\ReflectionProperty $property): ?SourceInfo
95+
{
96+
if (\PHP_VERSION_ID < 80400) {
97+
return null;
98+
}
99+
100+
return $this->getHookSourceInfo(
101+
hook: $property->getHook(\PropertyHookType::Get),
102+
);
103+
}
104+
105+
private function getHookSourceInfo(?\ReflectionMethod $hook): ?SourceInfo
106+
{
107+
if ($hook === null) {
108+
return null;
109+
}
110+
111+
$file = $hook->getFileName();
112+
$line = $hook->getStartLine();
113+
114+
if (\is_string($file) && $file !== '' && $line > 0) {
115+
return new SourceInfo($file, $line);
116+
}
117+
118+
return null;
88119
}
89120

90121
/**
@@ -131,9 +162,15 @@ private function createNamedTypeDefinition(\ReflectionNamedType $type): string
131162
*/
132163
private function createNonNullNamedTypeDefinition(\ReflectionNamedType $type): string
133164
{
165+
$literal = $type->getName();
166+
167+
// PHP 8.4 Setter's type bug
168+
if (\str_starts_with($literal, '?')) {
169+
$literal = \substr($literal, 1);
170+
}
171+
134172
/** @phpstan-ignore-next-line : Type's name cannot be empty */
135173
$name = new Name($type->getName());
136-
$literal = $name->toString();
137174

138175
if ($type->isBuiltin() || $name->isSpecial() || $name->isBuiltin()) {
139176
return $literal;

0 commit comments

Comments
 (0)