Test Failed
Push — main ( 46eee6...5832e5 )
by mikhail
03:28
created

NodeNeedsDocblockChecker::isConfiguredEnum()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
ccs 1
cts 1
cp 1
cc 2
nc 2
nop 1
crap 2
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
            return $this->config->class && !$node->isAnonymous();
40 18
        }
41
42
        if ($this->isConfiguredNode($node)) {
43
            return true;
44 70
        }
45 1
46
        if ($this->isMethodOrFunction($node)) {
47
            /** @var ClassMethod|Function_ $node */
48 70
            return $this->requiresMethodOrFunctionDocBlock($node);
49 1
        }
50
51
        return false;
52 70
    }
53 2
54
    private function isConfiguredNode(Node $node): bool
55
    {
56
        return $this->isConfiguredTrait($node)
57 70
            || $this->isConfiguredInterface($node)
58 70
            || $this->isConfiguredEnum($node)
59
            || $this->isConfiguredProperty($node)
60 46
            || $this->isConfiguredConstant($node);
61 7
    }
62
63 39
    private function isConfiguredTrait(Node $node): bool
64
    {
65
        return $node instanceof Trait_ && $this->config->trait;
66 70
    }
67 5
68
    private function isConfiguredInterface(Node $node): bool
69
    {
70 70
        return $node instanceof Interface_ && $this->config->interface;
71 1
    }
72
73
    private function isConfiguredEnum(Node $node): bool
74 70
    {
75
        return $node instanceof Enum_ && $this->config->enum;
76
    }
77
78
    private function isConfiguredProperty(Node $node): bool
79
    {
80
        return $node instanceof Property && $this->config->property;
81 39
    }
82
83 39
    private function isConfiguredConstant(Node $node): bool
84 39
    {
85
        return $node instanceof ClassConst && $this->config->constant;
86 39
    }
87
88
    private function isMethodOrFunction(Node $node): bool
89 48
    {
90
        return ($node instanceof ClassMethod || $node instanceof Function_) && $this->config->function;
91 48
    }
92
93
    private function requiresMethodOrFunctionDocBlock(ClassMethod|Function_ $node): bool
94
    {
95
        if ($this->config->requireForAllMethods) {
96
            return true;
97 48
        }
98 23
        return $this->methodRequiresAdditionalDocBlock($node);
99 23
    }
100
101
    /**
102 25
     * here we want to find methods that have uncaught throw statements or their return type will be better
103 6
     * described as generic
104 6
     */
105
    private function methodRequiresAdditionalDocBlock(ClassMethod|Function_ $node): bool
106
    {
107 19
        $this->throwsUncaught = $this->methodAnalyzer->methodNeedsThrowsTag($node, $this->class);
108
        $this->needsGeneric = $this->methodAnalyzer->methodNeedsGeneric($node);
109
110
        return $this->throwsUncaught || $this->needsGeneric;
111
    }
112
113
    public function determineMissingContent(): string
114
    {
115
        if ($this->needsGeneric && $this->throwsUncaught) {
116
            $this->needsGeneric = false;
117
            $this->throwsUncaught = false;
118
            return self::MISSING_THROWS_TAG . ' and ' . self::MISSING_GENERIC;
119
        }
120
121
        if ($this->needsGeneric) {
122
            $this->needsGeneric = false;
123
            return self::MISSING_GENERIC;
124
        }
125
126
        if ($this->throwsUncaught) {
127
            $this->throwsUncaught = false;
128
            return self::MISSING_THROWS_TAG;
129
        }
130
131
        return self::MISSING_DOC;
132
    }
133
}
134