Passed
Push — main ( bdd3af...bc6954 )
by mikhail
03:49
created

NodeNeedsDocblockChecker::isConfiguredProperty()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

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