Skip to content

Commit 142db51

Browse files
committed
mics
1 parent 4fd9621 commit 142db51

File tree

4 files changed

+101
-60
lines changed

4 files changed

+101
-60
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Behastan\Analyzer;
6+
7+
use Behastan\PhpParser\SimplePhpParser;
8+
use Behastan\Resolver\ClassMethodMasksResolver;
9+
use Behastan\ValueObject\ClassMethodContextDefinition;
10+
use PhpParser\Node\Name;
11+
use PhpParser\Node\Stmt\Class_;
12+
use PhpParser\Node\Stmt\ClassMethod;
13+
use PhpParser\NodeFinder;
14+
use PhpParser\PrettyPrinter\Standard;
15+
use Symfony\Component\Finder\SplFileInfo;
16+
17+
final readonly class ClassMethodContextDefinitionsAnalyzer
18+
{
19+
public function __construct(
20+
private SimplePhpParser $simplePhpParser,
21+
private NodeFinder $nodeFinder,
22+
private Standard $printerStandard,
23+
private ClassMethodMasksResolver $classMethodMasksResolver,
24+
) {
25+
}
26+
27+
/**
28+
* @param SplFileInfo[] $contextFileInfos
29+
* @return array<string, ClassMethodContextDefinition[]>
30+
*/
31+
public function analyseContextFiles(array $contextFileInfos): array
32+
{
33+
$classMethodContextDefinitionByClassMethodHash = [];
34+
35+
foreach ($contextFileInfos as $contextFileInfo) {
36+
$contextClassStmts = $this->simplePhpParser->parseFilePath($contextFileInfo->getRealPath());
37+
38+
$class = $this->nodeFinder->findFirstInstanceOf($contextClassStmts, Class_::class);
39+
if (! $class instanceof Class_ || ! $class->namespacedName instanceof Name) {
40+
continue;
41+
}
42+
43+
$className = $class->namespacedName->toString();
44+
45+
foreach ($class->getMethods() as $classMethod) {
46+
if (! $classMethod->isPublic() || $classMethod->isMagic()) {
47+
continue;
48+
}
49+
50+
$classMethodHash = $this->createClassMethodHash($classMethod);
51+
52+
$rawMasks = $this->classMethodMasksResolver->resolve($classMethod);
53+
54+
// no masks :(
55+
if (count($rawMasks) === 0) {
56+
continue;
57+
}
58+
59+
$classMethodContextDefinition = new ClassMethodContextDefinition(
60+
$contextFileInfo->getRealPath(),
61+
$className,
62+
$classMethod->name->toString(),
63+
// @todo what about multiple masks?
64+
$rawMasks[0],
65+
$classMethod->getStartLine()
66+
);
67+
68+
$classMethodContextDefinitionByClassMethodHash[$classMethodHash][] = $classMethodContextDefinition;
69+
}
70+
}
71+
72+
return $classMethodContextDefinitionByClassMethodHash;
73+
}
74+
75+
private function createClassMethodHash(ClassMethod $classMethod): string
76+
{
77+
$printedClassMethod = $this->printerStandard->prettyPrint((array) $classMethod->stmts);
78+
return sha1($printedClassMethod);
79+
}
80+
}

src/Command/DuplicatedDefinitionsCommand.php

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,9 @@
44

55
namespace Behastan\Command;
66

7+
use Behastan\Analyzer\ClassMethodContextDefinitionsAnalyzer;
78
use Behastan\Finder\BehatMetafilesFinder;
8-
use Behastan\PhpParser\SimplePhpParser;
9-
use Behastan\Resolver\ClassMethodMasksResolver;
109
use Behastan\ValueObject\ClassMethodContextDefinition;
11-
use PhpParser\Node\Name;
12-
use PhpParser\Node\Stmt\Class_;
13-
use PhpParser\Node\Stmt\ClassMethod;
14-
use PhpParser\NodeFinder;
15-
use PhpParser\PrettyPrinter\Standard;
1610
use Symfony\Component\Console\Command\Command;
1711
use Symfony\Component\Console\Input\InputArgument;
1812
use Symfony\Component\Console\Input\InputInterface;
@@ -25,10 +19,7 @@ final class DuplicatedDefinitionsCommand extends Command
2519
public function __construct(
2620
private readonly SymfonyStyle $symfonyStyle,
2721
private readonly BehatMetafilesFinder $behatMetafilesFinder,
28-
private readonly SimplePhpParser $simplePhpParser,
29-
private readonly NodeFinder $nodeFinder,
30-
private readonly Standard $printerStandard,
31-
private readonly ClassMethodMasksResolver $classMethodMasksResolver,
22+
private readonly ClassMethodContextDefinitionsAnalyzer $classMethodContextDefinitionsAnalyzer,
3223
) {
3324
parent::__construct();
3425
}
@@ -56,44 +47,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5647
return self::FAILURE;
5748
}
5849

