Skip to content

Commit 5f5a1ef

Browse files
committed
misc
1 parent a9e6f5b commit 5f5a1ef

File tree

9 files changed

+120
-59
lines changed

9 files changed

+120
-59
lines changed

src/Analyzer/UnusedDefinitionsAnalyzer.php

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
namespace Behastan\Analyzer;
66

77
use Behastan\DefinitionMasksResolver;
8+
use Behastan\Reporting\MaskCollectionStatsPrinter;
89
use Behastan\UsedInstructionResolver;
910
use Behastan\ValueObject\Mask\AbstractMask;
1011
use Behastan\ValueObject\Mask\ExactMask;
1112
use Behastan\ValueObject\Mask\NamedMask;
1213
use Behastan\ValueObject\Mask\RegexMask;
1314
use Behastan\ValueObject\Mask\SkippedMask;
14-
use Behastan\ValueObject\MaskCollection;
1515
use Nette\Utils\Strings;
1616
use Symfony\Component\Console\Style\SymfonyStyle;
1717
use Symfony\Component\Finder\SplFileInfo;
@@ -21,7 +21,8 @@
2121
public function __construct(
2222
private SymfonyStyle $symfonyStyle,
2323
private DefinitionMasksResolver $definitionMasksResolver,
24-
private UsedInstructionResolver $usedInstructionResolver
24+
private UsedInstructionResolver $usedInstructionResolver,
25+
private MaskCollectionStatsPrinter $maskCollectionStatsPrinter,
2526
) {
2627
}
2728

@@ -34,7 +35,7 @@ public function __construct(
3435
public function analyse(array $contextFiles, array $featureFiles): array
3536
{
3637
$maskCollection = $this->definitionMasksResolver->resolve($contextFiles);
37-
$this->printStats($maskCollection);
38+
$this->maskCollectionStatsPrinter->printStats($maskCollection);
3839

3940
$featureInstructions = $this->usedInstructionResolver->resolveInstructionsFromFeatureFiles($featureFiles);
4041

@@ -56,28 +57,6 @@ public function analyse(array $contextFiles, array $featureFiles): array
5657
return $unusedMasks;
5758
}
5859

59-
private function printStats(MaskCollection $maskCollection): void
60-
{
61-
$this->symfonyStyle->writeln(sprintf('Found %d masks:', $maskCollection->count()));
62-
$this->symfonyStyle->newLine();
63-
64-
$this->symfonyStyle->writeln(sprintf(' * %d exact', $maskCollection->countByType(ExactMask::class)));
65-
$this->symfonyStyle->writeln(sprintf(' * %d /regex/', $maskCollection->countByType(RegexMask::class)));
66-
$this->symfonyStyle->writeln(sprintf(' * %d :named', $maskCollection->countByType(NamedMask::class)));
67-
$this->symfonyStyle->writeln(sprintf(' * %d skipped', $maskCollection->countByType(SkippedMask::class)));
68-
69-
$skippedMasks = $maskCollection->byType(SkippedMask::class);
70-
if ($skippedMasks !== []) {
71-
$this->symfonyStyle->newLine();
72-
73-
foreach ($skippedMasks as $skippedMask) {
74-
$this->printMask($skippedMask);
75-
}
76-
77-
$this->symfonyStyle->newLine();
78-
}
79-
}
80-
8160
/**
8261
* @param string[] $featureInstructions
8362
*/
@@ -93,16 +72,6 @@ private function isRegexDefinitionUsed(string $regexBehatDefinition, array $feat
9372
return false;
9473
}
9574

96-
private function printMask(AbstractMask $unusedMask): void
97-
{
98-
$this->symfonyStyle->writeln($unusedMask->mask);
99-
100-
// make path relative
101-
$relativeFilePath = str_replace(getcwd() . '/', '', $unusedMask->filePath);
102-
$this->symfonyStyle->writeln($relativeFilePath);
103-
$this->symfonyStyle->newLine();
104-
}
105-
10675
/**
10776
* @param string[] $featureInstructions
10877
*/

src/Command/DuplicatedDefinitionsCommand.php

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Behastan\Command;
66

77
use Behastan\Analyzer\ClassMethodContextDefinitionsAnalyzer;
8+
use Behastan\Enum\Option;
89
use Behastan\Finder\BehatMetafilesFinder;
910
use Behastan\ValueObject\ClassMethodContextDefinition;
1011
use Symfony\Component\Console\Command\Command;
@@ -31,16 +32,19 @@ protected function configure(): void
3132
'Find duplicated definitions in *Context.php, use just one to keep definitions clear and to the point'
3233
);
3334

