Skip to content

Commit b01dbee

Browse files
committed
update: 调整重写顺序依赖问题
1 parent e30807b commit b01dbee

File tree

3 files changed

+96
-35
lines changed

3 files changed

+96
-35
lines changed

src/Visitor/AttributeRewriteVisitor.php

+48-33
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ public function enterNode(Node $node): void
125125
}
126126
// 设置顶级类
127127
$this->topClassReflection = $reflection;
128+
$this->parseClassComments();
128129
break;
129130
case $node instanceof Node\Stmt\Use_:
130131
foreach ($node->uses as $use)
@@ -161,19 +162,45 @@ public function leaveNode(Node $node): ?Node
161162

162163
return match (true)
163164
{
164-
$node instanceof Node\Stmt\ClassLike => $this->generateClass(/* @var $node Node\Stmt\ClassLike */ $node),
165+
$node instanceof Node\Stmt\ClassLike => $this->rewriteClass(/* @var $node Node\Stmt\ClassLike */ $node),
165166
$node instanceof Node\Stmt\ClassMethod => $this->generateClassMethodAttributes(/* @var $node Node\Stmt\ClassMethod */ $node),
166167
default => null,
167168
};
168169
}
169170

170-
private function generateClass(Node\Stmt\ClassLike $node): ?Node\Stmt\ClassLike
171+
private array $classCommentLines = [];
172+
173+
private function parseClassComments(): void
174+
{
175+
$node = $this->currentClass;
176+
177+
$classCommentDoc = Helper::arrayValueLast($node->getComments());
178+
$classCommentText = $classCommentDoc?->getText();
179+
180+
$this->classCommentLines = $this->parseCommentsProperty($classCommentText);
181+
}
182+
183+
private function rewriteClass(Node\Stmt\ClassLike $node): ?Node\Stmt\ClassLike
171184
{
172185
if ($this->debug)
173186
{
174187
$this->logger->debug("> Class: {$node->name}");
175188
}
176189

190+
$classCommentLines = array_filter(
191+
$this->classCommentLines,
192+
static fn ($line) => !('property' !== $line['kind'] && (str_contains($line['raw'], '@Annotation') || str_contains($line['raw'], '@Target'))),
193+
);
194+
if ($this->handleCode->isModified() || $this->classCommentLines !== $classCommentLines)
195+
{
196+
$classCommentLines = array_column($classCommentLines, 'raw');
197+
198+
$newClassCommentText = "/**\n" . implode("\n", $classCommentLines) . "\n */";
199+
$node->setDocComment(new Doc($newClassCommentText));
200+
201+
$this->handleCode->setModified();
202+
}
203+
177204
$newStmts = [];
178205
foreach ($node->stmts as $stmt)
179206
{
@@ -263,33 +290,27 @@ protected function migrationConstruct(Node\Stmt\ClassMethod $node): Node\Stmt\Cl
263290
}
264291
}
265292

266-
$classCommentDoc = Helper::arrayValueLast($this->currentClass->getComments());
267-
$classComments = $classCommentDoc?->getText();
293+
// $classCommentDoc = Helper::arrayValueLast($this->currentClass->getComments());
294+
// $classComments = $classCommentDoc?->getText();
268295

