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

NodeNeedsDocblockChecker   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Test Coverage

Coverage 92.31%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 25
eloc 42
dl 0
loc 90
ccs 36
cts 39
cp 0.9231
rs 10
c 1
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
C requiresDocBlock() 0 40 17
A methodRequiresAdditionalDocBlock() 0 6 2
A determineMissingContent() 0 19 5
A __construct() 0 4 1
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