Skip to content

Commit 8ece074

Browse files
authored
Playground: Implement PhpdocCommentRule
1 parent 929c7c5 commit 8ece074

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

issue-bot/playground.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ rules:
33
- PHPStan\Rules\Playground\MethodNeverRule
44
- PHPStan\Rules\Playground\NotAnalysedTraitRule
55
- PHPStan\Rules\Playground\NoPhpCodeRule
6+
- PHPStan\Rules\Playground\PhpdocCommentRule
67

78
conditionalTags:
89
PHPStan\Rules\Playground\StaticVarWithoutTypeRule:
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Playground;
4+
5+
use Nette\Utils\Strings;
6+
use PhpParser\Node;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Node\VirtualNode;
9+
use PHPStan\Rules\Rule;
10+
use PHPStan\Rules\RuleErrorBuilder;
11+
use function str_starts_with;
12+
13+
/**
14+
* @implements Rule<Node\Stmt>
15+
*/
16+
final class PhpdocCommentRule implements Rule
17+
{
18+
19+
public function getNodeType(): string
20+
{
21+
return Node\Stmt::class;
22+
}
23+
24+
public function processNode(Node $node, Scope $scope): array
25+
{
26+
if ($node instanceof VirtualNode) {
27+
return [];
28+
}
29+
30+
$comments = $node->getComments();
31+
32+
$errors = [];
33+
foreach ($comments as $comment) {
34+
foreach (['/**', '//', '#'] as $startTag) {
35+
if (str_starts_with($comment->getText(), $startTag)) {
36+
continue 2;
37+
}
38+
}
39+
40+
if (Strings::match($comment->getText(), '{(\s|^)@\w+(\s|$)}') === null) {
41+
continue;
42+
}
43+
44+
$errors[] = RuleErrorBuilder::message('Comment contains PHPDoc tag but does not start with /** prefix.')
45+
->identifier('phpstanPlayground.phpDoc')
46+
->build();
47+
}
48+
49+
return $errors;
50+
}
51+
52+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Playground;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
/**
9+
* @extends RuleTestCase<PhpdocCommentRule>
10+
*/
11+
class PhpdocCommentRuleTest extends RuleTestCase
12+
{
13+
14+
protected function getRule(): Rule
15+
{
16+
return new PhpdocCommentRule();
17+
}
18+
19+
public function testRule(): void
20+
{
21+
$this->analyse([__DIR__ . '/data/comments.php'], [
22+
[
23+
'Comment contains PHPDoc tag but does not start with /** prefix.',
24+
13,
25+
],
26+
[
27+
'Comment contains PHPDoc tag but does not start with /** prefix.',
28+
23,
29+
],
30+
]);
31+
}
32+
33+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace CommentTypes;
4+
5+
/**
6+
* @template T of FooInterface
7+
*/
8+
class Bar
9+
{
10+
/*
11+
* @var T $foo
12+
*/
13+
protected FooInterface $foo;
14+
15+
/**
16+
* @param T $foo
17+
*/
18+
public function __construct(FooInterface $foo) { $this->foo = $foo; }
19+
20+
/*
21+
* @return T
22+
*/
23+
public function getFoo(): FooInterface
24+
{
25+
return $this->foo;
26+
}
27+
28+
/*
29+
* some method
30+
*/
31+
public function getBar(): FooInterface
32+
{
33+
return $this->foo;
34+
}
35+
36+
// this should not error: @var
37+
# this should not error: @var
38+
39+
/*
40+
* comments which look like phpdoc should be ignored
41+
*
42+
* x@x.cz
43+
* 10 amps @ 1 volt
44+
*/
45+
public function ignoreComments(): FooInterface
46+
{
47+
return $this->foo;
48+
}
49+
}

0 commit comments

Comments
 (0)