269296
if ($isModified)
270297
{
271298
// 重写类属性注解
272-
$classCommentsLines = $this->parseCommentsProperty($classComments);
273-
$newClassComments = $this->refactorCommentsProperty($classCommentsLines, $newParams);
299+
$this->classCommentLines = $this->refactorCommentsProperty($this->classCommentLines, $newParams);
274300

275-
if ($newClassComments !== $classComments)
301+
// 重写方法注解
302+
$methodCommentDoc = Helper::arrayValueLast($node->getComments());
303+
$methodComments = $methodCommentDoc?->getText();
304+
if ($methodComments)
276305
{
277-
$this->currentClass->setDocComment(new Doc($newClassComments));
278-
279-
// 重写方法注解
280-
$methodCommentDoc = Helper::arrayValueLast($node->getComments());
281-
$methodComments = $methodCommentDoc?->getText();
282-
if ($methodComments)
306+
$methodComments = $this->cleanAnnotationFromComments($methodComments, $newParams);
307+
if (self::isEmptyComments(explode("\n", $methodComments)))
283308
{
284-
$methodComments = $this->cleanAnnotationFromComments($methodComments, $newParams);
285-
if (self::isEmptyComments(explode("\n", $methodComments)))
286-
{
287-
$node->setDocComment(new Doc(''));
288-
}
289-
else
290-
{
291-
$node->setDocComment(new Doc($methodComments));
292-
}
309+
$node->setDocComment(new Doc(''));
310+
}
311+
else
312+
{
313+
$node->setDocComment(new Doc($methodComments));
293314
}
294315
}
295316

@@ -371,7 +392,7 @@ protected function parseCommentsProperty(string $comments): array
371392
* }> $comments
372393
* @param array<Node\Param> $props
373394
*/
374-
protected function refactorCommentsProperty(array $comments, array $props): ?string
395+
protected function refactorCommentsProperty(array $comments, array $props): array
375396
{
376397
$classComments = [];
377398

@@ -386,20 +407,14 @@ protected function refactorCommentsProperty(array $comments, array $props): ?str
386407
{
387408
if ('property' !== $comment['kind'])
388409
{
389-
if (
390-
str_contains($comment['raw'], '@Annotation')
391-
|| str_contains($comment['raw'], '@Target')
392-
) {
393-
continue;
394-
}
395-
$classComments[] = $comment['raw'];
410+
$classComments[] = $comment;
396411
continue;
397412
}
398413
$meta = $comment['meta'];
399414
$prop = $propsMap[$meta['name']] ?? null;
400415
if (empty($prop))
401416
{
402-
$classComments[] = $comment['raw'];
417+
$classComments[] = $comment;
403418
continue;
404419
}
405420
$commentPropMap[$meta['name']] = $comment;
@@ -432,7 +447,7 @@ protected function refactorCommentsProperty(array $comments, array $props): ?str
432447
}
433448
}
434449

435-
return "/**\n" . implode("\n", $classComments) . "\n*/";
450+
return $classComments;
436451
}
437452

438453
/**
@@ -464,6 +479,6 @@ protected function cleanAnnotationFromComments(string $comments, array $props):
464479
}
465480
}
466481

467-
return "/**\n" . implode("\n", $newComments) . "\n*/";
482+
return "/**\n" . implode("\n", $newComments) . "\n */";
468483
}
469484
}

tests/AttributeRewriteTest.php

+26-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static function rewriteCodeDataProvider(): \Generator
6262
*
6363
*
6464
*
65-
*/
65+
*/
6666
#[\Attribute(\Attribute::TARGET_CLASS)]
6767
class TestConsumer extends Base
6868
{
@@ -128,7 +128,7 @@ public function __construct(
128128
*
129129
*
130130
*
131-
*/
131+
*/
132132
#[\Attribute(\Attribute::TARGET_PROPERTY)]
133133
class TestConstruct extends Base
134134
{
@@ -151,5 +151,29 @@ public function __construct(
151151
}
152152
PHP,
153153
];
154+
155+
yield 'class_comment' => [
156+
__DIR__ . '/StubAttribute/TestClassComment.php',
157+
<<<PHP
158+
<?php
159+
160+
declare (strict_types=1);
161+
namespace Imiphp\Tests\StubAttribute;
162+
163+
use Imi\Bean\Annotation\Base;
164+
/**
165+
* 回调注解.
166+
*
167+
*
168+
*
169+
* @property string|object \$class 类名,或者传入对象
170+
* @property string \$method 方法名
171+
*/
172+
#[\Attribute(\Attribute::TARGET_PROPERTY)]
173+
class TestClassComment extends Base
174+
{
175+
}
176+
PHP,
177+
];
154178
}
155179
}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Imiphp\Tests\StubAttribute;
6+
7+
use Imi\Bean\Annotation\Base;
8+
9+
/**
10+
* 回调注解.
11+
*
12+
* @Annotation
13+
*
14+
* @Target({"PROPERTY", "ANNOTATION"})
15+
*
16+
* @property string|object $class 类名,或者传入对象
17+
* @property string $method 方法名
18+
*/
19+
#[\Attribute(\Attribute::TARGET_PROPERTY)]
20+
class TestClassComment extends Base
21+
{
22+
}

0 commit comments

Comments
 (0)