Skip to content

Commit d2ccf95

Browse files
Merge pull request #86 from andreaswolf/issue-81
[TASK] Generalize rule filtering for a processor
2 parents 123395b + d44c3d3 commit d2ccf95

File tree

16 files changed

+100
-209
lines changed

16 files changed

+100
-209
lines changed

packages/fractor-composer-json/src/ComposerJsonFileProcessor.php

+10-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
use a9f\FractorComposerJson\Contract\ComposerJsonFractorRule;
1212
use a9f\FractorComposerJson\Contract\ComposerJsonPrinter;
1313

14+
/**
15+
* @implements FileProcessor<ComposerJsonFractorRule>
16+
*/
1417
final readonly class ComposerJsonFileProcessor implements FileProcessor
1518
{
1619
/**
@@ -23,13 +26,13 @@ public function __construct(
2326
) {
2427
}
2528

26-
public function handle(File $file): void
29+
public function handle(File $file, iterable $appliedRules): void
2730
{
2831
$composerJson = $this->composerJsonFactory->createFromFile($file);
2932
$oldComposerJson = $this->composerJsonFactory->createFromFile($file);
3033
$ident = Indent::fromFile($file);
3134

32-
foreach ($this->rules as $rule) {
35+
foreach ($appliedRules as $rule) {
3336
$rule->refactor($composerJson);
3437

3538
if ($oldComposerJson->getJsonArray() !== $composerJson->getJsonArray()) {
@@ -48,4 +51,9 @@ public function allowedFileExtensions(): array
4851
{
4952
return ['json'];
5053
}
54+
55+
public function getAllRules(): iterable
56+
{
57+
return $this->rules;
58+
}
5159
}

packages/fractor-fluid/config/application.php

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
declare(strict_types=1);
44

5-
use a9f\Fractor\Rules\RulesProvider;
65
use a9f\FractorFluid\Contract\FluidFractorRule;
76
use a9f\FractorFluid\FluidFileProcessor;
87
use Symfony\Component\DependencyInjection\ContainerBuilder;
98
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
10-
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
119
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;
1210

1311
return static function (ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void {
@@ -18,12 +16,8 @@
1816

1917
$services->load('a9f\\FractorFluid\\', __DIR__ . '/../src/');
2018

21-
$services->set('rules_providers.fluid_rule')
22-
->class(RulesProvider::class)
23-
->arg('$baseClassOrInterface', FluidFractorRule::class)
24-
->arg('$rules', tagged_iterator('fractor.fluid_rule'));
2519
$services->set(FluidFileProcessor::class)
26-
->arg('$rulesProvider', service('rules_providers.fluid_rule'));
20+
->arg('$rules', tagged_iterator('fractor.fluid_rule'));
2721

2822
$containerBuilder->registerForAutoconfiguration(FluidFractorRule::class)->addTag('fractor.fluid_rule');
2923
};

packages/fractor-fluid/src/FluidFileProcessor.php

+12-5
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@
77
use a9f\Fractor\Application\Contract\FileProcessor;
88
use a9f\Fractor\Application\ValueObject\AppliedRule;
99
use a9f\Fractor\Application\ValueObject\File;
10-
use a9f\Fractor\Rules\RulesProvider;
1110
use a9f\FractorFluid\Contract\FluidFractorRule;
1211

12+
/**
13+
* @implements FileProcessor<FluidFractorRule>
14+
*/
1315
final readonly class FluidFileProcessor implements FileProcessor
1416
{
1517
/**
16-
* @param RulesProvider<FluidFractorRule> $rulesProvider
18+
* @param iterable<FluidFractorRule> $rules
1719
*/
1820
public function __construct(
19-
private RulesProvider $rulesProvider
21+
private iterable $rules
2022
) {
2123
}
2224

@@ -25,9 +27,9 @@ public function canHandle(File $file): bool
2527
return in_array($file->getFileExtension(), $this->allowedFileExtensions(), true);
2628
}
2729

28-
public function handle(File $file): void
30+
public function handle(File $file, iterable $appliedRules): void
2931
{
30-
foreach ($this->rulesProvider->getApplicableRules($file) as $rule) {
32+
foreach ($appliedRules as $rule) {
3133
$newContent = $rule->refactor($file->getContent());
3234

3335
if ($newContent !== $file->getContent()) {
@@ -41,4 +43,9 @@ public function allowedFileExtensions(): array
4143
{
4244
return ['html', 'xml', 'txt'];
4345
}
46+
47+
public function getAllRules(): iterable
48+
{
49+
return $this->rules;
50+
}
4451
}

packages/fractor-xml/config/application.php

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
declare(strict_types=1);
44

5-
use a9f\Fractor\Rules\RulesProvider;
65
use a9f\FractorXml\Contract\XmlFractor;
76
use a9f\FractorXml\XmlFileProcessor;
87
use Symfony\Component\DependencyInjection\ContainerBuilder;
98
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
10-
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
119
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;
1210

1311
return static function (ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void {
@@ -18,12 +16,8 @@
1816

1917
$services->load('a9f\\FractorXml\\', __DIR__ . '/../src/');
2018

21-
$services->set('rules_providers.xml_rule')
22-
->class(RulesProvider::class)
23-
->arg('$baseClassOrInterface', XmlFractor::class)
24-
->arg('$rules', tagged_iterator('fractor.xml_rule'));
2519
$services->set(XmlFileProcessor::class)
26-
->arg('$rulesProvider', service('rules_providers.xml_rule'));
20+
->arg('$rules', tagged_iterator('fractor.xml_rule'));
2721

2822
$containerBuilder->registerForAutoconfiguration(XmlFractor::class)->addTag('fractor.xml_rule');
2923
};

packages/fractor-xml/src/XmlFileProcessor.php

+12-7
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@
77
use a9f\Fractor\Application\Contract\FileProcessor;
88
use a9f\Fractor\Application\ValueObject\File;
99
use a9f\Fractor\Exception\ShouldNotHappenException;
10-
use a9f\Fractor\Rules\RulesProvider;
1110
use a9f\FractorXml\Contract\XmlFractor;
1211
use a9f\FractorXml\ValueObjectFactory\DomDocumentFactory;
1312

13+
/**
14+
* @implements FileProcessor<XmlFractor>
15+
*/
1416
final readonly class XmlFileProcessor implements FileProcessor
1517
{
1618
/**
17-
* @param RulesProvider<XmlFractor> $rulesProvider
19+
* @param iterable<XmlFractor> $rules
1820
*/
1921
public function __construct(
2022
private DomDocumentFactory $domDocumentFactory,
21-
private RulesProvider $rulesProvider
23+
private iterable $rules
2224
) {
2325
}
2426

@@ -27,7 +29,7 @@ public function canHandle(File $file): bool
2729
return $file->getFileExtension() === 'xml';
2830
}
2931

30-
public function handle(File $file): void
32+
public function handle(File $file, iterable $appliedRules): void
3133
{
3234
$document = $this->domDocumentFactory->create();
3335
$originalXml = $file->getOriginalContent();
@@ -36,9 +38,7 @@ public function handle(File $file): void
3638
// This is a hacky trick to keep format and create a nice diff later
3739
$file->changeOriginalContent($this->saveXml($document));
3840

39-
$applicableRulesForFile = $this->rulesProvider->getApplicableRules($file);
40-
41-
$iterator = new DomDocumentIterator($applicableRulesForFile);
41+
$iterator = new DomDocumentIterator($appliedRules);
4242
$iterator->traverseDocument($file, $document);
4343

4444
$newXml = $this->saveXml($document);
@@ -55,6 +55,11 @@ public function allowedFileExtensions(): array
5555
return ['xml'];
5656
}
5757

58+
public function getAllRules(): iterable
59+
{
60+
return $this->rules;
61+
}
62+
5863
private function saveXml(\DOMDocument $document): string
5964
{
6065
$xml = $document->saveXML();

packages/fractor-yaml/config/application.php

+1-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
declare(strict_types=1);
44

5-
use a9f\Fractor\Rules\RulesProvider;
65
use a9f\FractorYaml\Contract\YamlDumper;
76
use a9f\FractorYaml\Contract\YamlFractorRule;
87
use a9f\FractorYaml\Contract\YamlParser;
@@ -11,7 +10,6 @@
1110
use a9f\FractorYaml\YamlFileProcessor;
1211
use Symfony\Component\DependencyInjection\ContainerBuilder;
1312
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
14-
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
1513
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;
1614

1715
return static function (ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void {
@@ -25,12 +23,8 @@
2523
$services->alias(YamlParser::class, SymfonyYamlParser::class);
2624
$services->alias(YamlDumper::class, SymfonyYamlDumper::class);
2725

28-
$services->set('rules_providers.yaml_rule')
29-
->class(RulesProvider::class)
30-
->arg('$baseClassOrInterface', YamlFractorRule::class)
31-
->arg('$rules', tagged_iterator('fractor.yaml_rule'));
3226
$services->set(YamlFileProcessor::class)
33-
->arg('$rulesProvider', service('rules_providers.yaml_rule'));
27+
->arg('$rules', tagged_iterator('fractor.yaml_rule'));
3428

3529
$containerBuilder->registerForAutoconfiguration(YamlFractorRule::class)->addTag('fractor.yaml_rule');
3630
};

packages/fractor-yaml/src/YamlFileProcessor.php

+12-5
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,21 @@
77
use a9f\Fractor\Application\Contract\FileProcessor;
88
use a9f\Fractor\Application\ValueObject\AppliedRule;
99
use a9f\Fractor\Application\ValueObject\File;
10-
use a9f\Fractor\Rules\RulesProvider;
1110
use a9f\Fractor\ValueObject\Indent;
1211
use a9f\FractorYaml\Contract\YamlDumper;
1312
use a9f\FractorYaml\Contract\YamlFractorRule;
1413
use a9f\FractorYaml\Contract\YamlParser;
1514

15+
/**
16+
* @implements FileProcessor<YamlFractorRule>
17+
*/
1618
final readonly class YamlFileProcessor implements FileProcessor
1719
{
1820
/**
19-
* @param RulesProvider<YamlFractorRule> $rulesProvider
21+
* @param iterable<YamlFractorRule> $rules
2022
*/
2123
public function __construct(
22-
private RulesProvider $rulesProvider,
24+
private iterable $rules,
2325
private YamlParser $yamlParser,
2426
private YamlDumper $yamlDumper
2527
) {
@@ -30,14 +32,14 @@ public function canHandle(File $file): bool
3032
return in_array($file->getFileExtension(), $this->allowedFileExtensions(), true);
3133
}
3234

33-
public function handle(File $file): void
35+
public function handle(File $file, iterable $appliedRules): void
3436
{
3537
$yaml = $this->yamlParser->parse($file);
3638
$indent = Indent::fromFile($file);
3739

3840
$newYaml = $yaml;
3941

40-
foreach ($this->rulesProvider->getApplicableRules($file) as $rule) {
42+
foreach ($appliedRules as $rule) {
4143
$oldYaml = $newYaml;
4244
$newYaml = $rule->refactor($newYaml);
4345

@@ -58,4 +60,9 @@ public function allowedFileExtensions(): array
5860
{
5961
return ['yaml', 'yml'];
6062
}
63+
64+
public function getAllRules(): iterable
65+
{
66+
return $this->rules;
67+
}
6168
}

packages/fractor/config/application.php

-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use a9f\Fractor\Differ\ConsoleDiffer;
1111
use a9f\Fractor\Differ\Contract\Differ;
1212
use a9f\Fractor\FractorApplication;
13-
use a9f\Fractor\Rules\RulesProvider;
1413
use Symfony\Component\Console\Attribute\AsCommand;
1514
use Symfony\Component\DependencyInjection\ChildDefinition;
1615
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -90,8 +89,5 @@ static function (ChildDefinition $definition, AsCommand $attribute): void {
9089
$services->set(FractorRunner::class)->arg('$processors', tagged_iterator('fractor.file_processor'));
9190
$services->set(AllowedFileExtensionsResolver::class)->arg('$processors', tagged_iterator('fractor.file_processor'));
9291
$services->set(Filesystem::class);
93-
// RulesProvider must be wired individually for each processor to ensure the correct rules base class is set
94-
$services->set(RulesProvider::class)->autowire(false);
95-
9692
$containerBuilder->registerForAutoconfiguration(FileProcessor::class)->addTag('fractor.file_processor');
9793
};

packages/fractor/src/Application/Contract/FileProcessor.php

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,25 @@
66

77
use a9f\Fractor\Application\ValueObject\File;
88

9+
/**
10+
* @template T of FractorRule
11+
*/
912
interface FileProcessor
1013
{
1114
public function canHandle(File $file): bool;
1215

13-
public function handle(File $file): void;
16+
/**
17+
* @param iterable<T> $appliedRules
18+
*/
19+
public function handle(File $file, iterable $appliedRules): void;
1420

1521
/**
1622
* @return list<non-empty-string>
1723
*/
1824
public function allowedFileExtensions(): array;
25+
26+
/**
27+
* @return iterable<T>
28+
*/
29+
public function getAllRules(): iterable;
1930
}

packages/fractor/src/Application/FractorRunner.php

+22-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use a9f\Fractor\Application\Contract\FileProcessor;
88
use a9f\Fractor\Application\Contract\FileWriter;
9+
use a9f\Fractor\Application\Contract\FractorRule;
910
use a9f\Fractor\Application\ValueObject\File;
1011
use a9f\Fractor\Configuration\ValueObject\Configuration;
1112
use a9f\Fractor\Console\Contract\Output;
@@ -22,15 +23,16 @@
2223
final readonly class FractorRunner
2324
{
2425
/**
25-
* @param FileProcessor[] $processors
26+
* @param iterable<FileProcessor<FractorRule>> $processors
2627
*/
2728
public function __construct(
2829
private FractorsChangelogLinesResolver $fractorsChangelogLinesResolver,
2930
private FilesFinder $fileFinder,
3031
private FilesCollector $fileCollector,
3132
private iterable $processors,
3233
private FileWriter $fileWriter,
33-
private FileDiffFactory $fileDiffFactory
34+
private FileDiffFactory $fileDiffFactory,
35+
private RuleSkipper $ruleSkipper
3436
) {
3537
Assert::allIsInstanceOf($this->processors, FileProcessor::class);
3638
}
@@ -55,7 +57,9 @@ public function run(Output $output, Configuration $configuration): void
5557
continue;
5658
}
5759

58-
$processor->handle($file);
60+
$applicableRules = $this->filterApplicableRules($processor->getAllRules(), $file);
61+
62+
$processor->handle($file, $applicableRules);
5963
}
6064

6165
if (! $file->hasChanged()) {
@@ -93,4 +97,19 @@ public function run(Output $output, Configuration $configuration): void
9397
$this->fileWriter->write($file);
9498
}
9599
}
100+
101+
/**
102+
* @param iterable<FractorRule> $rules
103+
* @return \Generator<FractorRule>
104+
*/
105+
private function filterApplicableRules(iterable $rules, File $file): \Generator
106+
{
107+
foreach ($rules as $rule) {
108+
if ($this->ruleSkipper->shouldSkip($rule::class, $file->getFilePath())) {
109+
continue;
110+
}
111+
112+
yield $rule;
113+
}
114+
}
96115
}

packages/fractor/src/Configuration/AllowedFileExtensionsResolver.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
namespace a9f\Fractor\Configuration;
66

77
use a9f\Fractor\Application\Contract\FileProcessor;
8+
use a9f\Fractor\Application\Contract\FractorRule;
89
use Webmozart\Assert\Assert;
910

1011
final readonly class AllowedFileExtensionsResolver
1112
{
1213
/**
13-
* @param FileProcessor[] $processors
14+
* @param iterable<FileProcessor<FractorRule>> $processors
1415
*/
1516
public function __construct(
1617
private iterable $processors

0 commit comments

Comments
 (0)