Passed
Push — main ( aa1c08...38dda7 )
by mikhail
13:28
created

DocBlockChecker::requiresDocBlock()   C

Complexity

Conditions 17
Paths 9

Size

Total Lines 37
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 17

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 19
c 1
b 1
f 0
dl 0
loc 37
ccs 19
cts 19
cp 1
rs 5.2166
cc 17
nc 9
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;
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 DocBlockChecker
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 65
    public function __construct(
28
        private readonly MissingDocblockConfigDTO $config,
29
        private readonly MethodAnalyzer $methodAnalyzer,
30
    ) {
31 65
    }
32
33 65
    public function requiresDocBlock(Node $node): bool
34
    {
35 65
        if ($node instanceof Class_ && $this->config->class) {
36 18
            return !$node->isAnonymous();
37
        }
38
39 65
        if ($node instanceof Trait_ && $this->config->trait) {
40 1
            return true;
41
        }
42
43 65
        if ($node instanceof Interface_ && $this->config->interface) {
44 1
            return true;
45
        }
46
47 65
        if ($node instanceof Enum_ && $this->config->enum) {
48 2
            return true;
49
        }
50
51
        if (
52 65
            ($node instanceof ClassMethod || $node instanceof Function_)
53 65
            && $this->config->function
54
        ) {
55 41
            if ($this->config->requireForAllMethods) {
56 7
                return true;
57
            }
58 34
            return $this->methodRequiresAdditionalDocBlock($node);
59
        }
60
61 65
        if ($node instanceof Property && $this->config->property) {
62 5
            return true;
63
        }
64
65 65
        if ($node instanceof ClassConst && $this->config->constant) {
66 1
            return true;
67
        }
68
69 65
        return false;
70
    }
71
72
    /**
73
     * here we want to find methods that have uncaught throw statements or their return type will be better
74
     * described as generic
75
     */
76 34
    private function methodRequiresAdditionalDocBlock(ClassMethod|Function_ $node): bool
77
    {
78 34
        $this->throwsUncaught = $this->methodAnalyzer->methodThrowsUncaughtExceptions($node);
79 34
        $this->needsGeneric = $this->methodAnalyzer->methodNeedsGeneric($node);
80
81 34
        return $this->throwsUncaught || $this->needsGeneric;
82
    }
83
84 45
    public function determineMissingContent(): string
85
    {
86 45
        if ($this->needsGeneric && $this->throwsUncaught) {
87
            $this->needsGeneric = false;
88
            $this->throwsUncaught = false;
89
            return self::MISSING_THROWS_TAG . ' and ' . self::MISSING_GENERIC;
90
        }
91
92 45
        if ($this->needsGeneric) {
93 23
            $this->needsGeneric = false;
94 23
            return self::MISSING_GENERIC;
95
        }
96
97 22
        if ($this->throwsUncaught) {
98 3
            $this->throwsUncaught = false;
99 3
            return self::MISSING_THROWS_TAG;
100
        }
101
102 19
        return self::MISSING_DOC;
103
    }
104
}
105