Issues (52)

src/AnalyzeComments/Metrics/CDS.php (3 issues)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SavinMikhail\CommentsDensity\AnalyzeComments\Metrics;
6
7
use InvalidArgumentException;
8
use Mikhail\PrimitiveWrappers\Int\Integer;
9
use SavinMikhail\CommentsDensity\AnalyzeComments\Analyzer\DTO\Output\CdsDTO;
0 ignored issues
show
The type SavinMikhail\CommentsDen...lyzer\DTO\Output\CdsDTO 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...
10
use SavinMikhail\CommentsDensity\AnalyzeComments\Analyzer\DTO\Output\CommentStatisticsDTO;
0 ignored issues
show
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...
11
use SavinMikhail\CommentsDensity\AnalyzeComments\Comments\CommentTypeFactory;
0 ignored issues
show
The type SavinMikhail\CommentsDen...ents\CommentTypeFactory 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
13
use function in_array;
14
use function round;
15
16
/**
17
 * comments density score (from 0 to 1).
18
 */
19
final class CDS
20
{
21
    private const MISSING_DOCBLOCK_WEIGHT = -1;
22
23
    private bool $exceedThreshold = false;
24
25
    /**
26
     * @param array<string, float> $thresholds
27
     */
28 4
    public function __construct(
29
        private readonly array $thresholds,
30
        private readonly CommentTypeFactory $commentFactory,
31 4
    ) {}
32
33
    /**
34
     * @param CommentStatisticsDTO[] $commentStatistics
35
     */
36 2
    public function calculateCDS(array $commentStatistics): float
37
    {
38 2
        $rawScore = $this->calculateRawScore($commentStatistics);
39 2
        $minPossibleScore = $this->getMinPossibleScore($commentStatistics);
40 2
        $maxPossibleScore = $this->getMaxPossibleScore($commentStatistics);
41
42
        try {
43 2
            return (new Integer(0))
44 2
                ->scaleToRange($rawScore, $minPossibleScore, $maxPossibleScore);
45
        } catch (InvalidArgumentException) {
46
            return 0;
47
        }
48
    }
49
50 2
    public function prepareCDS(float $cds): CdsDTO
51
    {
52 2
        $cds = round($cds, 2);
53
54 2
        return new CdsDTO(
55 2
            $cds,
56 2
            $this->getColorForCDS($cds),
57 2
        );
58
    }
59
60 1
    public function hasExceededThreshold(): bool
61
    {
62 1
        return $this->exceedThreshold;
63
    }
64
65
    /**
66
     * @param CommentStatisticsDTO[] $commentStatistics
67
     */
68 2
    private function calculateRawScore(array $commentStatistics): float
69
    {
70 2
        $rawScore = 0;
71
72 2
        foreach ($commentStatistics as $stat) {
73 2
            $comment = $this->commentFactory->getCommentType($stat->type);
74 2
            if ($comment) {
75 2
                $rawScore += $stat->count * $comment->getWeight();
76
77 2
                continue;
78
            }
79
            $rawScore += $stat->count * self::MISSING_DOCBLOCK_WEIGHT;
80
        }
81
82 2
        return $rawScore;
83
    }
84
85
    /**
86
     * @param CommentStatisticsDTO[] $commentStatistics
87
     */
88 2
    private function getMinPossibleScore(array $commentStatistics): float
89
    {
90 2
        $minScore = 0;
91 2
        foreach ($commentStatistics as $stat) {
92 2
            $comment = $this->commentFactory->getCommentType($stat->type);
93 2
            if (!$comment) {
94
                $minScore += self::MISSING_DOCBLOCK_WEIGHT * $stat->count;
95
96
                continue;
97
            }
98 2
            if ($comment->getWeight() < 0) {
99 2
                $minScore += $comment->getWeight() * $stat->count;
100
101 2
                continue;
102
            }
103 2
            $minScore -= $comment->getWeight() * $stat->count;
104
        }
105
106 2
        return $minScore;
107
    }
108
109
    /**
110
     * @param CommentStatisticsDTO[] $commentStatistics
111
     */
112 2
    private function getMaxPossibleScore(array $commentStatistics): float
113
    {
114 2
        $maxAmountOfDocBlock = 0;
115 2
        foreach ($commentStatistics as $statisticsDTO) {
116 2
            if (in_array($statisticsDTO->type, ['missingDocblock', 'docblock'], true)) {
117 2
                $maxAmountOfDocBlock += $statisticsDTO->count;
118
            }
119
        }
120
121 2
        return $maxAmountOfDocBlock * $this->commentFactory->getCommentType('docBlock')->getWeight();
122
    }
123
124 3
    private function getColorForCDS(float $cds): string
125
    {
126 3
        if (! isset($this->thresholds['CDS'])) {
127 1
            return 'white';
128
        }
129 3
        if ($cds >= $this->thresholds['CDS']) {
130 2
            return 'green';
131
        }
132 2
        $this->exceedThreshold = true;
133
134 2
        return 'red';
135
    }
136
}
137