59-
$classMethodContextDefinitionByClassMethodHash = [];
60-
61-
foreach ($contextFileInfos as $contextFileInfo) {
62-
$contextClassStmts = $this->simplePhpParser->parseFilePath($contextFileInfo->getRealPath());
63-
64-
$class = $this->nodeFinder->findFirstInstanceOf($contextClassStmts, Class_::class);
65-
if (! $class instanceof Class_ || ! $class->namespacedName instanceof Name) {
66-
continue;
67-
}
68-
69-
$className = $class->namespacedName->toString();
70-
71-
foreach ($class->getMethods() as $classMethod) {
72-
if (! $classMethod->isPublic() || $classMethod->isMagic()) {
73-
continue;
74-
}
75-
76-
$classMethodHash = $this->createClassMethodHash($classMethod);
77-
78-
$rawMasks = $this->classMethodMasksResolver->resolve($classMethod);
79-
80-
// no masks :(
81-
if (count($rawMasks) === 0) {
82-
continue;
83-
}
84-
85-
$classMethodContextDefinition = new ClassMethodContextDefinition(
86-
$contextFileInfo->getRealPath(),
87-
$className,
88-
$classMethod->name->toString(),
89-
// @todo what about multiple masks?
90-
$rawMasks[0],
91-
$classMethod->getStartLine()
92-
);
93-
94-
$classMethodContextDefinitionByClassMethodHash[$classMethodHash][] = $classMethodContextDefinition;
95-
}
96-
}
50+
$classMethodContextDefinitionByClassMethodHash = $this->classMethodContextDefinitionsAnalyzer->analyseContextFiles(
51+
$contextFileInfos
52+
);
9753

9854
// keep only duplicated
9955
$classMethodContextDefinitionByClassMethodHash = $this->filterOutNotDuplicated(
@@ -127,12 +83,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int
12783
return Command::FAILURE;
12884
}
12985

130-
private function createClassMethodHash(ClassMethod $classMethod): string
131-
{
132-
$printedClassMethod = $this->printerStandard->prettyPrint((array) $classMethod->stmts);
133-
return sha1($printedClassMethod);
134-
}
135-
13686
/**
13787
* @template TItem as object
13888
*
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,30 @@
44

55
namespace Behastan\Command;
66

7-
use Behastan\Analyzer\UnusedDefinitionsAnalyzer;
7+
use Behastan\DefinitionMasksResolver;
88
use Behastan\Finder\BehatMetafilesFinder;
9+
use Behastan\UsedInstructionResolver;
910
use Symfony\Component\Console\Command\Command;
1011
use Symfony\Component\Console\Input\InputArgument;
1112
use Symfony\Component\Console\Input\InputInterface;
1213
use Symfony\Component\Console\Output\OutputInterface;
1314
use Symfony\Component\Console\Style\SymfonyStyle;
1415
use Webmozart\Assert\Assert;
1516

16-
final class DefinitionStatsCommand extends Command
17+
final class StatsCommand extends Command
1718
{
1819
public function __construct(
1920
private readonly SymfonyStyle $symfonyStyle,
2021
private readonly BehatMetafilesFinder $behatMetafilesFinder,
21-
private readonly UnusedDefinitionsAnalyzer $unusedDefinitionsAnalyzer,
22+
private readonly DefinitionMasksResolver $definitionMasksResolver,
23+
private readonly UsedInstructionResolver $usedInstructionResolver,
2224
) {
2325
parent::__construct();
2426
}
2527

2628
protected function configure(): void
2729
{
28-
$this->setName('definitions-stats');
30+
$this->setName('stats');
2931

3032
$this->setDescription('Get Definition usage stats');
3133

@@ -55,7 +57,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5557

5658
$this->symfonyStyle->title('Usage stats for PHP definitions in *Feature files');
5759

60+
$maskCollection = $this->definitionMasksResolver->resolve($contextFiles);
61+
$featureInstructions = $this->usedInstructionResolver->resolveInstructionsFromFeatureFiles($featureFiles);
5862

63+
dump(123);
64+
die;
5965

6066
return Command::SUCCESS;
6167
}

src/DependencyInjection/ContainerFactory.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Behastan\DependencyInjection;
66

77
use Behastan\Command\DuplicatedDefinitionsCommand;
8+
use Behastan\Command\StatsCommand;
89
use Behastan\Command\UnusedDefinitionsCommand;
910
use Illuminate\Container\Container;
1011
use PhpParser\Parser;
@@ -28,7 +29,11 @@ public function create(): Container
2829
$application = new Application('Behastan');
2930

3031
// register commands
31-
foreach ([DuplicatedDefinitionsCommand::class, UnusedDefinitionsCommand::class] as $commandClass) {
32+
foreach ([
33+
DuplicatedDefinitionsCommand::class,
34+
UnusedDefinitionsCommand::class,
35+
StatsCommand::class,
36+
] as $commandClass) {
3237
$command = $container->make($commandClass);
3338
$application->add($command);
3439
}

0 commit comments

Comments
 (0)