From 71a7a8e8a13515578ae6c8ac86a5a0c2de74f4a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Tue, 1 Oct 2024 18:09:54 +0200 Subject: [PATCH] Removing Halstead, one tool, one job --- bin/cognitive-analysis | 2 +- composer.json | 4 +- docs/Halstead-Complexity-Analysis.md | 9 - readme.md | 7 - src/Application.php | 53 +--- src/Business/Cognitive/BaselineService.php | 6 +- src/Business/Cognitive/CognitiveMetrics.php | 2 +- .../Cognitive/CognitiveMetricsCollection.php | 2 +- .../Cognitive/CognitiveMetricsCollector.php | 20 +- src/Business/Cognitive/Delta.php | 2 +- .../Cognitive/Exporter/CsvExporter.php | 4 +- .../Exporter/DataExporterInterface.php | 2 +- .../Cognitive/Exporter/HtmlExporter.php | 4 +- .../Cognitive/Exporter/JsonExporter.php | 4 +- .../Cognitive/FindMetricsPluginInterface.php | 2 +- src/Business/Cognitive/MetricNames.php | 2 +- src/Business/Cognitive/ScoreCalculator.php | 2 +- src/Business/DirectoryScanner.php | 2 +- .../Halstead/Exporter/CsvExporter.php | 86 ------ .../Halstead/Exporter/JsonExporter.php | 27 -- src/Business/Halstead/HalsteadMetrics.php | 207 ------------- .../Halstead/HalsteadMetricsCollection.php | 89 ------ .../Halstead/HalsteadMetricsCollector.php | 123 -------- src/Business/MetricsFacade.php | 30 +- src/CognitiveAnalysisException.php | 2 +- .../CognitiveCollectorShellOutputPlugin.php | 8 +- src/Command/CognitiveMetricsCommand.php | 10 +- src/Command/HalsteadMetricsCommand.php | 127 -------- .../CognitiveMetricTextRenderer.php | 6 +- .../HalsteadMetricTextRenderer.php | 78 ----- src/Config/ConfigLoader.php | 4 +- src/Config/ConfigService.php | 2 +- src/PhpParser/CognitiveMetricsVisitor.php | 2 +- src/PhpParser/HalsteadMetricsVisitor.php | 271 ------------------ .../CognitiveMetricsCollectionTest.php | 6 +- .../CognitiveMetricsCollectorTest.php | 16 +- .../Cognitive/CognitiveMetricsTest.php | 6 +- tests/Unit/Business/Cognitive/DeltaTest.php | 4 +- .../Cognitive/Exporter/CsvExporterTest.php | 8 +- .../Cognitive/Exporter/JsonExporterTest.php | 8 +- .../Cognitive/ScoreCalculatorTest.php | 10 +- tests/Unit/Business/DirectoryScannerTest.php | 4 +- .../Halstead/Exporter/CsvExporterTest.php | 83 ------ .../HalsteadMetricsCollectionTest.php | 124 -------- .../Halstead/HalsteadMetricsCollectorTest.php | 29 -- .../Business/Halstead/HalsteadMetricsTest.php | 156 ---------- tests/Unit/Business/MetricsFacadeTest.php | 14 +- tests/Unit/Config/ConfigLoaderTest.php | 4 +- .../PhpParser/CognitiveMetricsVisitorTest.php | 4 +- 49 files changed, 106 insertions(+), 1571 deletions(-) delete mode 100644 docs/Halstead-Complexity-Analysis.md delete mode 100644 src/Business/Halstead/Exporter/CsvExporter.php delete mode 100644 src/Business/Halstead/Exporter/JsonExporter.php delete mode 100644 src/Business/Halstead/HalsteadMetrics.php delete mode 100644 src/Business/Halstead/HalsteadMetricsCollection.php delete mode 100644 src/Business/Halstead/HalsteadMetricsCollector.php delete mode 100644 src/Command/HalsteadMetricsCommand.php delete mode 100644 src/Command/Presentation/HalsteadMetricTextRenderer.php delete mode 100644 src/PhpParser/HalsteadMetricsVisitor.php delete mode 100644 tests/Unit/Business/Halstead/Exporter/CsvExporterTest.php delete mode 100644 tests/Unit/Business/Halstead/HalsteadMetricsCollectionTest.php delete mode 100644 tests/Unit/Business/Halstead/HalsteadMetricsCollectorTest.php delete mode 100644 tests/Unit/Business/Halstead/HalsteadMetricsTest.php diff --git a/bin/cognitive-analysis b/bin/cognitive-analysis index 8629f1b..1437080 100755 --- a/bin/cognitive-analysis +++ b/bin/cognitive-analysis @@ -7,6 +7,6 @@ if (file_exists(__DIR__ . '/../../../autoload.php')) { require_once __DIR__ . '/../vendor/autoload.php'; } -use Phauthentic\CodeQualityMetrics\Application; +use Phauthentic\CognitiveCodeAnalysis\Application; (new Application())->run(); diff --git a/composer.json b/composer.json index 52852fe..c4d17bb 100644 --- a/composer.json +++ b/composer.json @@ -12,12 +12,12 @@ }, "autoload": { "psr-4": { - "Phauthentic\\CodeQualityMetrics\\": "src/" + "Phauthentic\\CognitiveCodeAnalysis\\": "src/" } }, "autoload-dev": { "psr-4": { - "Phauthentic\\CodeQualityMetrics\\Tests\\": "tests/" + "Phauthentic\\CognitiveCodeAnalysis\\Tests\\": "tests/" } }, "authors": [ diff --git a/docs/Halstead-Complexity-Analysis.md b/docs/Halstead-Complexity-Analysis.md deleted file mode 100644 index 6f6fe79..0000000 --- a/docs/Halstead-Complexity-Analysis.md +++ /dev/null @@ -1,9 +0,0 @@ -# Halstead Complexity Analysis - -> Halstead's goal was to identify measurable properties of software, and the relations between them. This is similar to the identification of measurable properties of matter (like the volume, mass, and pressure of a gas) and the relationships between them (analogous to the gas equation). Thus his metrics are actually not just complexity metrics. - -[Source](https://en.wikipedia.org/wiki/Halstead_complexity_measures) - -## Result Interpretation - -It is up to you how to interpret the results, the Halstead metrics are probably even more controversial than the cognitive complexity metrics. diff --git a/readme.md b/readme.md index 882e553..c475f9d 100644 --- a/readme.md +++ b/readme.md @@ -26,12 +26,6 @@ You can also pass a baseline file to compare the results to. The JSON report is bin/cognitive-analysis metrics:cognitive --baseline cognitive.json ``` -Halstead Complexity Analysis - -```bash -bin/cognitive-analysis metrics:halstead -``` - ## Documentation * [Cognitive Complexity Analysis](./docs/Cognitive-Complexity-Analysis.md#cognitive-complexity-analysis) @@ -45,7 +39,6 @@ bin/cognitive-analysis metrics:halstead * [Examples](#examples) * [Wordpress WP_Debug_Data](#wordpress-wp_debug_data) * [Doctrine Paginator](#doctrine-paginator) -* [Halstead Complexity Analysis](./docs/Halstead-Complexity-Analysis.md) ## Resources diff --git a/src/Application.php b/src/Application.php index 96b6174..6e02f4d 100644 --- a/src/Application.php +++ b/src/Application.php @@ -2,22 +2,18 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics; - -use Phauthentic\CodeQualityMetrics\Business\Cognitive\BaselineService; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollector; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\FindMetricsPluginInterface; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\ScoreCalculator; -use Phauthentic\CodeQualityMetrics\Business\DirectoryScanner; -use Phauthentic\CodeQualityMetrics\Business\Halstead\HalsteadMetricsCollector; -use Phauthentic\CodeQualityMetrics\Command\Cognitive\CognitiveCollectorShellOutputPlugin; -use Phauthentic\CodeQualityMetrics\Command\CognitiveMetricsCommand; -use Phauthentic\CodeQualityMetrics\Command\HalsteadMetricsCommand; -use Phauthentic\CodeQualityMetrics\Business\MetricsFacade; -use Phauthentic\CodeQualityMetrics\Command\Presentation\CognitiveMetricTextRenderer; -use Phauthentic\CodeQualityMetrics\Command\Presentation\HalsteadMetricTextRenderer; -use Phauthentic\CodeQualityMetrics\Config\ConfigLoader; -use Phauthentic\CodeQualityMetrics\Config\ConfigService; +namespace Phauthentic\CognitiveCodeAnalysis; + +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\BaselineService; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollector; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\ScoreCalculator; +use Phauthentic\CognitiveCodeAnalysis\Business\DirectoryScanner; +use Phauthentic\CognitiveCodeAnalysis\Command\Cognitive\CognitiveCollectorShellOutputPlugin; +use Phauthentic\CognitiveCodeAnalysis\Command\CognitiveMetricsCommand; +use Phauthentic\CognitiveCodeAnalysis\Business\MetricsFacade; +use Phauthentic\CognitiveCodeAnalysis\Command\Presentation\CognitiveMetricTextRenderer; +use Phauthentic\CognitiveCodeAnalysis\Config\ConfigLoader; +use Phauthentic\CognitiveCodeAnalysis\Config\ConfigService; use PhpParser\NodeTraverser; use PhpParser\NodeTraverserInterface; use PhpParser\ParserFactory; @@ -45,9 +41,6 @@ public function __construct() private function registerServices(): void { - $this->containerBuilder->register(HalsteadMetricsCollector::class, HalsteadMetricsCollector::class) - ->setPublic(true); - $this->containerBuilder->register(CognitiveMetricsCollector::class, CognitiveMetricsCollector::class) ->setPublic(true); @@ -57,9 +50,6 @@ private function registerServices(): void $this->containerBuilder->register(ConfigService::class, ConfigService::class) ->setPublic(true); - $this->containerBuilder->register(HalsteadMetricTextRenderer::class, HalsteadMetricTextRenderer::class) - ->setPublic(true); - $this->containerBuilder->register(CognitiveMetricTextRenderer::class, CognitiveMetricTextRenderer::class) ->setPublic(true); @@ -121,14 +111,6 @@ private function bootstrapMetricsCollectors(): void ] ]) ->setPublic(true); - - $this->containerBuilder->register(HalsteadMetricsCollector::class, HalsteadMetricsCollector::class) - ->setArguments([ - new Reference(ParserFactory::class), - new Reference(NodeTraverserInterface::class), - new Reference(DirectoryScanner::class), - ]) - ->setPublic(true); } private function configureConfigService(): void @@ -145,7 +127,6 @@ private function registerMetricsFacade(): void { $this->containerBuilder->register(MetricsFacade::class, MetricsFacade::class) ->setArguments([ - new Reference(HalsteadMetricsCollector::class), new Reference(CognitiveMetricsCollector::class), new Reference(ScoreCalculator::class), new Reference(ConfigService::class), @@ -162,21 +143,13 @@ private function registerCommands(): void new Reference(BaselineService::class), ]) ->setPublic(true); - - $this->containerBuilder->register(HalsteadMetricsCommand::class, HalsteadMetricsCommand::class) - ->setArguments([ - new Reference(MetricsFacade::class), - new Reference(HalsteadMetricTextRenderer::class), - ]) - ->setPublic(true); } private function configureApplication(): void { $this->containerBuilder->register(SymfonyApplication::class, SymfonyApplication::class) ->setPublic(true) - ->addMethodCall('add', [new Reference(CognitiveMetricsCommand::class)]) - ->addMethodCall('add', [new Reference(HalsteadMetricsCommand::class)]); + ->addMethodCall('add', [new Reference(CognitiveMetricsCommand::class)]); } public function run(): void diff --git a/src/Business/Cognitive/BaselineService.php b/src/Business/Cognitive/BaselineService.php index b82a5fe..ee0d442 100644 --- a/src/Business/Cognitive/BaselineService.php +++ b/src/Business/Cognitive/BaselineService.php @@ -2,8 +2,9 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive; +use JsonException; use RuntimeException; /** @@ -30,13 +31,12 @@ public function calculateDeltas(CognitiveMetricsCollection $metricsCollection, a } } - /** * Loads the baseline file and returns the data as an array. * * @param string $baselineFile * @return array> $baseline - * @throws \JsonException + * @throws JsonException */ public function loadBaseline(string $baselineFile): array { diff --git a/src/Business/Cognitive/CognitiveMetrics.php b/src/Business/Cognitive/CognitiveMetrics.php index b4762a2..6c30c43 100644 --- a/src/Business/Cognitive/CognitiveMetrics.php +++ b/src/Business/Cognitive/CognitiveMetrics.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive; use InvalidArgumentException; use JsonSerializable; diff --git a/src/Business/Cognitive/CognitiveMetricsCollection.php b/src/Business/Cognitive/CognitiveMetricsCollection.php index 89d4562..84c4556 100644 --- a/src/Business/Cognitive/CognitiveMetricsCollection.php +++ b/src/Business/Cognitive/CognitiveMetricsCollection.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive; use ArrayIterator; use Closure; diff --git a/src/Business/Cognitive/CognitiveMetricsCollector.php b/src/Business/Cognitive/CognitiveMetricsCollector.php index a65ef24..10acf19 100644 --- a/src/Business/Cognitive/CognitiveMetricsCollector.php +++ b/src/Business/Cognitive/CognitiveMetricsCollector.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive; -use Phauthentic\CodeQualityMetrics\Business\DirectoryScanner; -use Phauthentic\CodeQualityMetrics\CognitiveAnalysisException; -use Phauthentic\CodeQualityMetrics\Config\ConfigService; -use Phauthentic\CodeQualityMetrics\PhpParser\CognitiveMetricsVisitor; +use Phauthentic\CognitiveCodeAnalysis\Business\DirectoryScanner; +use Phauthentic\CognitiveCodeAnalysis\CognitiveAnalysisException; +use Phauthentic\CognitiveCodeAnalysis\Config\ConfigService; +use Phauthentic\CognitiveCodeAnalysis\PhpParser\CognitiveMetricsVisitor; use PhpParser\Error; use PhpParser\NodeTraverserInterface; use PhpParser\Parser; @@ -38,7 +38,7 @@ public function __construct( * @param array $config * @return array */ - protected function getExcludePatternsFromConfig(array $config): array + private function getExcludePatternsFromConfig(array $config): array { if (isset($config['excludePatterns'])) { return $config['excludePatterns']; @@ -67,7 +67,7 @@ public function collect(string $path, array $config = []): CognitiveMetricsColle * @param iterable $files * @return CognitiveMetricsCollection */ - protected function findMetrics(iterable $files): CognitiveMetricsCollection + private function findMetrics(iterable $files): CognitiveMetricsCollection { $metricsCollection = new CognitiveMetricsCollection(); $visitor = new CognitiveMetricsVisitor(); @@ -137,7 +137,7 @@ private function processMethodMetrics( } } - public function isExcluded(string $classAndMethod): bool + private function isExcluded(string $classAndMethod): bool { $regexes = $this->configService->getConfig()['cognitive']['excludePatterns']; @@ -157,7 +157,7 @@ public function isExcluded(string $classAndMethod): bool * @param array $exclude List of regx to exclude * @return iterable An iterable of SplFileInfo objects */ - protected function findSourceFiles(string $path, array $exclude = []): iterable + private function findSourceFiles(string $path, array $exclude = []): iterable { return $this->directoryScanner->scan([$path], ['^(?!.*\.php$).+'] + $exclude); // Exclude non-PHP files } @@ -165,7 +165,7 @@ protected function findSourceFiles(string $path, array $exclude = []): iterable /** * @throws CognitiveAnalysisException */ - protected function traverseAbstractSyntaxTree(string $code): void + private function traverseAbstractSyntaxTree(string $code): void { try { $ast = $this->parser->parse($code); diff --git a/src/Business/Cognitive/Delta.php b/src/Business/Cognitive/Delta.php index a0f0d1b..54203de 100644 --- a/src/Business/Cognitive/Delta.php +++ b/src/Business/Cognitive/Delta.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive; /** * diff --git a/src/Business/Cognitive/Exporter/CsvExporter.php b/src/Business/Cognitive/Exporter/CsvExporter.php index 810cdbe..88a1c89 100644 --- a/src/Business/Cognitive/Exporter/CsvExporter.php +++ b/src/Business/Cognitive/Exporter/CsvExporter.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive\Exporter; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Exporter; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; use RuntimeException; /** diff --git a/src/Business/Cognitive/Exporter/DataExporterInterface.php b/src/Business/Cognitive/Exporter/DataExporterInterface.php index 856584c..b8820f7 100644 --- a/src/Business/Cognitive/Exporter/DataExporterInterface.php +++ b/src/Business/Cognitive/Exporter/DataExporterInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive\Exporter; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Exporter; /** * diff --git a/src/Business/Cognitive/Exporter/HtmlExporter.php b/src/Business/Cognitive/Exporter/HtmlExporter.php index db5fbcc..ac69022 100644 --- a/src/Business/Cognitive/Exporter/HtmlExporter.php +++ b/src/Business/Cognitive/Exporter/HtmlExporter.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive\Exporter; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Exporter; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; use RuntimeException; /** diff --git a/src/Business/Cognitive/Exporter/JsonExporter.php b/src/Business/Cognitive/Exporter/JsonExporter.php index 193c802..548e343 100644 --- a/src/Business/Cognitive/Exporter/JsonExporter.php +++ b/src/Business/Cognitive/Exporter/JsonExporter.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive\Exporter; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Exporter; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; use RuntimeException; /** diff --git a/src/Business/Cognitive/FindMetricsPluginInterface.php b/src/Business/Cognitive/FindMetricsPluginInterface.php index e562061..ccecba3 100644 --- a/src/Business/Cognitive/FindMetricsPluginInterface.php +++ b/src/Business/Cognitive/FindMetricsPluginInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive; use SplFileInfo; diff --git a/src/Business/Cognitive/MetricNames.php b/src/Business/Cognitive/MetricNames.php index 99b5f86..fd478fc 100644 --- a/src/Business/Cognitive/MetricNames.php +++ b/src/Business/Cognitive/MetricNames.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive; /** * Enum to represent the metric names. diff --git a/src/Business/Cognitive/ScoreCalculator.php b/src/Business/Cognitive/ScoreCalculator.php index cb97586..9fa5f54 100644 --- a/src/Business/Cognitive/ScoreCalculator.php +++ b/src/Business/Cognitive/ScoreCalculator.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Business\Cognitive; /** * diff --git a/src/Business/DirectoryScanner.php b/src/Business/DirectoryScanner.php index c1519b0..9caf866 100644 --- a/src/Business/DirectoryScanner.php +++ b/src/Business/DirectoryScanner.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business; +namespace Phauthentic\CognitiveCodeAnalysis\Business; use FilesystemIterator; use Generator; diff --git a/src/Business/Halstead/Exporter/CsvExporter.php b/src/Business/Halstead/Exporter/CsvExporter.php deleted file mode 100644 index 44b62a9..0000000 --- a/src/Business/Halstead/Exporter/CsvExporter.php +++ /dev/null @@ -1,86 +0,0 @@ -assertTargetDirectoryExists($filename); - $this->assertIsWriteablePath($filename); - - $file = fopen($filename, 'wb'); - $file = $this->assertIsResource($file, $filename); - - fputcsv($file, $this->header); - - foreach ($metricsCollection as $metrics) { - fputcsv($file, [ - $metrics->getN1(), - $metrics->getN2(), - $metrics->getTotalOperators(), - $metrics->getTotalOperands(), - $metrics->getProgramLength(), - $metrics->getProgramVocabulary(), - $metrics->getVolume(), - $metrics->getDifficulty(), - $metrics->getEffort(), - $metrics->getPossibleBugs(), - $metrics->getClass(), - $metrics->getFile() - ]); - } - - fclose($file); - } -} diff --git a/src/Business/Halstead/Exporter/JsonExporter.php b/src/Business/Halstead/Exporter/JsonExporter.php deleted file mode 100644 index 0557755..0000000 --- a/src/Business/Halstead/Exporter/JsonExporter.php +++ /dev/null @@ -1,27 +0,0 @@ - $metrics - */ - public function __construct(array $metrics) - { - $this->assertArrayKeyIsPresent($metrics, 'n1'); - $this->assertArrayKeyIsPresent($metrics, 'n2'); - $this->assertArrayKeyIsPresent($metrics, 'N1'); - $this->assertArrayKeyIsPresent($metrics, 'N2'); - - $this->n1 = $metrics['n1']; - $this->n2 = $metrics['n2']; - $this->N1 = $metrics['N1']; - $this->N2 = $metrics['N2']; - - if (isset($metrics['class'])) { - $this->class = $metrics['class']; - } - - if (isset($metrics['file'])) { - $this->file = $metrics['file']; - } - - $this->calculateDerivedMetrics(); - } - - /** - * @param array $metrics - * @return self - */ - public static function fromArray(array $metrics): self - { - return new self($metrics); - } - - /** - * Calculate derived Halstead metrics (Program Length, Program Vocabulary, Volume, Difficulty, Effort). - */ - private function calculateDerivedMetrics(): void - { - // Program length (N) is the sum of N1 and N2 - $this->programLength = $this->N1 + $this->N2; - - // Program vocabulary (n) is the sum of n1 and n2 - $this->programVocabulary = $this->n1 + $this->n2; - - // Halstead Volume = Program length * log2(Program vocabulary) - $this->volume = $this->programLength * log($this->programVocabulary, 2); - - // Halstead Difficulty = (n1 / 2) * (N2 / n2) - $this->difficulty = ($this->n1 / 2) * ($this->N2 / $this->n2); - - // Halstead Effort = Difficulty * Volume - $this->effort = $this->difficulty * $this->volume; - - // Possible Bugs = Volume / 3000 - $this->possibleBugs = $this->volume / 3000; - } - - /** - * @param array $array - * @param string $key - * @return void - */ - private function assertArrayKeyIsPresent(array $array, string $key): void - { - if (!array_key_exists($key, $array)) { - throw new InvalidArgumentException("Missing required key: $key"); - } - } - - // Getters for read-only attributes - public function getN1(): int - { - return $this->n1; - } - - public function getN2(): int - { - return $this->n2; - } - - public function getTotalOperators(): int - { - return $this->N1; - } - - public function getTotalOperands(): int - { - return $this->N2; - } - - public function getProgramLength(): int - { - return $this->programLength; - } - - public function getProgramVocabulary(): int - { - return $this->programVocabulary; - } - - public function getVolume(): float - { - return $this->volume; - } - - public function getDifficulty(): float - { - return $this->difficulty; - } - - public function getEffort(): float - { - return $this->effort; - } - - public function getPossibleBugs(): float - { - return $this->possibleBugs; - } - - public function getClass(): ?string - { - return $this->class; - } - - public function getFile(): ?string - { - return $this->file; - } - - /** - * @return array - */ - public function toArray(): array - { - return [ - 'n1' => $this->n1, - 'n2' => $this->n2, - 'N1' => $this->N1, - 'N2' => $this->N2, - 'program_length' => $this->programLength, - 'program_vocabulary' => $this->programVocabulary, - 'volume' => $this->volume, - 'difficulty' => $this->difficulty, - 'effort' => $this->effort, - 'possible_bugs' => $this->possibleBugs, // Added for possible bugs - 'class' => $this->class, - 'file' => $this->file - ]; - } - - /** - * @return array - */ - public function jsonSerialize(): array - { - return $this->toArray(); - } - - /** - * Compares two HalsteadMetrics objects to see if they are equal. - * - * @param self $metrics - * @return bool - */ - public function equals(self $metrics): bool - { - return $metrics->getN1() === $this->n1 - && $metrics->getN2() === $this->n2 - && $metrics->getTotalOperators() === $this->N1 - && $metrics->getTotalOperands() === $this->N2 - && $metrics->getClass() === $this->class - && $metrics->getFile() === $this->file; - } -} diff --git a/src/Business/Halstead/HalsteadMetricsCollection.php b/src/Business/Halstead/HalsteadMetricsCollection.php deleted file mode 100644 index f5aabb3..0000000 --- a/src/Business/Halstead/HalsteadMetricsCollection.php +++ /dev/null @@ -1,89 +0,0 @@ - - */ -class HalsteadMetricsCollection implements IteratorAggregate, Countable, JsonSerializable -{ - /** - * @var HalsteadMetrics[] - */ - private array $metrics = []; - - /** - * Add a HalsteadMetrics object to the collection - */ - public function add(HalsteadMetrics $metric): void - { - $this->metrics[] = $metric; - } - - /** - * Filter the collection using a callback function - * - * @return self A new collection with filtered results - */ - public function filter(Closure $callback): self - { - $filtered = array_filter($this->metrics, $callback); - - $newCollection = new self(); - foreach ($filtered as $metric) { - $newCollection->add($metric); - } - - return $newCollection; - } - - /** - * Get an iterator for the collection - * - * @return ArrayIterator - */ - public function getIterator(): ArrayIterator - { - return new ArrayIterator($this->metrics); - } - - /** - * Get the count of metrics in the collection - */ - public function count(): int - { - return count($this->metrics); - } - - /** - * Check if a specific HalsteadMetrics object is in the collection - */ - public function contains(HalsteadMetrics $otherMetric): bool - { - foreach ($this->metrics as $metric) { - if ($otherMetric->equals($metric)) { - return true; - } - } - - return false; - } - - /** - * @return array - */ - public function jsonSerialize(): array - { - return $this->metrics; - } -} diff --git a/src/Business/Halstead/HalsteadMetricsCollector.php b/src/Business/Halstead/HalsteadMetricsCollector.php deleted file mode 100644 index 345648d..0000000 --- a/src/Business/Halstead/HalsteadMetricsCollector.php +++ /dev/null @@ -1,123 +0,0 @@ -parser = $parserFactory->createForHostVersion(); - } - - /** - * @param array $config - * @return array - */ - protected function getExcludePatternsFromConfig(array $config): array - { - if (isset($config['excludePatterns'])) { - return $config['excludePatterns']; - } - - return []; - } - - /** - * Find source files using DirectoryScanner - * - * @param string $path Path to the directory or file to scan - * @param array $exclude List of regx to exclude - * @return iterable An iterable of SplFileInfo objects - */ - protected function findSourceFiles(string $path, array $exclude = []): iterable - { - return $this->directoryScanner->scan([$path], ['^(?!.*\.php$).+'] + $exclude); // Exclude non-PHP files - } - - protected function traverseAbstractSyntaxTree(string $code): void - { - try { - $ast = $this->parser->parse($code); - } catch (Error $e) { - throw new RuntimeException("Parse error: {$e->getMessage()}", 0, $e); - } - - if ($ast === null) { - throw new RuntimeException("Could not parse the code."); - } - - $this->traverser->traverse($ast); - } - - /** - * Collect Halstead metrics from the given path. - * - * @param string $path - * @param array $config - * @return HalsteadMetricsCollection - */ - public function collect(string $path, array $config = []): HalsteadMetricsCollection - { - $files = $this->findSourceFiles($path, $this->getExcludePatternsFromConfig($config)); - - return $this->findMetrics($files); - } - - /** - * Collect Halstead metrics from the found source files. - * - * @param iterable $files - * @return HalsteadMetricsCollection - */ - protected function findMetrics(iterable $files): HalsteadMetricsCollection - { - $metricsCollection = new HalsteadMetricsCollection(); - - foreach ($files as $file) { - $code = file_get_contents($file->getRealPath()); - - if ($code === false) { - throw new RuntimeException("Could not read file: {$file->getRealPath()}"); - } - - $halsteadMetricsVisitor = new HalsteadMetricsVisitor(); - $this->traverser->addVisitor($halsteadMetricsVisitor); - - $this->traverseAbstractSyntaxTree($code); - - $metricsData = $halsteadMetricsVisitor->getMetrics(); - $this->traverser->removeVisitor($halsteadMetricsVisitor); - - foreach ($metricsData as $class => $data) { - $data['class'] = $class; - $data['file'] = $file->getRealPath(); - $metrics = HalsteadMetrics::fromArray($data); - - if (!$metricsCollection->contains($metrics)) { - $metricsCollection->add($metrics); - } - } - } - - return $metricsCollection; - } -} diff --git a/src/Business/MetricsFacade.php b/src/Business/MetricsFacade.php index 64317dc..1b89547 100644 --- a/src/Business/MetricsFacade.php +++ b/src/Business/MetricsFacade.php @@ -2,17 +2,15 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Business; +namespace Phauthentic\CognitiveCodeAnalysis\Business; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollector; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\Exporter\CsvExporter; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\Exporter\HtmlExporter; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\Exporter\JsonExporter; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\ScoreCalculator; -use Phauthentic\CodeQualityMetrics\Business\Halstead\HalsteadMetricsCollection; -use Phauthentic\CodeQualityMetrics\Business\Halstead\HalsteadMetricsCollector; -use Phauthentic\CodeQualityMetrics\Config\ConfigService; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollector; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Exporter\CsvExporter; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Exporter\HtmlExporter; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Exporter\JsonExporter; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\ScoreCalculator; +use Phauthentic\CognitiveCodeAnalysis\Config\ConfigService; /** * Facade class for collecting and managing code quality metrics. @@ -23,7 +21,6 @@ class MetricsFacade * Constructor initializes the metrics collectors, score calculator, and config service. */ public function __construct( - private readonly HalsteadMetricsCollector $halsteadMetricsCollector, private readonly CognitiveMetricsCollector $cognitiveMetricsCollector, private readonly ScoreCalculator $scoreCalculator, private readonly ConfigService $configService @@ -31,17 +28,6 @@ public function __construct( $this->loadConfig(__DIR__ . '/../../config.yml'); } - /** - * Collects and returns Halstead metrics for the given path. - * - * @param string $path The file or directory path to collect metrics from. - * @return HalsteadMetricsCollection The collected Halstead metrics. - */ - public function getHalsteadMetrics(string $path): HalsteadMetricsCollection - { - return $this->halsteadMetricsCollector->collect($path); - } - /** * Collects and returns cognitive metrics for the given path. * diff --git a/src/CognitiveAnalysisException.php b/src/CognitiveAnalysisException.php index b58c532..93f2be3 100644 --- a/src/CognitiveAnalysisException.php +++ b/src/CognitiveAnalysisException.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics; +namespace Phauthentic\CognitiveCodeAnalysis; use Exception; diff --git a/src/Command/Cognitive/CognitiveCollectorShellOutputPlugin.php b/src/Command/Cognitive/CognitiveCollectorShellOutputPlugin.php index a9c0e59..a516c3d 100644 --- a/src/Command/Cognitive/CognitiveCollectorShellOutputPlugin.php +++ b/src/Command/Cognitive/CognitiveCollectorShellOutputPlugin.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Command\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Command\Cognitive; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\FindMetricsPluginInterface; -use Phauthentic\CodeQualityMetrics\Command\CognitiveMetricsCommand; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\FindMetricsPluginInterface; +use Phauthentic\CognitiveCodeAnalysis\Command\CognitiveMetricsCommand; use SplFileInfo; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/Command/CognitiveMetricsCommand.php b/src/Command/CognitiveMetricsCommand.php index cda875a..0271fd0 100644 --- a/src/Command/CognitiveMetricsCommand.php +++ b/src/Command/CognitiveMetricsCommand.php @@ -2,13 +2,13 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Command; +namespace Phauthentic\CognitiveCodeAnalysis\Command; use Exception; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\BaselineService; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; -use Phauthentic\CodeQualityMetrics\Business\MetricsFacade; -use Phauthentic\CodeQualityMetrics\Command\Presentation\CognitiveMetricTextRenderer; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\BaselineService; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\MetricsFacade; +use Phauthentic\CognitiveCodeAnalysis\Command\Presentation\CognitiveMetricTextRenderer; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; diff --git a/src/Command/HalsteadMetricsCommand.php b/src/Command/HalsteadMetricsCommand.php deleted file mode 100644 index 8a34f86..0000000 --- a/src/Command/HalsteadMetricsCommand.php +++ /dev/null @@ -1,127 +0,0 @@ -addArgument(self::ARGUMENT_PATH, InputArgument::REQUIRED, 'Path to PHP files or directories to parse.') - ->addOption(self::OPTION_EXPORT_CSV, null, InputArgument::OPTIONAL, 'Writes metrics to a CSV file', null) - ->addOption(self::OPTION_EXPORT_JSON, null, InputArgument::OPTIONAL, 'Writes metrics to a JSON file', null) - ->addOption(self::OPTION_EXPORT_HTML, null, InputArgument::OPTIONAL, 'Writes metrics to an HTML file', null) - ->addOption(self::OPTION_CONFIG_FILE, null, InputArgument::OPTIONAL, 'Path to a configuration file', null); - } - - /** - * Executes the command. - * - * @param InputInterface $input - * @param OutputInterface $output - * @return int Command status code. - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - // Get the path to the files or directories to analyze. - $path = $input->getArgument(self::ARGUMENT_PATH); - - // Load configuration if the option is provided. - $configFile = $input->getOption(self::OPTION_CONFIG_FILE); - if ($configFile && !$this->loadConfiguration($configFile, $output)) { - return Command::FAILURE; - } - - // Generate metrics for the provided path. - $metricsCollection = $this->metricsFacade->getHalsteadMetrics($path); - - // Render the metrics to the console. - $this->metricTextRenderer->render($metricsCollection, $output); - - // Handle different export options. - $this->handleExportOptions($input, $metricsCollection); - - return Command::SUCCESS; - } - - /** - * Loads configuration and handles errors. - * - * @param string $configFile - * @param OutputInterface $output - * @return bool Success or failure. - */ - private function loadConfiguration(string $configFile, OutputInterface $output): bool - { - try { - $this->metricsFacade->loadConfig($configFile); - return true; - } catch (Exception $e) { - $output->writeln('Failed to load configuration: ' . $e->getMessage() . ''); - return false; - } - } - - /** - * Handles exporting metrics to different formats based on user input. - * - * @param InputInterface $input - * @param HalsteadMetricsCollection $metricsCollection - * @return void - */ - private function handleExportOptions(InputInterface $input, HalsteadMetricsCollection $metricsCollection): void - { - if ($input->getOption(self::OPTION_EXPORT_JSON)) { - $file = $input->getOption(self::OPTION_EXPORT_JSON); - (new JsonExporter())->export($metricsCollection, $file); - } - - if ($input->getOption(self::OPTION_EXPORT_CSV)) { - $file = $input->getOption(self::OPTION_EXPORT_CSV); - (new CsvExporter())->export($metricsCollection, $file); - } - } -} diff --git a/src/Command/Presentation/CognitiveMetricTextRenderer.php b/src/Command/Presentation/CognitiveMetricTextRenderer.php index 98104df..98aa364 100644 --- a/src/Command/Presentation/CognitiveMetricTextRenderer.php +++ b/src/Command/Presentation/CognitiveMetricTextRenderer.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Command\Presentation; +namespace Phauthentic\CognitiveCodeAnalysis\Command\Presentation; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetrics; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetrics; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; use RuntimeException; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/Command/Presentation/HalsteadMetricTextRenderer.php b/src/Command/Presentation/HalsteadMetricTextRenderer.php deleted file mode 100644 index 371c9b4..0000000 --- a/src/Command/Presentation/HalsteadMetricTextRenderer.php +++ /dev/null @@ -1,78 +0,0 @@ -writeln("Class: " . $metrics->getclass() . " "); - $output->writeln("File: " . $metrics->getFile() . " "); - - $table = new Table($output); - $table->setStyle('box'); - $table->setHeaders($this->getTableHeaders()); - - $rows = []; - $data = $this->prepareTableRow($metrics); - $rows[] = array_values($data); - - $table->setRows($rows); - - $table->render(); - $output->writeln(""); - } - } - - /** - * @return string[] - */ - protected function getTableHeaders(): array - { - return [ - "n1 Distinct\nOperators", - "n2 Distinct\nOperands", - "Total\nOperators", - "Total\nOperands", - "Program\nLength", - "Program\nVocabulary", - "Volume", - "Difficulty", - "Effort", - "Possible\nBugs" - ]; - } - - /** - * @param \Phauthentic\CodeQualityMetrics\Business\Halstead\HalsteadMetrics $metrics - * @return array - */ - protected function prepareTableRow(HalsteadMetrics $metrics): array - { - return [ - 'n1' => $metrics->getN1(), - 'n2' => $metrics->getN2(), - 'N1' => $metrics->getTotalOperators(), - 'N2' => $metrics->getTotalOperands(), - 'programLength' => $metrics->getProgramLength(), - 'programVocabulary' => $metrics->getProgramVocabulary(), - 'volume' => round($metrics->getVolume(), 2), - 'difficulty' => round($metrics->getDifficulty(), 2), - 'effort' => round($metrics->getEffort(), 2), - 'possibleBugs' => round($metrics->getPossibleBugs(), 2) - ]; - } -} diff --git a/src/Config/ConfigLoader.php b/src/Config/ConfigLoader.php index ea97c65..c0d3a88 100644 --- a/src/Config/ConfigLoader.php +++ b/src/Config/ConfigLoader.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Config; +namespace Phauthentic\CognitiveCodeAnalysis\Config; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\MetricNames; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\MetricNames; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; diff --git a/src/Config/ConfigService.php b/src/Config/ConfigService.php index 221bb9f..f67b31b 100644 --- a/src/Config/ConfigService.php +++ b/src/Config/ConfigService.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Config; +namespace Phauthentic\CognitiveCodeAnalysis\Config; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Config\Definition\Processor; diff --git a/src/PhpParser/CognitiveMetricsVisitor.php b/src/PhpParser/CognitiveMetricsVisitor.php index 02aadd7..3c61c9d 100644 --- a/src/PhpParser/CognitiveMetricsVisitor.php +++ b/src/PhpParser/CognitiveMetricsVisitor.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\PhpParser; +namespace Phauthentic\CognitiveCodeAnalysis\PhpParser; use PhpParser\Node; use PhpParser\NodeVisitorAbstract; diff --git a/src/PhpParser/HalsteadMetricsVisitor.php b/src/PhpParser/HalsteadMetricsVisitor.php deleted file mode 100644 index c07ece3..0000000 --- a/src/PhpParser/HalsteadMetricsVisitor.php +++ /dev/null @@ -1,271 +0,0 @@ -setCurrentNamespace($node); - } elseif ($node instanceof Class_) { - $this->setCurrentClassName($node); - } elseif ($this->isOperator($node)) { - $this->addOperator($node); - } elseif ($this->isOperand($node)) { - $this->addOperand($node); - } - } - - private function setCurrentNamespace(Namespace_ $node): void - { - $this->currentNamespace = $node->name ? $node->name->toString() : null; - } - - private function setCurrentClassName(Class_ $node): void - { - $className = $node->name ? $node->name->toString() : ''; - $this->currentClassName = $this->currentNamespace - ? $this->currentNamespace . '\\' . $className - : $className; - } - - private function addOperator(Node $node): void - { - $this->operators[] = $node->getType(); - } - - private function addOperand(Node $node): void - { - $this->operands[] = $this->getOperandValue($node); - } - - public function leaveNode(Node $node) - { - if ($node instanceof Class_) { - // Store metrics for the class before resetting - $this->storeClassMetrics(); - $this->resetMetrics(); - } - } - - private function isOperator(Node $node): bool - { - return $node instanceof Node\Expr\BinaryOp - || $node instanceof Node\Expr\Assign - || $node instanceof Node\Expr\FuncCall - || $node instanceof Node\Expr\MethodCall; - } - - private function isOperand(Node $node): bool - { - return $node instanceof Node\Expr\Variable - || $node instanceof Node\Scalar\String_ - || $node instanceof Node\Scalar\LNumber - || $node instanceof Node\Scalar\DNumber; - } - - private function getOperandValue(Node $node): string - { - if ($node instanceof Node\Expr\Variable) { - return '$' . $node->name; - } - - if ($node instanceof Node\Scalar\String_) { - return (string) $node->value; - } - - if ($node instanceof Node\Scalar\LNumber || $node instanceof Node\Scalar\DNumber) { - return (string) $node->value; - } - - return ''; - } - - private function storeClassMetrics(): void - { - if ($this->currentClassName !== null) { - $this->classMetrics[$this->currentClassName] = $this->calculateMetrics(); - } - } - - public function resetMetrics(): void - { - $this->operators = []; - $this->operands = []; - $this->currentClassName = null; - } - - private function calculateMetrics(): array - { - // Step 1: Count distinct and total occurrences of operators and operands - $distinctOperators = $this->countDistinctOperators(); - $distinctOperands = $this->countDistinctOperands(); - $totalOperators = $this->countTotalOperators(); - $totalOperands = $this->countTotalOperands(); - - // Step 2: Calculate basic metrics - $programLength = $this->calculateProgramLength($totalOperators, $totalOperands); - $programVocabulary = $this->calculateProgramVocabulary($distinctOperators, $distinctOperands); - - // Step 3: Calculate advanced metrics - $volume = $this->calculateVolume($programLength, $programVocabulary); - $difficulty = $this->calculateDifficulty($distinctOperators, $totalOperands, $distinctOperands); - $effort = $difficulty * $volume; - - // Step 4: Prepare the results array - return [ - 'n1' => $distinctOperators, - 'n2' => $distinctOperands, - 'N1' => $totalOperators, - 'N2' => $totalOperands, - 'programLength' => $programLength, - 'programVocabulary' => $programVocabulary, - 'volume' => $volume, - 'difficulty' => $difficulty, - 'effort' => $effort, - 'className' => $this->currentClassName, // Include the FQCN - ]; - } - - /** - * Calculate the program length. - * - * @param int $N1 The total occurrences of operators. - * @param int $N2 The total occurrences of operands. - * @return int The program length. - */ - private function calculateProgramLength(int $N1, int $N2): int - { - return $N1 + $N2; - } - - /** - * Calculate the program vocabulary. - * - * @param int $n1 The count of distinct operators. - * @param int $n2 The count of distinct operands. - * @return int The program vocabulary. - */ - private function calculateProgramVocabulary(int $n1, int $n2): int - { - return $n1 + $n2; - } - - /** - * Calculate the volume of the program. - * - * @param int $programLength The length of the program. - * @param int $programVocabulary The vocabulary of the program. - * @return float The volume of the program. - */ - private function calculateVolume(int $programLength, int $programVocabulary): float - { - return $programLength * log($programVocabulary, 2); - } - - /** - * Calculate the difficulty of the program. - * - * @param int $n1 The count of distinct operators. - * @param int $N2 The total occurrences of operands. - * @param int $n2 The count of distinct operands. - * @return float The difficulty of the program. - */ - private function calculateDifficulty(int $n1, int $N2, int $n2): float - { - return ($n1 / 2) * ($N2 / $n2); - } - - /** - * Calculate the effort required for the program. - * - * @param float $difficulty The difficulty of the program. - * @param float $volume The volume of the program. - * @return float The effort required for the program. - */ - private function calculateEffort(float $difficulty, float $volume): float - { - return $difficulty * $volume; - } - - /** - * Count the number of distinct operators. - * - * @return int The count of distinct operators. - */ - private function countDistinctOperators(): int - { - return count(array_unique($this->operators)); - } - - /** - * Count the number of distinct operands. - * - * @return int The count of distinct operands. - */ - private function countDistinctOperands(): int - { - return count(array_unique($this->operands)); - } - - /** - * Count the total occurrences of operators. - * - * @return int The total occurrences of operators. - */ - private function countTotalOperators(): int - { - return count($this->operators); - } - - /** - * Count the total occurrences of operands. - * - * @return int The total occurrences of operands. - */ - private function countTotalOperands(): int - { - return count($this->operands); - } - - public function getMetrics(): array - { - // In case we haven't left the last class - if ($this->currentClassName !== null) { - $this->storeClassMetrics(); - } - - return $this->classMetrics; - } -} diff --git a/tests/Unit/Business/Cognitive/CognitiveMetricsCollectionTest.php b/tests/Unit/Business/Cognitive/CognitiveMetricsCollectionTest.php index d521dce..5538282 100644 --- a/tests/Unit/Business/Cognitive/CognitiveMetricsCollectionTest.php +++ b/tests/Unit/Business/Cognitive/CognitiveMetricsCollectionTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Business\Cognitive; use ArrayIterator; use InvalidArgumentException; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetrics; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetrics; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Unit/Business/Cognitive/CognitiveMetricsCollectorTest.php b/tests/Unit/Business/Cognitive/CognitiveMetricsCollectorTest.php index 5ca4fa0..0fd910e 100644 --- a/tests/Unit/Business/Cognitive/CognitiveMetricsCollectorTest.php +++ b/tests/Unit/Business/Cognitive/CognitiveMetricsCollectorTest.php @@ -2,14 +2,14 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Business\Cognitive; - -use Phauthentic\CodeQualityMetrics\Business\AbstractMetricCollector; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollector; -use Phauthentic\CodeQualityMetrics\Business\DirectoryScanner; -use Phauthentic\CodeQualityMetrics\Config\ConfigLoader; -use Phauthentic\CodeQualityMetrics\Config\ConfigService; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Business\Cognitive; + +use Phauthentic\CognitiveCodeAnalysis\Business\AbstractMetricCollector; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollector; +use Phauthentic\CognitiveCodeAnalysis\Business\DirectoryScanner; +use Phauthentic\CognitiveCodeAnalysis\Config\ConfigLoader; +use Phauthentic\CognitiveCodeAnalysis\Config\ConfigService; use PhpParser\NodeTraverser; use PhpParser\ParserFactory; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Business/Cognitive/CognitiveMetricsTest.php b/tests/Unit/Business/Cognitive/CognitiveMetricsTest.php index e854d0d..61c6687 100644 --- a/tests/Unit/Business/Cognitive/CognitiveMetricsTest.php +++ b/tests/Unit/Business/Cognitive/CognitiveMetricsTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Business\Cognitive; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetrics; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\Delta; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetrics; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Delta; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Unit/Business/Cognitive/DeltaTest.php b/tests/Unit/Business/Cognitive/DeltaTest.php index 2591797..138472d 100644 --- a/tests/Unit/Business/Cognitive/DeltaTest.php +++ b/tests/Unit/Business/Cognitive/DeltaTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Business\Cognitive; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\Delta; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Delta; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Unit/Business/Cognitive/Exporter/CsvExporterTest.php b/tests/Unit/Business/Cognitive/Exporter/CsvExporterTest.php index a54794a..d8b3de9 100644 --- a/tests/Unit/Business/Cognitive/Exporter/CsvExporterTest.php +++ b/tests/Unit/Business/Cognitive/Exporter/CsvExporterTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Business\Cognitive\Exporter; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Business\Cognitive\Exporter; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetrics; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\Exporter\CsvExporter; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetrics; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Exporter\CsvExporter; use PHPUnit\Framework\TestCase; use RuntimeException; diff --git a/tests/Unit/Business/Cognitive/Exporter/JsonExporterTest.php b/tests/Unit/Business/Cognitive/Exporter/JsonExporterTest.php index 98582af..778d04d 100644 --- a/tests/Unit/Business/Cognitive/Exporter/JsonExporterTest.php +++ b/tests/Unit/Business/Cognitive/Exporter/JsonExporterTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Business\Cognitive\Exporter; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Business\Cognitive\Exporter; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetrics; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetricsCollection; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\Exporter\JsonExporter; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetrics; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetricsCollection; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\Exporter\JsonExporter; use PHPUnit\Framework\TestCase; /** diff --git a/tests/Unit/Business/Cognitive/ScoreCalculatorTest.php b/tests/Unit/Business/Cognitive/ScoreCalculatorTest.php index 0a4d092..f96824b 100644 --- a/tests/Unit/Business/Cognitive/ScoreCalculatorTest.php +++ b/tests/Unit/Business/Cognitive/ScoreCalculatorTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Business\Cognitive; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Business\Cognitive; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\CognitiveMetrics; -use Phauthentic\CodeQualityMetrics\Business\Cognitive\ScoreCalculator; -use Phauthentic\CodeQualityMetrics\Config\ConfigLoader; -use Phauthentic\CodeQualityMetrics\Config\ConfigService; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\CognitiveMetrics; +use Phauthentic\CognitiveCodeAnalysis\Business\Cognitive\ScoreCalculator; +use Phauthentic\CognitiveCodeAnalysis\Config\ConfigLoader; +use Phauthentic\CognitiveCodeAnalysis\Config\ConfigService; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Processor; diff --git a/tests/Unit/Business/DirectoryScannerTest.php b/tests/Unit/Business/DirectoryScannerTest.php index fa02d01..649d734 100644 --- a/tests/Unit/Business/DirectoryScannerTest.php +++ b/tests/Unit/Business/DirectoryScannerTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Business\Halstead; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Business\Halstead; use FilesystemIterator; -use Phauthentic\CodeQualityMetrics\Business\DirectoryScanner; +use Phauthentic\CognitiveCodeAnalysis\Business\DirectoryScanner; use PHPUnit\Framework\TestCase; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; diff --git a/tests/Unit/Business/Halstead/Exporter/CsvExporterTest.php b/tests/Unit/Business/Halstead/Exporter/CsvExporterTest.php deleted file mode 100644 index d06c9d7..0000000 --- a/tests/Unit/Business/Halstead/Exporter/CsvExporterTest.php +++ /dev/null @@ -1,83 +0,0 @@ - 1, - 'n2' => 2, - 'N1' => 10, - 'N2' => 20, - 'class' => 'SomeClass', - 'file' => 'SomeFile.php' - ]); - - // Create a HalsteadMetricsCollection and add the metrics object - $metricsCollection = new HalsteadMetricsCollection(); - $metricsCollection->add($metrics); - - // Create a temporary file for testing - $filename = tempnam(sys_get_temp_dir(), 'csv_export_') . '.csv'; - - // Instantiate the CsvExporter and export the metrics collection to the file - $csvExporter = new CsvExporter(); - $csvExporter->export($metricsCollection, $filename); - - // Assert that the file was created and has the expected content - $this->assertFileExists($filename); - - $expectedContent = <<assertEquals($expectedContent, file_get_contents($filename)); - - // Cleanup - unlink($filename); - } - - public function testExportToFileWithNonExistentDirectory(): void - { - // Expect a RuntimeException when exporting to a non-existent directory - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Directory /nonexistent does not exist'); - - // Create an empty HalsteadMetricsCollection - $metricsCollection = new HalsteadMetricsCollection(); - - // Attempt to export to a non-existent directory - $csvExporter = new CsvExporter(); - $csvExporter->export($metricsCollection, '/nonexistent/invalid.csv'); - } - - public function testExportThrowsExceptionWhenFileIsNotWriteable(): void - { - // Expect a RuntimeException when file cannot be opened for writing - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Directory / is not writable'); - - // Create an empty HalsteadMetricsCollection - $metricsCollection = new HalsteadMetricsCollection(); - - // Attempt to export to an unwritable file - $csvExporter = new CsvExporter(); - $csvExporter->export($metricsCollection, '/does-not-exist'); - } -} diff --git a/tests/Unit/Business/Halstead/HalsteadMetricsCollectionTest.php b/tests/Unit/Business/Halstead/HalsteadMetricsCollectionTest.php deleted file mode 100644 index c329d01..0000000 --- a/tests/Unit/Business/Halstead/HalsteadMetricsCollectionTest.php +++ /dev/null @@ -1,124 +0,0 @@ - 5, - 'n2' => 3, - 'N1' => 10, - 'N2' => 7, - ]); - - $this->assertCount(0, $collection); - - $collection->add($metric); - - $this->assertCount(1, $collection); - } - - public function testGetIterator(): void - { - $collection = new HalsteadMetricsCollection(); - $metric1 = new HalsteadMetrics([ - 'n1' => 5, - 'n2' => 3, - 'N1' => 10, - 'N2' => 7, - ]); - $metric2 = new HalsteadMetrics([ - 'n1' => 6, - 'n2' => 4, - 'N1' => 12, - 'N2' => 8, - ]); - - $collection->add($metric1); - $collection->add($metric2); - - $iterator = $collection->getIterator(); - - $this->assertInstanceOf(\ArrayIterator::class, $iterator); - $this->assertCount(2, $iterator); - $this->assertSame($metric1, $iterator[0]); - $this->assertSame($metric2, $iterator[1]); - } - - public function testFilter(): void - { - $collection = new HalsteadMetricsCollection(); - $metric1 = new HalsteadMetrics([ - 'n1' => 5, - 'n2' => 3, - 'N1' => 10, - 'N2' => 7, - ]); - $metric2 = new HalsteadMetrics([ - 'n1' => 10, - 'n2' => 5, - 'N1' => 20, - 'N2' => 15, - ]); - - $collection->add($metric1); - $collection->add($metric2); - - $filteredCollection = $collection->filter(fn(HalsteadMetrics $m) => $m->getN1() > 5); - - $this->assertCount(1, $filteredCollection); - $this->assertTrue($filteredCollection->contains($metric2)); - $this->assertFalse($filteredCollection->contains($metric1)); - } - - public function testContains(): void - { - $collection = new HalsteadMetricsCollection(); - $metric = new HalsteadMetrics([ - 'n1' => 5, - 'n2' => 3, - 'N1' => 10, - 'N2' => 7, - ]); - - $collection->add($metric); - - $this->assertTrue($collection->contains($metric)); - } - - public function testJsonSerialize(): void - { - $collection = new HalsteadMetricsCollection(); - $metric1 = new HalsteadMetrics([ - 'n1' => 5, - 'n2' => 3, - 'N1' => 10, - 'N2' => 7, - ]); - $metric2 = new HalsteadMetrics([ - 'n1' => 6, - 'n2' => 4, - 'N1' => 12, - 'N2' => 8, - ]); - - $collection->add($metric1); - $collection->add($metric2); - - $expectedJson = json_encode([$metric1, $metric2]); - - $this->assertJsonStringEqualsJsonString($expectedJson, json_encode($collection)); - } -} diff --git a/tests/Unit/Business/Halstead/HalsteadMetricsCollectorTest.php b/tests/Unit/Business/Halstead/HalsteadMetricsCollectorTest.php deleted file mode 100644 index c85b7ec..0000000 --- a/tests/Unit/Business/Halstead/HalsteadMetricsCollectorTest.php +++ /dev/null @@ -1,29 +0,0 @@ -collect('./tests/TestCode'); - - $this->assertCount(4, $collection); - } -} diff --git a/tests/Unit/Business/Halstead/HalsteadMetricsTest.php b/tests/Unit/Business/Halstead/HalsteadMetricsTest.php deleted file mode 100644 index 997410c..0000000 --- a/tests/Unit/Business/Halstead/HalsteadMetricsTest.php +++ /dev/null @@ -1,156 +0,0 @@ - 10, - 'n2' => 20, - 'N1' => 30, - 'N2' => 40, - 'class' => 'Test\ClassName', - 'file' => '/path/to/file.php' - ]; - - $halsteadMetrics = new HalsteadMetrics($metrics); - - $this->assertSame(10, $halsteadMetrics->getN1()); - $this->assertSame(20, $halsteadMetrics->getN2()); - $this->assertSame(30, $halsteadMetrics->getTotalOperators()); - $this->assertSame(40, $halsteadMetrics->getTotalOperands()); - $this->assertSame(70, $halsteadMetrics->getProgramLength()); - $this->assertSame(30, $halsteadMetrics->getProgramVocabulary()); - $this->assertEquals(70 * log(30, 2), $halsteadMetrics->getVolume()); - $this->assertEquals((10 / 2) * (40 / 20), $halsteadMetrics->getDifficulty()); - $this->assertEquals($halsteadMetrics->getDifficulty() * $halsteadMetrics->getVolume(), $halsteadMetrics->getEffort()); - $this->assertSame('Test\ClassName', $halsteadMetrics->getClass()); - $this->assertSame('/path/to/file.php', $halsteadMetrics->getFile()); - } - - public function testConstructorThrowsExceptionForMissingKey(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Missing required key: n1'); - - $metrics = [ - 'n2' => 20, - 'N1' => 30, - 'N2' => 40, - ]; - - new HalsteadMetrics($metrics); // This should throw an exception - } - - public function testToArrayMethod(): void - { - $metrics = [ - 'n1' => 5, - 'n2' => 15, - 'N1' => 25, - 'N2' => 35, - 'class' => 'Another\ClassName', - 'file' => '/another/path/to/file.php' - ]; - - $halsteadMetrics = new HalsteadMetrics($metrics); - - $expectedArray = [ - 'n1' => 5, - 'n2' => 15, - 'N1' => 25, - 'N2' => 35, - 'program_length' => 60, - 'program_vocabulary' => 20, - 'volume' => 60 * log(20, 2), - 'difficulty' => (5 / 2) * (35 / 15), - 'effort' => ((5 / 2) * (35 / 15)) * (60 * log(20, 2)), - 'class' => 'Another\ClassName', - 'file' => '/another/path/to/file.php', - 'possible_bugs' => 0.08643856189774725 - ]; - - $this->assertEquals($expectedArray, $halsteadMetrics->toArray()); - } - - public function testJsonSerializeMethod(): void - { - $metrics = [ - 'n1' => 7, - 'n2' => 14, - 'N1' => 21, - 'N2' => 28, - 'class' => 'Sample\Class', - 'file' => '/sample/path.php' - ]; - - $halsteadMetrics = new HalsteadMetrics($metrics); - - $expectedJson = json_encode([ - 'n1' => 7, - 'n2' => 14, - 'N1' => 21, - 'N2' => 28, - 'possible_bugs' => 0.07174118457205308, - 'program_length' => 49, - 'program_vocabulary' => 21, - 'volume' => 49 * log(21, 2), - 'difficulty' => (7 / 2) * (28 / 14), - 'effort' => ((7 / 2) * (28 / 14)) * (49 * log(21, 2)), - 'class' => 'Sample\Class', - 'file' => '/sample/path.php' - ], JSON_THROW_ON_ERROR); - - $this->assertJsonStringEqualsJsonString($expectedJson, json_encode($halsteadMetrics)); - } - - public function testEqualsMethod(): void - { - $metrics1 = [ - 'n1' => 3, - 'n2' => 6, - 'N1' => 9, - 'N2' => 12, - 'class' => 'TestClass', - 'file' => '/test/file.php' - ]; - - $metrics2 = [ - 'n1' => 3, - 'n2' => 6, - 'N1' => 9, - 'N2' => 12, - 'class' => 'TestClass', - 'file' => '/test/file.php' - ]; - - $halsteadMetrics1 = new HalsteadMetrics($metrics1); - $halsteadMetrics2 = new HalsteadMetrics($metrics2); - - $this->assertTrue($halsteadMetrics1->equals($halsteadMetrics2)); - - $metrics3 = [ - 'n1' => 5, - 'n2' => 10, - 'N1' => 15, - 'N2' => 20, - 'class' => 'DifferentClass', - 'file' => '/different/file.php' - ]; - - $halsteadMetrics3 = new HalsteadMetrics($metrics3); - - $this->assertFalse($halsteadMetrics1->equals($halsteadMetrics3)); - } -} diff --git a/tests/Unit/Business/MetricsFacadeTest.php b/tests/Unit/Business/MetricsFacadeTest.php index 4807826..8dab5f9 100644 --- a/tests/Unit/Business/MetricsFacadeTest.php +++ b/tests/Unit/Business/MetricsFacadeTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Business; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Business; -use Phauthentic\CodeQualityMetrics\Application; +use Phauthentic\CognitiveCodeAnalysis\Application; use PHPUnit\Framework\TestCase; -use Phauthentic\CodeQualityMetrics\Business\MetricsFacade; +use Phauthentic\CognitiveCodeAnalysis\Business\MetricsFacade; use Symfony\Component\Yaml\Exception\ParseException; /** @@ -24,14 +24,6 @@ public function setUp(): void $this->metricsFacade = (new Application())->get(MetricsFacade::class); } - public function testGetHalsteadMetrics(): void - { - $halsteadMetrics = $this->metricsFacade->getHalsteadMetrics($this->testCodePath); - - $this->assertNotEmpty($halsteadMetrics); - $this->assertCount(4, $halsteadMetrics); - } - public function testGetCognitiveMetrics(): void { $cognitiveMetrics = $this->metricsFacade->getCognitiveMetrics($this->testCodePath); diff --git a/tests/Unit/Config/ConfigLoaderTest.php b/tests/Unit/Config/ConfigLoaderTest.php index 9e163d2..43bdab5 100644 --- a/tests/Unit/Config/ConfigLoaderTest.php +++ b/tests/Unit/Config/ConfigLoaderTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\Config; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\Config; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Processor; -use Phauthentic\CodeQualityMetrics\Config\ConfigLoader; +use Phauthentic\CognitiveCodeAnalysis\Config\ConfigLoader; /** * Class ConfigLoaderTest diff --git a/tests/Unit/PhpParser/CognitiveMetricsVisitorTest.php b/tests/Unit/PhpParser/CognitiveMetricsVisitorTest.php index 2d7c311..9c6fa07 100644 --- a/tests/Unit/PhpParser/CognitiveMetricsVisitorTest.php +++ b/tests/Unit/PhpParser/CognitiveMetricsVisitorTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Phauthentic\CodeQualityMetrics\Tests\Unit\PhpParser; +namespace Phauthentic\CognitiveCodeAnalysis\Tests\Unit\PhpParser; use PhpParser\ParserFactory; use PhpParser\NodeTraverser; -use Phauthentic\CodeQualityMetrics\PhpParser\CognitiveMetricsVisitor; +use Phauthentic\CognitiveCodeAnalysis\PhpParser\CognitiveMetricsVisitor; use PHPUnit\Framework\TestCase; /**