Passed
Push — main ( 28fe2f...804823 )
by mikhail
03:26
created

CommentDensity   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 153
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 21
Bugs 6 Features 1
Metric Value
eloc 88
c 21
b 6
f 1
dl 0
loc 153
ccs 0
cts 101
cp 0
rs 10
wmc 22

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A isInWhitelist() 0 8 3
A createOutputDTO() 0 19 2
A prepareComments() 0 28 4
B analyze() 0 44 6
B prepareCommentStatistics() 0 32 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SavinMikhail\CommentsDensity;
6
7
use Generator;
8
use SavinMikhail\CommentsDensity\Comments\CommentFactory;
9
use SavinMikhail\CommentsDensity\Comments\CommentTypeInterface;
10
use SavinMikhail\CommentsDensity\DTO\Input\ConfigDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDensity\DTO\Input\ConfigDTO 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...
11
use SavinMikhail\CommentsDensity\DTO\Output\CommentDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDensity\DTO\Output\CommentDTO 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...
12
use SavinMikhail\CommentsDensity\DTO\Output\CommentStatisticsDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDen...ut\CommentStatisticsDTO 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...
13
use SavinMikhail\CommentsDensity\DTO\Output\OutputDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDensity\DTO\Output\OutputDTO 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...
14
use SavinMikhail\CommentsDensity\Metrics\Metrics;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDensity\Metrics\Metrics 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...
15
use SavinMikhail\CommentsDensity\Reporters\ReporterInterface;
16
use SplFileInfo;
17
18
use function str_contains;
19
20
final class CommentDensity
21
{
22
    private bool $exceedThreshold = false;
23
24
    public function __construct(
25
        private readonly ConfigDTO $configDTO,
26
        private readonly CommentFactory $commentFactory,
27
        private readonly FileAnalyzer $fileAnalyzer,
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDensity\FileAnalyzer 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...
28
        private readonly ReporterInterface $reporter,
29
        private readonly MissingDocBlockAnalyzer $missingDocBlock,
30
        private readonly Metrics $metrics,
31
    ) {
32
    }
33
34
    public function analyze(Generator $files): bool
35
    {
36
        $this->metrics->startPerformanceMonitoring();
37
        $comments = [];
38
        $commentStatistics = [];
39
        $totalLinesOfCode = 0;
40
        $cdsSum = 0;
41
        $filesAnalyzed = 0;
42
43
        foreach ($files as $file) {
44
            if (! ($file instanceof SplFileInfo)) {
45
                continue;
46
            }
47
            if ($this->isInWhitelist($file->getRealPath())) {
48
                continue;
49
            }
50
            if ($file->getSize() === 0) {
51
                continue;
52
            }
53
54
            $this->fileAnalyzer->analyzeFile(
55
                $file,
56
                $commentStatistics,
57
                $comments,
58
                $totalLinesOfCode,
59
                $cdsSum
60
            );
61
            $filesAnalyzed++;
62
        }
63
64
        $this->metrics->stopPerformanceMonitoring();
65
66
        $averageCds = $totalLinesOfCode === 0 ? 0 : $cdsSum / $totalLinesOfCode;
0 ignored issues
show
introduced by
The condition $totalLinesOfCode === 0 is always true.
Loading history...
67
        $outputDTO = $this->createOutputDTO(
68
            $comments,
69
            $commentStatistics,
70
            $totalLinesOfCode,
71
            $averageCds,
72
            $filesAnalyzed,
73
        );
74
75
        $this->reporter->report($outputDTO);
76
77
        return $this->exceedThreshold;
78
    }
79
80
    private function createOutputDTO(
81
        array $comments,
82
        array $commentStatistics,
83
        int $linesOfCode,
84
        float $cds,
85
        int $filesAnalyzed,
86
    ): OutputDTO {
87
        $outputDTO = new OutputDTO(
88
            $filesAnalyzed,
89
            $this->prepareCommentStatistics($commentStatistics),
90
            $this->prepareComments($comments),
91
            $this->metrics->getPerformanceMetrics(),
92
            $this->metrics->prepareComToLoc($commentStatistics, $linesOfCode),
93
            $this->metrics->prepareCDS($cds)
94
        );
95
        if ($this->metrics->hasExceededThreshold()) {
96
            $this->exceedThreshold = true;
97
        }
98
        return $outputDTO;
99
    }
100
101
    private function prepareCommentStatistics(array $commentStatistics): array
102
    {
103
        $preparedStatistics = [];
104
        foreach ($commentStatistics as $type => $stat) {
105
            if ($type === 'missingDocblock') {
106
                $preparedStatistics[] = new CommentStatisticsDTO(
107
                    $this->missingDocBlock->getColor(),
108
                    $this->missingDocBlock->getName(),
109
                    $stat['lines'],
110
                    $this->missingDocBlock->getStatColor($stat['count'], $this->configDTO->thresholds),
111
                    $stat['count']
112
                );
113
                if ($this->missingDocBlock->hasExceededThreshold()) {
114
                    $this->exceedThreshold = true;
115
                }
116
                continue;
117
            }
118
            $commentType = $this->commentFactory->getCommentType($type);
119
            if ($commentType) {
120
                $preparedStatistics[] = new CommentStatisticsDTO(
121
                    $commentType->getColor(),
122
                    $commentType->getName(),
123
                    $stat['lines'],
124
                    $commentType->getStatColor($stat['count'], $this->configDTO->thresholds),
125
                    $stat['count']
126
                );
127
                if ($commentType->hasExceededThreshold()) {
128
                    $this->exceedThreshold = true;
129
                }
130
            }
131
        }
132
        return $preparedStatistics;
133
    }
134
135
    private function prepareComments(array $comments): array
136
    {
137
        $preparedComments = [];
138
        foreach ($comments as $comment) {
139
            /** @var CommentTypeInterface|string $commentType */
140
            $commentType = $comment['type'];
141
            if ($commentType === 'missingDocblock') {
142
                $preparedComments[] = new CommentDTO(
143
                    'missingDocblock',
144
                    'red',
145
                    $comment['file'],
146
                    $comment['line'],
147
                    $comment['content']
148
                );
149
                continue;
150
            }
151
            if ($commentType->getAttitude() === 'good') {
152
                continue;
153
            }
154
            $preparedComments[] = new CommentDTO(
155
                $commentType->getName(),
156
                $commentType->getColor(),
157
                $comment['file'],
158
                $comment['line'],
159
                $comment['content']
160
            );
161
        }
162
        return $preparedComments;
163
    }
164
165
    private function isInWhitelist(string $filePath): bool
166
    {
167
        foreach ($this->configDTO->exclude as $whitelistedDir) {
168
            if (str_contains($filePath, $whitelistedDir)) {
169
                return true;
170
            }
171
        }
172
        return false;
173
    }
174
}
175