8000 bug #59963 [TypeInfo] Fix ``@var`` tag reading for promoted propertie… · symfony/symfony@9f7257e · GitHub
[go: up one dir, main page]

Skip to content

Commit 9f7257e

Browse files
bug #59963 [TypeInfo] Fix @var tag reading for promoted properties (mtarld)
This PR was merged into the 7.2 branch. Discussion ---------- [TypeInfo] Fix ``@var`` tag reading for promoted properties | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #59959 | License | MIT Read either ``@param`` and ``@var`` tags for promoted properties. Commits ------- 3291bf3 [TypeInfo] Fix promoted property with ``@var`` tag
2 parents 6471d4a + 3291bf3 commit 9f7257e

File tree

3 files changed

+36
-23
lines changed

3 files changed

+36
-23
lines changed

src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithPhpDoc.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,18 @@ final class DummyWithPhpDoc
1111

1212
/**
1313
* @param bool $promoted
14+
* @param bool $promotedVarAndParam
1415
*/
1516
public function __construct(
1617
public mixed $promoted,
18+
/**
19+
* @var string
20+
*/
21+
public mixed $promotedVar,
22+
/**
23+
* @var string
24+
*/
25+
public mixed $promotedVarAndParam,
1726
) {
1827
}
1928

src/Symfony/Component/TypeInfo/Tests/TypeResolver/PhpDocAwareReflectionTypeResolverTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public function testReadPhpDoc()
2929

3030
$this->assertEquals(Type::array(Type::object(Dummy::class)), $resolver->resolve($reflection->getProperty('arrayOfDummies')));
3131
$this->assertEquals(Type::bool(), $resolver->resolve($reflection->getProperty('promoted')));
32+
$this->assertEquals(Type::string(), $resolver->resolve($reflection->getProperty('promotedVar')));
33+
$this->assertEquals(Type::string(), $resolver->resolve($reflection->getProperty('promotedVarAndParam')));
3234
$this->assertEquals(Type::object(Dummy::class), $resolver->resolve($reflection->getMethod('getNextDummy')));
3335
$this->assertEquals(Type::object(Dummy::class), $resolver->resolve($reflection->getMethod('getNextDummy')->getParameters()[0]));
3436
}

src/Symfony/Component/TypeInfo/TypeResolver/PhpDocAwareReflectionTypeResolver.php

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -64,36 +64,38 @@ public function resolve(mixed $subject, ?TypeContext $typeContext = null): Type
6464
throw new UnsupportedException(\sprintf('Expected subject to be a "ReflectionProperty", a "ReflectionParameter" or a "ReflectionFunctionAbstract", "%s" given.', get_debug_type($subject)), $subject);
6565
}
6666

67-
$docComment = match (true) {
68-
$subject instanceof \ReflectionProperty => $subject->isPromoted() ? $subject->getDeclaringClass()?->getConstructor()?->getDocComment() : $subject->getDocComment(),
69-
$subject instanceof \ReflectionParameter => $subject->getDeclaringFunction()->getDocComment(),
70-
$subject instanceof \ReflectionFunctionAbstract => $subject->getDocComment(),
67+
$typeContext ??= $this->typeContextFactory->createFromReflection($subject);
68+
69+
$docComments = match (true) {
70+
$subject instanceof \ReflectionProperty => $subject->isPromoted()
71+
? ['@var' => $subject->getDocComment(), '@param' => $subject->getDeclaringClass()?->getConstructor()?->getDocComment()]
72+
: ['@var' => $subject->getDocComment()],
73+
$subject instanceof \ReflectionParameter => ['@param' => $subject->getDeclaringFunction()->getDocComment()],
74+
$subject instanceof \ReflectionFunctionAbstract => ['@return' => $subject->getDocComment()],
7175
};
7276

73-
if (!$docComment) {
74-
return $this->reflectionTypeResolver->resolve($subject);
75-
}
77+
foreach ($docComments as $tagName => $docComment) {
78+
if (!$docComment) {
79+
continue;
80+
}
7681

77-
$typeContext ??= $this->typeContextFactory->createFromReflection($subject);
82+
$tokens = new TokenIterator($this->lexer->tokenize($docComment));
83+
$docNode = $this->phpDocParser->parse($tokens);
7884

79-
$tagName = match (true) {
80-
$subject instanceof \ReflectionProperty => $subject->isPromoted() ? '@param' : '@var',
81-
$subject instanceof \ReflectionParameter => '@param',
82-
$subject instanceof \ReflectionFunctionAbstract => '@return',
83-
};
85+
foreach ($docNode->getTagsByName($tagName) as $tag) {
86+
$tagValue = $tag->value;
8487

85-
$tokens = new TokenIterator($this->lexer->tokenize($docComment));
86-
$docNode = $this->phpDocParser->parse($tokens);
88+
if ('@var' === $tagName && $tagValue instanceof VarTagValueNode) {
89+
return $this->stringTypeResolver->resolve((string) $tagValue, $typeContext);
90+
}
8791

88-
foreach ($docNode->getTagsByName($tagName) as $tag) {
89-
$tagValue = $tag->value;
92+
if ('@param' === $tagName && $tagValue instanceof ParamTagValueNode && '$'.$subject->getName() === $tagValue->parameterName) {
93+
return $this->stringTypeResolver->resolve((string) $tagValue, $typeContext);
94+
}
9095

91-
if (
92-
$tagValue instanceof VarTagValueNode
93-
|| $tagValue instanceof ParamTagValueNode && $tagName && '$'.$subject->getName() === $tagValue->parameterName
94-
|| $tagValue instanceof ReturnTagValueNode
95-
) {
96-
return $this->stringTypeResolver->resolve((string) $tagValue, $typeContext);
96+
if ('@return' === $tagName && $tagValue instanceof ReturnTagValueNode) {
97+
return $this->stringTypeResolver->resolve((string) $tagValue, $typeContext);
98+
}
9799
}
98100
}
99101

0 commit comments

Comments
 (0)
0