Skip to content

Commit b0c71c4

Browse files
committed
PhpDocEditor
1 parent 701d9ef commit b0c71c4

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Fixable\PhpDoc;
4+
5+
use Override;
6+
use PHPStan\PhpDocParser\Ast\AbstractNodeVisitor;
7+
use PHPStan\PhpDocParser\Ast\Node;
8+
9+
final class CallbackVisitor extends AbstractNodeVisitor
10+
{
11+
12+
/** @var callable(Node): (Node|Node[]|null) */
13+
private $callback;
14+
15+
/** @param callable(Node): (Node|Node[]|null) $callback */
16+
public function __construct(callable $callback)
17+
{
18+
$this->callback = $callback;
19+
}
20+
21+
/**
22+
* @return Node[]|Node|null
23+
*/
24+
#[Override]
25+
public function enterNode(Node $node): array|Node|null
26+
{
27+
$callback = $this->callback;
28+
29+
return $callback($node);
30+
}
31+
32+
}

src/Fixable/PhpDoc/PhpDocEditor.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Fixable\PhpDoc;
4+
5+
use PhpParser\Comment\Doc;
6+
use PHPStan\DependencyInjection\AutowiredService;
7+
use PHPStan\PhpDocParser\Ast\Node;
8+
use PHPStan\PhpDocParser\Ast\NodeTraverser;
9+
use PHPStan\PhpDocParser\Ast\NodeVisitor\CloningVisitor;
10+
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
11+
use PHPStan\PhpDocParser\Lexer\Lexer;
12+
use PHPStan\PhpDocParser\Parser\PhpDocParser;
13+
use PHPStan\PhpDocParser\Parser\TokenIterator;
14+
use PHPStan\PhpDocParser\Printer\Printer;
15+
use function count;
16+
17+
/**
18+
* @api
19+
* @internal Experimental
20+
*/
21+
#[AutowiredService]
22+
final class PhpDocEditor
23+
{
24+
25+
public function __construct(private Printer $printer, private Lexer $lexer, private PhpDocParser $phpDocParser)
26+
{
27+
}
28+
29+
/**
30+
* @param callable(Node): (Node|Node[]|null) $callback
31+
*/
32+
public function edit(\PhpParser\Node $node, callable $callback): void
33+
{
34+
$doc = $node->getDocComment();
35+
if ($doc === null) {
36+
$phpDoc = '/** */';
37+
} else {
38+
$phpDoc = $doc->getText();
39+
}
40+
$tokens = new TokenIterator($this->lexer->tokenize($phpDoc));
41+
$phpDocNode = $this->phpDocParser->parse($tokens);
42+
43+
$cloningTraverser = new NodeTraverser([new CloningVisitor()]);
44+
45+
/** @var PhpDocNode $newPhpDocNode */
46+
[$newPhpDocNode] = $cloningTraverser->traverse([$phpDocNode]);
47+
48+
$traverser = new NodeTraverser([new CallbackVisitor($callback)]);
49+
50+
/** @var PhpDocNode $newPhpDocNode */
51+
[$newPhpDocNode] = $traverser->traverse([$newPhpDocNode]);
52+
53+
if (count($newPhpDocNode->children) === 0) {
54+
$node->setAttribute('comments', []);
55+
return;
56+
}
57+
58+
$doc = new Doc($this->printer->printFormatPreserving($newPhpDocNode, $phpDocNode, $tokens));
59+
$node->setDocComment($doc);
60+
}
61+
62+
}

0 commit comments

Comments
 (0)