Skip to content

Commit af8e840

Browse files
committed
Printer: keep the format of the tag value when the tag name changes
Amp-Thread-ID: https://ampcode.com/threads/T-01a17930-0285-73c5-a957-4325c77aa1b2
1 parent e364709 commit af8e840

2 files changed

Lines changed: 83 additions & 0 deletions

File tree

‎src/Printer/Printer.php‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,22 @@ private function printNodeFormatPreserving(Node $node, TokenIterator $originalTo
977977
continue;
978978
}
979979

980+
if ($this->isRenamedTag($node, $subNodeName, $originalTokens, $startPos)) {
981+
// the tag name is the first token of the tag; keep the format of the value
982+
$result .= $subNode;
983+
$pos = $startPos + 1;
984+
continue;
985+
}
986+
987+
if (
988+
$node instanceof DoctrineAnnotation
989+
&& $subNodeName === 'name'
990+
&& $node->getAttribute(Attribute::ORIGINAL_NODE)->name !== $originalTokens->getContentBetween($startPos, $startPos + 1)
991+
) {
992+
// the tokens of the annotation of a Doctrine tag do not contain the name, the tag prints it
993+
continue;
994+
}
995+
980996
if (is_array($subNode) && is_array($origSubNode)) {
981997
// Array subnode changed, we might be able to reconstruct it
982998
$listResult = $this->printArrayFormatPreserving(
@@ -1053,6 +1069,20 @@ private function printNodeFormatPreserving(Node $node, TokenIterator $originalTo
10531069
return $result . $originalTokens->getContentBetween($pos, $endPos + 1);
10541070
}
10551071

1072+
private function isRenamedTag(Node $node, string $subNodeName, TokenIterator $originalTokens, int $startPos): bool
1073+
{
1074+
if (!$node instanceof PhpDocTagNode || $subNodeName !== 'name') {
1075+
return false;
1076+
}
1077+
1078+
$originalNode = $node->getAttribute(Attribute::ORIGINAL_NODE);
1079+
if (!$originalNode instanceof PhpDocTagNode) {
1080+
return false;
1081+
}
1082+
1083+
return $originalTokens->getContentBetween($startPos, $startPos + 1) === $originalNode->name;
1084+
}
1085+
10561086
/**
10571087
* Prints a node that replaces the tokens of the original node.
10581088
*

‎tests/PHPStan/Printer/PrinterTest.php‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,59 @@ public function enterNode(Node $node)
22002200
},
22012201
];
22022202

2203+
$renameDoctrineTagVisitor = new class extends AbstractNodeVisitor {
2204+
2205+
public function enterNode(Node $node)
2206+
{
2207+
if ($node instanceof PhpDocTagNode && $node->value instanceof DoctrineTagValueNode) {
2208+
$node->name = '@Bar';
2209+
$node->value->annotation->name = '@Bar';
2210+
}
2211+
2212+
return $node;
2213+
}
2214+
2215+
};
2216+
2217+
yield [
2218+
'/**' . PHP_EOL .
2219+
' * @\Foo\Bar(' . PHP_EOL .
2220+
' * name="x",' . PHP_EOL .
2221+
' * cols={@\Foo\Col("a")}' . PHP_EOL .
2222+
' * )' . PHP_EOL .
2223+
' */',
2224+
'/**' . PHP_EOL .
2225+
' * @Bar(' . PHP_EOL .
2226+
' * name="x",' . PHP_EOL .
2227+
' * cols={@\Foo\Col("a")}' . PHP_EOL .
2228+
' * )' . PHP_EOL .
2229+
' */',
2230+
$renameDoctrineTagVisitor,
2231+
];
2232+
2233+
yield [
2234+
'/** @\Foo\Bar("a") some description */',
2235+
'/** @Bar("a") some description */',
2236+
$renameDoctrineTagVisitor,
2237+
];
2238+
2239+
yield [
2240+
'/** @param int $a */',
2241+
'/** @phpstan-param int $a */',
2242+
new class extends AbstractNodeVisitor {
2243+
2244+
public function enterNode(Node $node)
2245+
{
2246+
if ($node instanceof PhpDocTagNode) {
2247+
$node->name = '@phpstan-param';
2248+
}
2249+
2250+
return $node;
2251+
}
2252+
2253+
},
2254+
];
2255+
22032256
yield [
22042257
'/**' . PHP_EOL .
22052258
' * @X({' . PHP_EOL .

0 commit comments

Comments
 (0)