Skip to content

Commit 65f6b8c

Browse files
Add support for inheritors tag
1 parent 0a8e718 commit 65f6b8c

File tree

5 files changed

+126
-0
lines changed

5 files changed

+126
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
4+
5+
use PHPStan\PhpDocParser\Ast\NodeAttributes;
6+
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
7+
use function trim;
8+
9+
class InheritorsTagValueNode implements PhpDocTagValueNode
10+
{
11+
12+
use NodeAttributes;
13+
14+
public TypeNode $type;
15+
16+
/** @var string (may be empty) */
17+
public string $description;
18+
19+
public function __construct(TypeNode $type, string $description)
20+
{
21+
$this->type = $type;
22+
$this->description = $description;
23+
}
24+
25+
26+
public function __toString(): string
27+
{
28+
return trim("{$this->type} {$this->description}");
29+
}
30+
31+
}

src/Ast/PhpDoc/PhpDocNode.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,17 @@ public function getRequireImplementsTagValues(string $tagName = '@phpstan-requir
231231
);
232232
}
233233

234+
/**
235+
* @return InheritorsTagValueNode[]
236+
*/
237+
public function getInheritorsTagValues(string $tagName = '@phpstan-inheritors'): array
238+
{
239+
return array_filter(
240+
array_column($this->getTagsByName($tagName), 'value'),
241+
static fn (PhpDocTagValueNode $value): bool => $value instanceof InheritorsTagValueNode,
242+
);
243+
}
244+
234245
/**
235246
* @return DeprecatedTagValueNode[]
236247
*/

src/Parser/PhpDocParser.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,11 @@ public function parseTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\Ph
403403
$tagValue = $this->parseRequireImplementsTagValue($tokens);
404404
break;
405405

406+
case '@psalm-inheritors':
407+
case '@phpstan-inheritors':
408+
$tagValue = $this->parseInheritorsTagValue($tokens);
409+
break;
410+
406411
case '@deprecated':
407412
$tagValue = $this->parseDeprecatedTagValue($tokens);
408413
break;
@@ -933,6 +938,13 @@ private function parseRequireImplementsTagValue(TokenIterator $tokens): Ast\PhpD
933938
return new Ast\PhpDoc\RequireImplementsTagValueNode($type, $description);
934939
}
935940

941+
private function parseInheritorsTagValue(TokenIterator $tokens): Ast\PhpDoc\InheritorsTagValueNode
942+
{
943+
$type = $this->typeParser->parse($tokens);
944+
$description = $this->parseOptionalDescription($tokens, true);
945+
return new Ast\PhpDoc\InheritorsTagValueNode($type, $description);
946+
}
947+
936948
private function parseDeprecatedTagValue(TokenIterator $tokens): Ast\PhpDoc\DeprecatedTagValueNode
937949
{
938950
$description = $this->parseOptionalDescription($tokens, false);

src/Printer/Printer.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineTagValueNode;
1919
use PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;
2020
use PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;
21+
use PHPStan\PhpDocParser\Ast\PhpDoc\InheritorsTagValueNode;
2122
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;
2223
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueParameterNode;
2324
use PHPStan\PhpDocParser\Ast\PhpDoc\MixinTagValueNode;
@@ -327,6 +328,10 @@ private function printTagValue(PhpDocTagValueNode $node): string
327328
$type = $this->printType($node->type);
328329
return trim("{$type} {$node->description}");
329330
}
331+
if ($node instanceof InheritorsTagValueNode) {
332+
$type = $this->printType($node->type);
333+
return trim("{$type} {$node->description}");
334+
}
330335
if ($node instanceof ParamOutTagValueNode) {
331336
$type = $this->printType($node->type);
332337
return trim("{$type} {$node->parameterName} {$node->description}");

tests/PHPStan/Parser/PhpDocParserTest.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ protected function setUp(): void
108108
* @dataProvider provideMixinTagsData
109109
* @dataProvider provideRequireExtendsTagsData
110110
* @dataProvider provideRequireImplementsTagsData
111+
* @dataProvider provideInheritorsTagsData
111112
* @dataProvider provideDeprecatedTagsData
112113
* @dataProvider providePropertyTagsData
113114
* @dataProvider provideMethodTagsData
@@ -2210,6 +2211,72 @@ public function provideRequireImplementsTagsData(): Iterator
22102211
];
22112212
}
22122213

2214+
public function provideInheritorsTagsData(): Iterator
2215+
{
2216+
yield [
2217+
'OK without description',
2218+
'/** @phpstan-inheritors Foo|Bar */',
2219+
new PhpDocNode([
2220+
new PhpDocTagNode(
2221+
'@phpstan-inheritors',
2222+
new RequireImplementsTagValueNode(
2223+
new IdentifierTypeNode('Foo|Bar'),
2224+
'',
2225+
),
2226+
),
2227+
]),
2228+
];
2229+
2230+
yield [
2231+
'OK with description',
2232+
'/** @phpstan-inheritors Foo|Bar optional description */',
2233+
new PhpDocNode([
2234+
new PhpDocTagNode(
2235+
'@phpstan-inheritors',
2236+
new RequireImplementsTagValueNode(
2237+
new IdentifierTypeNode('Foo|Bar'),
2238+
'optional description',
2239+
),
2240+
),
2241+
]),
2242+
];
2243+
2244+
yield [
2245+
'OK with psalm-prefix description',
2246+
'/** @psalm-inheritors Foo|Bar optional description */',
2247+
new PhpDocNode([
2248+
new PhpDocTagNode(
2249+
'@psalm-inheritors',
2250+
new RequireImplementsTagValueNode(
2251+
new IdentifierTypeNode('Foo|Bar'),
2252+
'optional description',
2253+
),
2254+
),
2255+
]),
2256+
];
2257+
2258+
yield [
2259+
'invalid without type and description',
2260+
'/** @phpstan-inheritors */',
2261+
new PhpDocNode([
2262+
new PhpDocTagNode(
2263+
'@phpstan-inheritors',
2264+
new InvalidTagValueNode(
2265+
'',
2266+
new ParserException(
2267+
'*/',
2268+
Lexer::TOKEN_CLOSE_PHPDOC,
2269+
32,
2270+
Lexer::TOKEN_IDENTIFIER,
2271+
null,
2272+
1,
2273+
),
2274+
),
2275+
),
2276+
]),
2277+
];
2278+
}
2279+
22132280
public function provideDeprecatedTagsData(): Iterator
22142281
{
22152282
yield [

0 commit comments

Comments
 (0)