34-
$this->addArgument('test-directory', InputArgument::REQUIRED, 'Director with *.Context.php definition files');
35+
$this->addArgument(
36+
Option::TEST_DIRECTORY,
37+
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
38+
'Director with *.Context.php definition files'
39+
);
3540
}
3641

3742
protected function execute(InputInterface $input, OutputInterface $output): int
3843
{
39-
$testDirectory = (string) $input->getArgument('test-directory');
40-
Assert::directory($testDirectory);
41-
42-
$contextFileInfos = BehatMetafilesFinder::findContextFiles([$testDirectory]);
44+
$testDirectories = (array) $input->getArgument(Option::TEST_DIRECTORY);
45+
Assert::allDirectory($testDirectories);
4346

47+
$contextFileInfos = BehatMetafilesFinder::findContextFiles($testDirectories);
4448
if ($contextFileInfos === []) {
4549
$this->symfonyStyle->error('No *.Context files found. Please provide correct test directory');
4650
return self::FAILURE;
@@ -60,7 +64,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6064

6165
foreach ($classAndMethods as $classMethodContextDefinition) {
6266
/** @var ClassMethodContextDefinition $classMethodContextDefinition */
63-
$relativeFilePath = substr($classMethodContextDefinition->getFilePath(), strlen($testDirectory) + 1);
67+
$relativeFilePath = substr(
68+
$classMethodContextDefinition->getFilePath(),
69+
strlen($testDirectories[0]) + 1
70+
);
6471

6572
$this->symfonyStyle->writeln(
6673
$relativeFilePath . ':' . $classMethodContextDefinition->getMethodLine()
@@ -74,7 +81,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7481
}
7582

7683
$this->symfonyStyle->error(
77-
sprintf('Found %d duplicated class classMethod contents', count(
84+
sprintf('Found %d duplicated class method contents', count(
7885
$classMethodContextDefinitionByClassMethodHash
7986
))
8087
);

src/Command/StatsCommand.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5757
$this->symfonyStyle->title('Usage stats for PHP definitions in *Feature files');
5858

5959
$featureInstructions = $this->usedInstructionResolver->resolveInstructionsFromFeatureFiles($featureFiles);
60-
6160
$classMethodContextDefinitions = $this->classMethodContextDefinitionsAnalyzer->resolve($contextFiles);
6261

6362
foreach ($classMethodContextDefinitions as $i => $classMethodContextDefinition) {
6463
$section = sprintf('%d) %s', $i + 1, $classMethodContextDefinition->getMask());
6564
$this->symfonyStyle->section($section);
66-
$this->symfonyStyle->newLine();
67-
}
6865

69-
dump(123);
70-
die;
66+
$classMethodContextDefinition->recordUsage($featureInstructions);
67+
68+
$this->symfonyStyle->writeln(' * ' . $classMethodContextDefinition->getUsageCount() . ' usages');
69+
$this->symfonyStyle->newLine(2);
70+
}
7171

7272
return Command::SUCCESS;
7373
}

src/Command/UnusedDefinitionsCommand.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Behastan\Command;
66

77
use Behastan\Analyzer\UnusedDefinitionsAnalyzer;
8+
use Behastan\Enum\Option;
89
use Behastan\Finder\BehatMetafilesFinder;
910
use Behastan\ValueObject\Mask\AbstractMask;
1011
use Symfony\Component\Console\Command\Command;
@@ -30,15 +31,15 @@ protected function configure(): void
3031
$this->setDescription('Checks Behat definitions in *Context.php files and feature files to spot unused ones');
3132

3233
$this->addArgument(
33-
'test-directory',
34+
Option::TEST_DIRECTORY,
3435
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
3536
'One or more paths to check or *.Context.php and feature.yml files'
3637
);
3738
}
3839

3940
protected function execute(InputInterface $input, OutputInterface $output): int
4041
{
41-
$testDirectories = (array) $input->getArgument('test-directory');
42+
$testDirectories = (array) $input->getArgument(Option::TEST_DIRECTORY);
4243
Assert::allDirectory($testDirectories);
4344

4445
$featureFiles = BehatMetafilesFinder::findFeatureFiles($testDirectories);

src/Enum/Option.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Behastan\Enum;
6+
7+
final class Option
8+
{
9+
/**
10+
* @var string
11+
*/
12+
public const TEST_DIRECTORY = 'test-directory';
13+
}

src/Finder/BehatMetafilesFinder.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ public static function findContextFiles(array $directories): array
2929

3030
/**
3131
* @param string[] $directories
32-
*
3332
* @return SplFileInfo[]
3433
*/
3534
public static function findFeatureFiles(array $directories): array
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Behastan\Reporting;
6+
7+
use Behastan\ValueObject\Mask\AbstractMask;
8+
use Behastan\ValueObject\Mask\ExactMask;
9+
use Behastan\ValueObject\Mask\NamedMask;
10+
use Behastan\ValueObject\Mask\RegexMask;
11+
use Behastan\ValueObject\Mask\SkippedMask;
12+
use Behastan\ValueObject\MaskCollection;
13+
use Symfony\Component\Console\Style\SymfonyStyle;
14+
15+
final readonly class MaskCollectionStatsPrinter
16+
{
17+
public function __construct(
18+
private SymfonyStyle $symfonyStyle
19+
) {
20+
}
21+
22+
public function printStats(MaskCollection $maskCollection): void
23+
{
24+
$this->symfonyStyle->writeln(sprintf('Found %d masks:', $maskCollection->count()));
25+
$this->symfonyStyle->newLine();
26+
27+
$this->symfonyStyle->writeln(sprintf(' * %d exact', $maskCollection->countByType(ExactMask::class)));
28+
$this->symfonyStyle->writeln(sprintf(' * %d /regex/', $maskCollection->countByType(RegexMask::class)));
29+
$this->symfonyStyle->writeln(sprintf(' * %d :named', $maskCollection->countByType(NamedMask::class)));
30+
$this->symfonyStyle->writeln(sprintf(' * %d skipped', $maskCollection->countByType(SkippedMask::class)));
31+
32+
$skippedMasks = $maskCollection->byType(SkippedMask::class);
33+
if ($skippedMasks !== []) {
34+
$this->symfonyStyle->newLine();
35+
36+
foreach ($skippedMasks as $skippedMask) {
37+
$this->printMask($skippedMask);
38+
}
39+
40+
$this->symfonyStyle->newLine();
41+
}
42+
}
43+
44+
private function printMask(AbstractMask $unusedMask): void
45+
{
46+
$this->symfonyStyle->writeln($unusedMask->mask);
47+
48+
// make path relative
49+
$relativeFilePath = str_replace(getcwd() . '/', '', $unusedMask->filePath);
50+
$this->symfonyStyle->writeln($relativeFilePath);
51+
$this->symfonyStyle->newLine();
52+
}
53+
}

src/UsedInstructionResolver.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use Nette\Utils\Strings;
88
use RuntimeException;
99
use Symfony\Component\Finder\SplFileInfo;
10-
use Webmozart\Assert\Assert;
1110

1211
final class UsedInstructionResolver
1312
{
@@ -17,8 +16,6 @@ final class UsedInstructionResolver
1716
*/
1817
public function resolveInstructionsFromFeatureFiles(array $featureFileInfos): array
1918
{
20-
Assert::allIsInstanceOf($featureFileInfos, SplFileInfo::class);
21-
2219
$instructions = [];
2320

2421
foreach ($featureFileInfos as $featureFileInfo) {

src/ValueObject/ClassMethodContextDefinition.php

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44

55
namespace Behastan\ValueObject;
66

7-
final readonly class ClassMethodContextDefinition
7+
final class ClassMethodContextDefinition
88
{
9+
private int $usageCount = 0;
10+
911
public function __construct(
10-
private string $filePath,
11-
private string $class,
12-
private string $methodName,
13-
private string $mask,
14-
private ?int $methodLine = null
12+
private readonly string $filePath,
13+
private readonly string $class,
14+
private readonly string $methodName,
15+
private readonly string $mask,
16+
private readonly ?int $methodLine = null
1517
) {
1618
}
1719

@@ -39,4 +41,24 @@ public function getMethodLine(): ?int
3941
{
4042
return $this->methodLine;
4143
}
44+
45+
/**
46+
* @param string[] $featureInstructions
47+
*/
48+
public function recordUsage(array $featureInstructions): void
49+
{
50+
$usageCount = 0;
51+
foreach ($featureInstructions as $featureInstruction) {
52+
if ($this->mask === $featureInstruction) {
53+
++$usageCount;
54+
}
55+
}
56+
57+
$this->usageCount = $usageCount;
58+
}
59+
60+
public function getUsageCount(): int
61+
{
62+
return $this->usageCount;
63+
}
4264
}

0 commit comments

Comments
 (0)