Passed
Push — main ( ecc027...46eee6 )
by mikhail
03:29
created

NodeNeedsDocblockChecker::requiresDocBlock()   C

Complexity

Conditions 17
Paths 17

Size

Total Lines 40
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 17

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 40
ccs 21
cts 21
cp 1
rs 5.2166
c 0
b 0
f 0
cc 17
nc 17
nop 1
crap 17

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace SavinMikhail\CommentsDensity\MissingDocblock\Visitors\Checkers;
6
7
use PhpParser\Node;
8
use PhpParser\Node\Stmt\Class_;
9
use PhpParser\Node\Stmt\ClassConst;
10
use PhpParser\Node\Stmt\ClassMethod;
11
use PhpParser\Node\Stmt\Enum_;
12
use PhpParser\Node\Stmt\Function_;
13
use PhpParser\Node\Stmt\Interface_;
14
use PhpParser\Node\Stmt\Property;
15
use PhpParser\Node\Stmt\Trait_;
16
use SavinMikhail\CommentsDensity\DTO\Input\MissingDocblockConfigDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDen...issingDocblockConfigDTO was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
18
final class NodeNeedsDocblockChecker
19
{
20
    private const MISSING_DOC = 'missing doc';
21
    private const MISSING_THROWS_TAG = 'missing @throws tag';
22
    private const MISSING_GENERIC = 'missing generic';
23
24
    private bool $needsGeneric = false;
25
    private bool $throwsUncaught = false;
26
27
    private ?Class_ $class = null;
28
29 70
    public function __construct(
30
        private readonly MissingDocblockConfigDTO $config,
31
        private readonly MethodNeedsDocblockChecker $methodAnalyzer,
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDen...hodNeedsDocblockChecker was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
    ) {
33 70
    }
34
35 70
    public function requiresDocBlock(Node $node): bool
36
    {
37 70
        if ($node instanceof Class_) {
38 51
            $this->class = $node;
39 51
            if ($this->config->class) {
40 18
                return !$node->isAnonymous();
41
            }
42
        }
43
44 70
        if ($node instanceof Trait_ && $this->config->trait) {
45 1
            return true;
46
        }
47
48 70
        if ($node instanceof Interface_ && $this->config->interface) {
49 1
            return true;
50
        }
51
52 70
        if ($node instanceof Enum_ && $this->config->enum) {
53 2
            return true;
54
        }
55
56
        if (
57 70
            ($node instanceof ClassMethod || $node instanceof Function_)
58 70
            && $this->config->function
59
        ) {
60 46
            if ($this->config->requireForAllMethods) {
61 7
                return true;
62
            }
63 39
            return $this->methodRequiresAdditionalDocBlock($node);
64
        }
65
66 70
        if ($node instanceof Property && $this->config->property) {
67 5
            return true;
68
        }
69
70 70
        if ($node instanceof ClassConst && $this->config->constant) {
71 1
            return true;
72
        }
73
74 70
        return false;
75
    }
76
77
    /**
78
     * here we want to find methods that have uncaught throw statements or their return type will be better
79
     * described as generic
80
     */
81 39
    private function methodRequiresAdditionalDocBlock(ClassMethod|Function_ $node): bool
82
    {
83 39
        $this->throwsUncaught = $this->methodAnalyzer->methodNeedsThrowsTag($node, $this->class);
84 39
        $this->needsGeneric = $this->methodAnalyzer->methodNeedsGeneric($node);
85
86 39
        return $this->throwsUncaught || $this->needsGeneric;
87
    }
88
89 48
    public function determineMissingContent(): string
90
    {
91 48
        if ($this->needsGeneric && $this->throwsUncaught) {
92
            $this->needsGeneric = false;
93
            $this->throwsUncaught = false;
94
            return self::MISSING_THROWS_TAG . ' and ' . self::MISSING_GENERIC;
95
        }
96
97 48
        if ($this->needsGeneric) {
98 23
            $this->needsGeneric = false;
99 23
            return self::MISSING_GENERIC;
100
        }
101
102 25
        if ($this->throwsUncaught) {
103 6
            $this->throwsUncaught = false;
104 6
            return self::MISSING_THROWS_TAG;
105
        }
106
107 19
        return self::MISSING_DOC;
108
    }
109
}
110