Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
AddMissingClassPhpDocRector
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
3 / 3
6
100.00% covered (success)
100.00%
1 / 1
 getRuleDefinition
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getNodeTypes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 refactor
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3declare(strict_types=1);
4
5/**
6 * Fast Forward Development Tools for PHP projects.
7 *
8 * This file is part of fast-forward/dev-tools project.
9 *
10 * @author   Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
11 * @license  https://opensource.org/licenses/MIT MIT License
12 *
13 * @see      https://github.com/php-fast-forward/
14 * @see      https://github.com/php-fast-forward/dev-tools
15 * @see      https://github.com/php-fast-forward/dev-tools/issues
16 * @see      https://php-fast-forward.github.io/dev-tools/
17 * @see      https://datatracker.ietf.org/doc/html/rfc2119
18 */
19
20namespace FastForward\DevTools\Rector;
21
22use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
23use PhpParser\Comment\Doc;
24use PhpParser\Node;
25use Rector\Rector\AbstractRector;
26use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
27use PhpParser\Node\Stmt\Class_;
28
29/**
30 * Provides automated refactoring to prepend basic PHPDoc comments on classes missing them.
31 * This rule MUST adhere to AST standards and SHALL traverse `Class_` nodes exclusively.
32 */
33 class AddMissingClassPhpDocRector extends AbstractRector
34{
35    /**
36     * Resolves the definition describing this rule for documentation generation.
37     *
38     * The method MUST return a properly instantiated RuleDefinition stating its purpose.
39     *
40     * @return RuleDefinition the description entity for the given Rector rule
41     */
42    public function getRuleDefinition(): RuleDefinition
43    {
44        return new RuleDefinition('Add basic PHPDoc to classes without docblock', [
45            new CodeSample('class SomeClass {}', "/**\n * SomeClass\n */\nclass SomeClass {}"),
46        ]);
47    }
48
49    /**
50     * Declares the types of Abstract Syntax Tree nodes that trigger this refactoring run.
51     *
52     * The method MUST identify `Class_` nodes reliably. It SHALL define the interception target.
53     *
54     * @return array<int, class-string<Node>> an array containing registered node class references
55     */
56    public function getNodeTypes(): array
57    {
58        return [Class_::class];
59    }
60
61    /**
62     * Triggers the modification process against a matched AST node.
63     *
64     * The method MUST verify the absence of an existing PHPDoc header accurately.
65     * It SHOULD append a basic boilerplate PHPDoc comment if applicable.
66     * If the node is unchanged, it SHALL return null.
67     *
68     * @param Node $node the current active syntax instance parsed by the framework
69     *
70     * @return Node|null the modified active syntax state, or null if untouched
71     */
72    public function refactor(Node $node): ?Node
73    {
74        if (! $node instanceof Class_) {
75            return null;
76        }
77
78        if ($node->getDocComment() instanceof Doc) {
79            return null;
80        }
81
82        $className = $this->getName($node->name) ?? 'Class';
83        $namespace = $node->namespacedName?->slice(0, -1)
84            ->toString() ?? '';
85
86        $lines = ['/**'];
87        $lines[] = \sprintf(' * %s', $className);
88
89        if ('' !== $namespace) {
90            $lines[] = ' *';
91            $lines[] = \sprintf(' * @package %s', $namespace);
92        }
93
94        $lines[] = ' */';
95
96        $node->setDocComment(new Doc(implode("\n", $lines)));
97
98        return $node;
99    }
100}