Passed
Push — main ( b13408...5e6da4 )
by mikhail
03:02
created

CommentDensity::prepareCDS()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SavinMikhail\CommentsDensity;
6
7
use RecursiveDirectoryIterator;
8
use RecursiveIteratorIterator;
9
use SavinMikhail\CommentsDensity\Comments\CommentFactory;
10
use SavinMikhail\CommentsDensity\Comments\CommentTypeInterface;
11
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...
12
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...
13
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...
14
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...
15
use SavinMikhail\CommentsDensity\DTO\Output\PerformanceMetricsDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDen...t\PerformanceMetricsDTO 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...
16
use SavinMikhail\CommentsDensity\Reporters\ReporterInterface;
17
use SplFileInfo;
18
19
use function round;
20
21
final class CommentDensity
22
{
23
    private bool $exceedThreshold = false;
24
25
    public function __construct(
26
        private readonly ConfigDTO $configDTO,
27
        private readonly CommentFactory $commentFactory,
28
        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...
29
        private readonly ReporterInterface $reporter,
30
        private readonly CDS $cds,
31
        private readonly ComToLoc $comToLoc,
32
        private readonly MissingDocBlockAnalyzer $missingDocBlock,
33
    ) {
34
    }
35
36
    public function analyzeDirectories(array $directories): bool
37
    {
38
        $startTime = microtime(true);
39
        $comments = [];
40
        $commentStatistics = [];
41
        $totalLinesOfCode = 0;
42
        $cdsSum = 0;
43
        $filesAnalyzed = 0;
44
45
        foreach ($directories as $directory) {
46
            $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
47
            /** @var SplFileInfo $file */
48
            foreach ($iterator as $file) {
49
                if ($this->isInWhitelist($file->getRealPath())) {
50
                    continue;
51
                }
52
                $this->fileAnalyzer->analyzeFile(
53
                    $file,
54
                    $commentStatistics,
55
                    $comments,
56
                    $totalLinesOfCode,
57
                    $cdsSum
58
                );
59
                $filesAnalyzed++;
60
            }
61
        }
62
63
        $endTime = microtime(true);
64
        $executionTimeMS = round(($endTime - $startTime) * 1000, 2);
65
        $peakMemoryUsage = memory_get_peak_usage(true);
66
67
        $outputDTO = $this->createOutputDTO(
68
            $comments,
69
            $commentStatistics,
70
            $totalLinesOfCode,
71
            $cdsSum / $totalLinesOfCode,
72
            $filesAnalyzed,
73
            $executionTimeMS,
74
            $peakMemoryUsage
75
        );
76
77
        $this->reporter->report($outputDTO);
78
79
        return $this->exceedThreshold;
80
    }
81
82
    private function createOutputDTO(
83
        array $comments,
84
        array $commentStatistics,
85
        int $linesOfCode,
86
        float $cds,
87
        int $filesAnalyzed,
88
        float $executionTime,
89
        float $peakMemoryUsage
90
    ): OutputDTO {
91
        $metricsDTO = new PerformanceMetricsDTO(
92
            $executionTime,
93
            round($peakMemoryUsage / 1024 / 1024, 2)
94
        );
95
96
        $cdsDTO = $this->cds->prepareCDS($cds);
97
        $comToLocDTO = $this->comToLoc->prepareComToLoc($commentStatistics, $linesOfCode);
98
99
100
        if ($this->cds->hasExceededThreshold() || $this->comToLoc->hasExceededThreshold()) {
101
            $this->exceedThreshold = true;
102
        }
103
        return new OutputDTO(
104
            $filesAnalyzed,
105
            $this->prepareCommentStatistics($commentStatistics),
106
            $this->prepareComments($comments),
107
            $metricsDTO,
108
            $comToLocDTO,
109
            $cdsDTO
110
        );
111
    }
112
113
    private function prepareCommentStatistics(array $commentStatistics): array
114
    {
115
        $preparedStatistics = [];
116
        foreach ($commentStatistics as $type => $count) {
117
            if ($type === 'missingDocblock') {
118
                $preparedStatistics[] = new CommentStatisticsDTO(
119
                    $this->missingDocBlock->getColor(),
120
                    $this->missingDocBlock->getName(),
121
                    $count,
122
                    $this->missingDocBlock->getStatColor($count, $this->configDTO->thresholds)
123
                );
124
                continue;
125
            }
126
            $commentType = $this->commentFactory->getCommentType($type);
127
            if ($commentType) {
128
                $preparedStatistics[] = new CommentStatisticsDTO(
129
                    $commentType->getColor(),
130
                    $commentType->getName(),
131
                    $count,
132
                    $commentType->getStatColor($count, $this->configDTO->thresholds)
133
                );
134
            }
135
        }
136
        return  $preparedStatistics;
137
    }
138
139
    private function prepareComments(array $comments): array
140
    {
141
        $preparedComments = [];
142
        foreach ($comments as $comment) {
143
            /** @var CommentTypeInterface|string $commentType */
144
            $commentType = $comment['type'];
145
            if ($commentType === 'missingDocblock') {
146
                $preparedComments[] = new CommentDTO(
147
                    'missingDocblock',
148
                    'red',
149
                    $comment['file'],
150
                    $comment['line'],
151
                    $comment['content']
152
                );
153
                continue;
154
            }
155
            if ($commentType->getAttitude() === 'good') {
156
                continue;
157
            }
158
            $preparedComments[] = new CommentDTO(
159
                $commentType->getName(),
160
                $commentType->getColor(),
161
                $comment['file'],
162
                $comment['line'],
163
                $comment['content']
164
            );
165
        }
166
        return $preparedComments;
167
    }
168
169
    public function analyzeFile(string $filename): bool
170
    {
171
        $comments = [];
172
        $commentStatistics = [];
173
        $totalLinesOfCode = 0;
174
        $cdsSum = 0;
175
176
        $this->fileAnalyzer->analyzeFile(
177
            new SplFileInfo($filename),
178
            $commentStatistics,
179
            $comments,
180
            $totalLinesOfCode,
181
            $cdsSum
182
        );
183
184
185
        return $this->exceedThreshold;
186
    }
187
188
    private function isInWhitelist(string $filePath): bool
189
    {
190
        foreach ($this->configDTO->exclude as $whitelistedDir) {
191
            if (str_contains($filePath, $whitelistedDir)) {
192
                return true;
193
            }
194
        }
195
        return false;
196
    }
197
}
198