diff --git a/baseline.xml b/baseline.xml index 518cf5087..97523c0c0 100644 --- a/baseline.xml +++ b/baseline.xml @@ -11,4 +11,19 @@ list<RuleInterface> + + + DependsOnDisallowedLayer + + + + + DependsOnInternalToken + + + + + DependsOnPrivateLayer + + diff --git a/config/services.php b/config/services.php index 63789bd84..568aa3523 100644 --- a/config/services.php +++ b/config/services.php @@ -6,11 +6,16 @@ use PhpParser\Parser; use PhpParser\ParserFactory; use Psr\EventDispatcher\EventDispatcherInterface; +use Qossmic\Deptrac\Contract\Analyser\EventHelper; +use Qossmic\Deptrac\Contract\Layer\LayerProvider; use Qossmic\Deptrac\Core\Analyser\DependencyLayersAnalyser; use Qossmic\Deptrac\Core\Analyser\EventHandler\AllowDependencyHandler; +use Qossmic\Deptrac\Core\Analyser\EventHandler\DependsOnDisallowedLayer; +use Qossmic\Deptrac\Core\Analyser\EventHandler\DependsOnInternalToken; +use Qossmic\Deptrac\Core\Analyser\EventHandler\DependsOnPrivateLayer; use Qossmic\Deptrac\Core\Analyser\EventHandler\MatchingLayersHandler; use Qossmic\Deptrac\Core\Analyser\EventHandler\UncoveredDependentHandler; -use Qossmic\Deptrac\Core\Analyser\EventHandler\ViolationHandler; +use Qossmic\Deptrac\Core\Analyser\EventHandler\UnmatchedSkippedViolations; use Qossmic\Deptrac\Core\Analyser\LayerForTokenAnalyser; use Qossmic\Deptrac\Core\Analyser\TokenInLayerAnalyser; use Qossmic\Deptrac\Core\Analyser\UnassignedTokenAnalyser; @@ -65,7 +70,6 @@ use Qossmic\Deptrac\Core\Layer\Collector\SuperglobalCollector; use Qossmic\Deptrac\Core\Layer\Collector\TraitCollector; use Qossmic\Deptrac\Core\Layer\Collector\UsesCollector; -use Qossmic\Deptrac\Core\Layer\LayerProvider; use Qossmic\Deptrac\Core\Layer\LayerResolver; use Qossmic\Deptrac\Core\Layer\LayerResolverInterface; use Qossmic\Deptrac\Supportive\Console\Command\AnalyseCommand; @@ -316,11 +320,21 @@ ->set(AllowDependencyHandler::class) ->tag('kernel.event_subscriber'); $services - ->set(ViolationHandler::class) + ->set(DependsOnDisallowedLayer::class) + ->tag('kernel.event_subscriber'); + $services + ->set(DependsOnPrivateLayer::class) + ->tag('kernel.event_subscriber'); + $services + ->set(DependsOnInternalToken::class) + ->tag('kernel.event_subscriber'); + $services + ->set(UnmatchedSkippedViolations::class) + ->tag('kernel.event_subscriber'); + $services->set(EventHelper::class) ->args([ '$skippedViolations' => param('skip_violations'), - ]) - ->tag('kernel.event_subscriber'); + ]); $services ->set(DependencyLayersAnalyser::class); $services->set(TokenInLayerAnalyser::class) diff --git a/docs/index.md b/docs/index.md index 61990011e..f39f794dd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -25,14 +25,14 @@ You can analyse projects that require an older PHP version as long as You can install Deptrac via Composer. We recommend using the [deptrac-shim](https://github.com/qossmic/deptrac-shim) package for this. Alternatively, you can also use [PHIVE](#phive) or download the -[PHAR](#phar) attached to each release on GitHub. +[PHAR](#phar) attached to each release on GitHub. This will ensure that Deptrac and its dependencies are bundled together and will not interfere with any of your project's dependencies. ### Composer -We strongly advise against using the deptrac package directly as a composer dependency. -We update dependencies regularly, which might cause disruptions in your project. +We strongly advise against using the deptrac package directly as a composer dependency. +We update dependencies regularly, which might cause disruptions in your project. Instead, please use the dedicated distribution repository . When you install Deptrac using the qossmic/deptrac-shim package, you will get @@ -200,12 +200,13 @@ This can be disabled with the `--no-cache` option. The generated output will roughly look like this: ```bash - ----------- -------------------------------------------------------------------------------------------------------------------------------- - Reason Repository - ----------- -------------------------------------------------------------------------------------------------------------------------------- - Violation examples\MyNamespace\Repository\SomeRepository must not depend on examples\MyNamespace\Controllers\SomeController (Controller) - /Users/dbr/workspace/qossmic/deptrac/examples/ControllerServiceRepository1/SomeRepository.php:5 - ----------- -------------------------------------------------------------------------------------------------------------------------------- + -------------------------- -------------------------------------------------------------------------------------------------------------------------------- + Reason Repository + -------------------------- -------------------------------------------------------------------------------------------------------------------------------- + DependsOnDisallowedLayer examples\MyNamespace\Repository\SomeRepository must not depend on examples\MyNamespace\Controllers\SomeController + You are depending on token that is a part of a layer that you are not allowed to depend on. (Controller) + /Users/dbr/workspace/qossmic/deptrac/examples/ControllerServiceRepository1/SomeRepository.php:5 + -------------------------- -------------------------------------------------------------------------------------------------------------------------------- -------------------- ----- diff --git a/src/Contract/Analyser/EventHelper.php b/src/Contract/Analyser/EventHelper.php new file mode 100644 index 000000000..8ec0d8bbf --- /dev/null +++ b/src/Contract/Analyser/EventHelper.php @@ -0,0 +1,61 @@ + + */ + private array $unmatchedSkippedViolation; + + /** + * @param array $skippedViolations + */ + public function __construct( + private readonly array $skippedViolations, + public readonly LayerProvider $layerProvider, + ) { + $this->unmatchedSkippedViolation = $skippedViolations; + } + + public function isViolationSkipped(string $depender, string $dependent): bool + { + $matched = isset($this->skippedViolations[$depender]) && in_array($dependent, $this->skippedViolations[$depender], true); + + if ($matched && false !== ($key = array_search($dependent, $this->unmatchedSkippedViolation[$depender], true))) { + unset($this->unmatchedSkippedViolation[$depender][$key]); + } + + return $matched; + } + + /** + * @return array + */ + public function unmatchedSkippedViolations(): array + { + return array_filter($this->unmatchedSkippedViolation); + } + + public function addSkippableViolation(ProcessEvent $event, AnalysisResult $result, string $dependentLayer, ViolationCreatingInterface $violationCreatingRule): void + { + if ($this->isViolationSkipped( + $event->dependency->getDepender() + ->toString(), + $event->dependency->getDependent() + ->toString() + ) + ) { + $result->addRule(new SkippedViolation($event->dependency, $event->dependerLayer, $dependentLayer)); + } else { + $result->addRule(new Violation($event->dependency, $event->dependerLayer, $dependentLayer, $violationCreatingRule)); + } + } +} diff --git a/src/Contract/Analyser/ViolationCreatingInterface.php b/src/Contract/Analyser/ViolationCreatingInterface.php new file mode 100644 index 000000000..ae6e237ef --- /dev/null +++ b/src/Contract/Analyser/ViolationCreatingInterface.php @@ -0,0 +1,20 @@ +dependentLayer; } + + public function ruleName(): string + { + return $this->violationCreatingRule->ruleName(); + } + + public function ruleDescription(): string + { + return $this->violationCreatingRule->ruleDescription(); + } } diff --git a/src/Core/Analyser/DependencyLayersAnalyser.php b/src/Core/Analyser/DependencyLayersAnalyser.php index 48fa97efe..a21976093 100644 --- a/src/Core/Analyser/DependencyLayersAnalyser.php +++ b/src/Core/Analyser/DependencyLayersAnalyser.php @@ -60,9 +60,9 @@ public function analyse(): AnalysisResult $dependentRef = $this->tokenResolver->resolve($dependent, $astMap); $dependentLayers = $this->layerResolver->getLayersForReference($dependentRef); - foreach ($dependerLayers as $dependentLayer) { + foreach ($dependerLayers as $dependerLayer) { $event = new ProcessEvent( - $dependency, $dependerRef, $dependentLayer, $dependentRef, $dependentLayers, $result + $dependency, $dependerRef, $dependerLayer, $dependentRef, $dependentLayers, $result ); $this->eventDispatcher->dispatch($event); diff --git a/src/Core/Analyser/EventHandler/AllowDependencyHandler.php b/src/Core/Analyser/EventHandler/AllowDependencyHandler.php index 2420912f8..6ca89d66f 100644 --- a/src/Core/Analyser/EventHandler/AllowDependencyHandler.php +++ b/src/Core/Analyser/EventHandler/AllowDependencyHandler.php @@ -6,27 +6,17 @@ use Qossmic\Deptrac\Contract\Analyser\ProcessEvent; use Qossmic\Deptrac\Contract\Result\Allowed; -use Qossmic\Deptrac\Contract\Result\Error; -use Qossmic\Deptrac\Core\Ast\AstMap\ClassLike\ClassLikeReference; -use Qossmic\Deptrac\Core\Layer\Exception\CircularReferenceException; -use Qossmic\Deptrac\Core\Layer\LayerProvider; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use function in_array; - /** * @internal */ class AllowDependencyHandler implements EventSubscriberInterface { - public function __construct(private readonly LayerProvider $layerProvider) - { - } - public static function getSubscribedEvents() { return [ - ProcessEvent::class => ['invoke', 4], + ProcessEvent::class => ['invoke', -100], ]; } @@ -34,33 +24,8 @@ public function invoke(ProcessEvent $event): void { $ruleset = $event->getResult(); - foreach ($event->dependentLayers as $dependentLayer => $isPublic) { - try { - $allowedLayers = $this->layerProvider->getAllowedLayers($event->dependerLayer); - } catch (CircularReferenceException $circularReferenceException) { - $ruleset->addError(new Error($circularReferenceException->getMessage())); - $event->stopPropagation(); - - return; - } - - if (!$isPublic && $event->dependerLayer !== $dependentLayer) { - return; - } - - if (!in_array($dependentLayer, $allowedLayers, true)) { - return; - } - - if ($event->dependerLayer !== $dependentLayer - && $event->dependentReference instanceof ClassLikeReference - && $event->dependentReference->isInternal - ) { - return; - } - + foreach ($event->dependentLayers as $dependentLayer => $_) { $ruleset->addRule(new Allowed($event->dependency, $event->dependerLayer, $dependentLayer)); - $event->stopPropagation(); } } diff --git a/src/Core/Analyser/EventHandler/DependsOnDisallowedLayer.php b/src/Core/Analyser/EventHandler/DependsOnDisallowedLayer.php new file mode 100644 index 000000000..38c50196e --- /dev/null +++ b/src/Core/Analyser/EventHandler/DependsOnDisallowedLayer.php @@ -0,0 +1,61 @@ + ['invoke', -1], + ]; + } + + public function invoke(ProcessEvent $event): void + { + $ruleset = $event->getResult(); + + try { + $allowedLayers = $this->eventHelper->layerProvider->getAllowedLayers($event->dependerLayer); + } catch (CircularReferenceException $circularReferenceException) { + $ruleset->addError(new Error($circularReferenceException->getMessage())); + $event->stopPropagation(); + + return; + } + + foreach ($event->dependentLayers as $dependentLayer => $_) { + if (!in_array($dependentLayer, $allowedLayers, true)) { + $this->eventHelper->addSkippableViolation($event, $ruleset, $dependentLayer, $this); + $event->stopPropagation(); + } + } + } + + public function ruleName(): string + { + return 'DependsOnDisallowedLayer'; + } + + public function ruleDescription(): string + { + return 'You are depending on token that is a part of a layer that you are not allowed to depend on.'; + } +} diff --git a/src/Core/Analyser/EventHandler/DependsOnInternalToken.php b/src/Core/Analyser/EventHandler/DependsOnInternalToken.php new file mode 100644 index 000000000..43bb9cd7e --- /dev/null +++ b/src/Core/Analyser/EventHandler/DependsOnInternalToken.php @@ -0,0 +1,51 @@ + ['invoke', -2], + ]; + } + + public function invoke(ProcessEvent $event): void + { + $ruleset = $event->getResult(); + foreach ($event->dependentLayers as $dependentLayer => $_) { + if ($event->dependerLayer !== $dependentLayer + && $event->dependentReference instanceof ClassLikeReference + && $event->dependentReference->isInternal + ) { + $this->eventHelper->addSkippableViolation($event, $ruleset, $dependentLayer, $this); + $event->stopPropagation(); + } + } + } + + public function ruleName(): string + { + return 'DependsOnInternalToken'; + } + + public function ruleDescription(): string + { + return 'You are depending on a token that is internal to the layer and you are not part of that layer.'; + } +} diff --git a/src/Core/Analyser/EventHandler/DependsOnPrivateLayer.php b/src/Core/Analyser/EventHandler/DependsOnPrivateLayer.php new file mode 100644 index 000000000..1c4b58b4f --- /dev/null +++ b/src/Core/Analyser/EventHandler/DependsOnPrivateLayer.php @@ -0,0 +1,48 @@ + ['invoke', -3], + ]; + } + + public function invoke(ProcessEvent $event): void + { + $ruleset = $event->getResult(); + + foreach ($event->dependentLayers as $dependentLayer => $isPublic) { + if ($event->dependerLayer === $dependentLayer && !$isPublic) { + $this->eventHelper->addSkippableViolation($event, $ruleset, $dependentLayer, $this); + $event->stopPropagation(); + } + } + } + + public function ruleName(): string + { + return 'DependsOnPrivateLayer'; + } + + public function ruleDescription(): string + { + return 'You are depending on a part of a layer that was defined as private to that layer and you are not part of that layer.'; + } +} diff --git a/src/Core/Analyser/EventHandler/MatchingLayersHandler.php b/src/Core/Analyser/EventHandler/MatchingLayersHandler.php index 5d4f82c5a..068ec434f 100644 --- a/src/Core/Analyser/EventHandler/MatchingLayersHandler.php +++ b/src/Core/Analyser/EventHandler/MatchingLayersHandler.php @@ -28,7 +28,7 @@ public function invoke(ProcessEvent $event): void public static function getSubscribedEvents() { return [ - ProcessEvent::class => ['invoke', 16], + ProcessEvent::class => ['invoke', 1], ]; } } diff --git a/src/Core/Analyser/EventHandler/SkippedViolationHelper.php b/src/Core/Analyser/EventHandler/SkippedViolationHelper.php deleted file mode 100644 index 6973ac63c..000000000 --- a/src/Core/Analyser/EventHandler/SkippedViolationHelper.php +++ /dev/null @@ -1,47 +0,0 @@ - - */ - private array $unmatchedSkippedViolation; - - /** - * @param array $skippedViolation - */ - public function __construct(private readonly array $skippedViolation) - { - $this->unmatchedSkippedViolation = $skippedViolation; - } - - public function isViolationSkipped(string $depender, string $dependent): bool - { - $matched = isset($this->skippedViolation[$depender]) && in_array($dependent, $this->skippedViolation[$depender], true); - - if ($matched && false !== ($key = array_search($dependent, $this->unmatchedSkippedViolation[$depender], true))) { - unset($this->unmatchedSkippedViolation[$depender][$key]); - } - - return $matched; - } - - /** - * @return array - */ - public function unmatchedSkippedViolations(): array - { - return array_filter($this->unmatchedSkippedViolation); - } -} diff --git a/src/Core/Analyser/EventHandler/UncoveredDependentHandler.php b/src/Core/Analyser/EventHandler/UncoveredDependentHandler.php index e7e28266d..61c3a362f 100644 --- a/src/Core/Analyser/EventHandler/UncoveredDependentHandler.php +++ b/src/Core/Analyser/EventHandler/UncoveredDependentHandler.php @@ -49,7 +49,7 @@ private function ignoreUncoveredInternalClass(ClassLikeToken $token): bool public static function getSubscribedEvents() { return [ - ProcessEvent::class => ['invoke', 32], + ProcessEvent::class => ['invoke', 2], ]; } } diff --git a/src/Core/Analyser/EventHandler/UnmatchedSkippedViolations.php b/src/Core/Analyser/EventHandler/UnmatchedSkippedViolations.php new file mode 100644 index 000000000..63fb6dae0 --- /dev/null +++ b/src/Core/Analyser/EventHandler/UnmatchedSkippedViolations.php @@ -0,0 +1,40 @@ +getResult(); + + foreach ($this->eventHelper->unmatchedSkippedViolations() as $tokenA => $tokensB) { + foreach ($tokensB as $tokenB) { + $ruleset->addError(new Error(sprintf('Skipped violation "%s" for "%s" was not matched.', $tokenB, $tokenA))); + } + } + } + + public static function getSubscribedEvents() + { + return [ + PostProcessEvent::class => ['handleUnmatchedSkipped'], + ]; + } +} diff --git a/src/Core/Analyser/EventHandler/ViolationHandler.php b/src/Core/Analyser/EventHandler/ViolationHandler.php deleted file mode 100644 index 6182c5e42..000000000 --- a/src/Core/Analyser/EventHandler/ViolationHandler.php +++ /dev/null @@ -1,66 +0,0 @@ -|null $skippedViolations - */ - public function __construct(?array $skippedViolations) - { - $this->skippedViolationHelper = new SkippedViolationHelper($skippedViolations ?? []); - } - - public function handleViolation(ProcessEvent $event): void - { - $depender = $event->dependency->getDepender(); - $dependent = $event->dependency->getDependent(); - $ruleset = $event->getResult(); - - foreach ($event->dependentLayers as $dependentLayer => $_) { - if ($this->skippedViolationHelper->isViolationSkipped($depender->toString(), $dependent->toString())) { - $ruleset->addRule(new SkippedViolation($event->dependency, $event->dependerLayer, $dependentLayer)); - - continue; - } - - $ruleset->addRule(new Violation($event->dependency, $event->dependerLayer, $dependentLayer)); - } - } - - public function handleUnmatchedSkipped(PostProcessEvent $event): void - { - $ruleset = $event->getResult(); - - foreach ($this->skippedViolationHelper->unmatchedSkippedViolations() as $classLikeNameA => $classLikes) { - foreach ($classLikes as $classLikeNameB) { - $ruleset->addError(new Error(sprintf('Skipped violation "%s" for "%s" was not matched.', $classLikeNameB, $classLikeNameA))); - } - } - } - - public static function getSubscribedEvents() - { - return [ - ProcessEvent::class => ['handleViolation', -32], - PostProcessEvent::class => ['handleUnmatchedSkipped'], - ]; - } -} diff --git a/src/Supportive/OutputFormatter/TableOutputFormatter.php b/src/Supportive/OutputFormatter/TableOutputFormatter.php index 3841d3270..ef85440d2 100644 --- a/src/Supportive/OutputFormatter/TableOutputFormatter.php +++ b/src/Supportive/OutputFormatter/TableOutputFormatter.php @@ -53,11 +53,11 @@ public function finish( foreach ($groupedRules as $layer => $rules) { $rows = []; foreach ($rules as $rule) { - if ($rule instanceof Uncovered) { - $rows[] = $this->uncoveredRow($rule, $outputFormatterInput->failOnUncovered); - } else { - $rows[] = $this->violationRow($rule); - } + $rows[] = match (true) { + $rule instanceof Uncovered => $this->uncoveredRow($rule, $outputFormatterInput->failOnUncovered), + $rule instanceof Violation => $this->violationRow($rule), + $rule instanceof SkippedViolation => $this->skippedViolationRow($rule), + }; } $style->table(['Reason', $layer], $rows); @@ -77,7 +77,7 @@ public function finish( /** * @return array{string, string} */ - private function violationRow(Violation|SkippedViolation $rule): array + private function skippedViolationRow(SkippedViolation $rule): array { $dependency = $rule->getDependency(); @@ -95,10 +95,31 @@ private function violationRow(Violation|SkippedViolation $rule): array $fileOccurrence = $rule->getDependency()->getFileOccurrence(); $message .= sprintf("\n%s:%d", $fileOccurrence->filepath, $fileOccurrence->line); - return [ - $rule instanceof SkippedViolation ? 'Skipped' : 'Violation', - $message, - ]; + return ['Skipped', $message]; + } + + /** + * @return array{string, string} + */ + private function violationRow(Violation $rule): array + { + $dependency = $rule->getDependency(); + + $message = sprintf( + '%s must not depend on %s', + $dependency->getDepender()->toString(), + $dependency->getDependent()->toString(), + ); + $message .= sprintf("\n%s (%s)", $rule->ruleDescription(), $rule->getDependentLayer()); + + if (count($dependency->serialize()) > 1) { + $message .= "\n".$this->formatMultilinePath($dependency); + } + + $fileOccurrence = $rule->getDependency()->getFileOccurrence(); + $message .= sprintf("\n%s:%d", $fileOccurrence->filepath, $fileOccurrence->line); + + return [sprintf('%s', $rule->ruleName()), $message]; } private function formatMultilinePath(DependencyInterface $dep): string diff --git a/tests/Core/Analyser/EventHandler/SkippedViolationHelperTest.php b/tests/Contract/Analyser/EventHelperTest.php similarity index 88% rename from tests/Core/Analyser/EventHandler/SkippedViolationHelperTest.php rename to tests/Contract/Analyser/EventHelperTest.php index efa06e3c6..8b8c491fd 100644 --- a/tests/Core/Analyser/EventHandler/SkippedViolationHelperTest.php +++ b/tests/Contract/Analyser/EventHelperTest.php @@ -2,13 +2,14 @@ declare(strict_types=1); -namespace Tests\Qossmic\Deptrac\Core\Analyser\EventHandler; +namespace Tests\Qossmic\Deptrac\Contract\Analyser; use PHPUnit\Framework\TestCase; -use Qossmic\Deptrac\Core\Analyser\EventHandler\SkippedViolationHelper; +use Qossmic\Deptrac\Contract\Analyser\EventHelper; +use Qossmic\Deptrac\Contract\Layer\LayerProvider; use Qossmic\Deptrac\Core\Ast\AstMap\ClassLike\ClassLikeToken; -final class SkippedViolationHelperTest extends TestCase +final class EventHelperTest extends TestCase { public function testIsViolationSkipped(): void { @@ -23,7 +24,7 @@ public function testIsViolationSkipped(): void 'DependencyClass2', ], ]; - $helper = new SkippedViolationHelper($configuration); + $helper = new EventHelper($configuration, new LayerProvider([])); self::assertTrue( $helper->isViolationSkipped( @@ -70,7 +71,7 @@ public function testUnmatchedSkippedViolations(): void 'DependencyClass2', ], ]; - $helper = new SkippedViolationHelper($configuration); + $helper = new EventHelper($configuration, new LayerProvider([])); self::assertTrue( $helper->isViolationSkipped( diff --git a/tests/Core/Analyser/EventHandler/AllowDependencyHandlerTest.php b/tests/Core/Analyser/EventHandler/AllowDependencyHandlerTest.php index f020c8771..c491f5808 100644 --- a/tests/Core/Analyser/EventHandler/AllowDependencyHandlerTest.php +++ b/tests/Core/Analyser/EventHandler/AllowDependencyHandlerTest.php @@ -16,6 +16,6 @@ public function testGetSubscribedEvents(): void self::assertCount(1, $subscribedEvents); self::assertArrayHasKey(ProcessEvent::class, $subscribedEvents); - self::assertSame(['invoke', 4], $subscribedEvents[ProcessEvent::class]); + self::assertSame(['invoke', -100], $subscribedEvents[ProcessEvent::class]); } } diff --git a/tests/Core/Analyser/EventHandler/MatchingLayersHandlerTest.php b/tests/Core/Analyser/EventHandler/MatchingLayersHandlerTest.php index 28507ba03..d22323ea6 100644 --- a/tests/Core/Analyser/EventHandler/MatchingLayersHandlerTest.php +++ b/tests/Core/Analyser/EventHandler/MatchingLayersHandlerTest.php @@ -16,6 +16,6 @@ public function testGetSubscribedEvents(): void self::assertCount(1, $subscribedEvents); self::assertArrayHasKey(ProcessEvent::class, $subscribedEvents); - self::assertSame(['invoke', 16], $subscribedEvents[ProcessEvent::class]); + self::assertSame(['invoke', 1], $subscribedEvents[ProcessEvent::class]); } } diff --git a/tests/Core/Analyser/EventHandler/UncoveredDependentHandlerTest.php b/tests/Core/Analyser/EventHandler/UncoveredDependentHandlerTest.php index c9c8232e5..8bc72cf5f 100644 --- a/tests/Core/Analyser/EventHandler/UncoveredDependentHandlerTest.php +++ b/tests/Core/Analyser/EventHandler/UncoveredDependentHandlerTest.php @@ -16,6 +16,6 @@ public function testGetSubscribedEvents(): void self::assertCount(1, $subscribedEvents); self::assertArrayHasKey(ProcessEvent::class, $subscribedEvents); - self::assertSame(['invoke', 32], $subscribedEvents[ProcessEvent::class]); + self::assertSame(['invoke', 2], $subscribedEvents[ProcessEvent::class]); } } diff --git a/tests/Core/Analyser/EventHandler/UnmatchedSkippedViolationsTest.php b/tests/Core/Analyser/EventHandler/UnmatchedSkippedViolationsTest.php new file mode 100644 index 000000000..e3fda03d1 --- /dev/null +++ b/tests/Core/Analyser/EventHandler/UnmatchedSkippedViolationsTest.php @@ -0,0 +1,21 @@ + [], @@ -148,7 +150,8 @@ public function finishProvider(): iterable ]) ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), ], 'errors' => [], diff --git a/tests/Supportive/OutputFormatter/GraphVizDotOutputFormatterTest.php b/tests/Supportive/OutputFormatter/GraphVizDotOutputFormatterTest.php index 9271bf545..57d637de9 100644 --- a/tests/Supportive/OutputFormatter/GraphVizDotOutputFormatterTest.php +++ b/tests/Supportive/OutputFormatter/GraphVizDotOutputFormatterTest.php @@ -23,6 +23,7 @@ use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Filesystem\Path; +use Tests\Qossmic\Deptrac\Supportive\OutputFormatter\data\DummyViolationCreatingRule; use const PHP_EOL; @@ -36,11 +37,11 @@ public function testFinish(): void $classA = ClassLikeToken::fromFQCN('ClassA'); $analysisResult = new AnalysisResult(); - $analysisResult->addRule(new Violation(new Dependency($classA, ClassLikeToken::fromFQCN('ClassB'), $fileOccurrenceA, DependencyType::PARAMETER), 'LayerA', 'LayerB')); - $analysisResult->addRule(new Violation(new Dependency($classA, ClassLikeToken::fromFQCN('ClassHidden'), $fileOccurrenceA, DependencyType::PARAMETER), 'LayerA', 'LayerHidden')); + $analysisResult->addRule(new Violation(new Dependency($classA, ClassLikeToken::fromFQCN('ClassB'), $fileOccurrenceA, DependencyType::PARAMETER), 'LayerA', 'LayerB', new DummyViolationCreatingRule())); + $analysisResult->addRule(new Violation(new Dependency($classA, ClassLikeToken::fromFQCN('ClassHidden'), $fileOccurrenceA, DependencyType::PARAMETER), 'LayerA', 'LayerHidden', new DummyViolationCreatingRule())); $analysisResult->addRule(new Violation(new Dependency(ClassLikeToken::fromFQCN('ClassAB'), ClassLikeToken::fromFQCN('ClassBA'), new FileOccurrence('classAB.php', 1), DependencyType::PARAMETER - ), 'LayerA', 'LayerB')); + ), 'LayerA', 'LayerB', new DummyViolationCreatingRule())); $analysisResult->addRule(new Allowed(new Dependency($classA, ClassLikeToken::fromFQCN('ClassC'), $fileOccurrenceA, DependencyType::PARAMETER), 'LayerA', 'LayerC')); $analysisResult->addRule(new Uncovered(new Dependency($classA, ClassLikeToken::fromFQCN('ClassD'), $fileOccurrenceA, DependencyType::PARAMETER), 'LayerC')); diff --git a/tests/Supportive/OutputFormatter/JUnitOutputFormatterTest.php b/tests/Supportive/OutputFormatter/JUnitOutputFormatterTest.php index ec5a9e8e8..1e23b76e6 100644 --- a/tests/Supportive/OutputFormatter/JUnitOutputFormatterTest.php +++ b/tests/Supportive/OutputFormatter/JUnitOutputFormatterTest.php @@ -24,6 +24,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Style\SymfonyStyle; +use Tests\Qossmic\Deptrac\Supportive\OutputFormatter\data\DummyViolationCreatingRule; final class JUnitOutputFormatterTest extends TestCase { @@ -76,7 +77,8 @@ public function basicDataProvider(): iterable ]) ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), ], 'expected-junit-report_1.xml', @@ -87,7 +89,8 @@ public function basicDataProvider(): iterable new Violation( new Dependency($originalA, $originalB, new FileOccurrence('foo.php', 12), DependencyType::PARAMETER), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), ], 'expected-junit-report_2.xml', @@ -150,7 +153,8 @@ public function basicDataProvider(): iterable ]) ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), ], 'expected-junit-report-with-skipped-violations.xml', diff --git a/tests/Supportive/OutputFormatter/JsonOutputFormatterTest.php b/tests/Supportive/OutputFormatter/JsonOutputFormatterTest.php index 1e67f698b..2243cffff 100644 --- a/tests/Supportive/OutputFormatter/JsonOutputFormatterTest.php +++ b/tests/Supportive/OutputFormatter/JsonOutputFormatterTest.php @@ -25,6 +25,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Style\SymfonyStyle; +use Tests\Qossmic\Deptrac\Supportive\OutputFormatter\data\DummyViolationCreatingRule; final class JsonOutputFormatterTest extends TestCase { @@ -78,7 +79,8 @@ public function basicDataProvider(): iterable ) ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), new Violation( new InheritDependency( @@ -112,7 +114,8 @@ public function basicDataProvider(): iterable ) ), 'LayerA', - 'LayerC' + 'LayerC', + new DummyViolationCreatingRule() ), new Violation( new InheritDependency( @@ -146,7 +149,8 @@ public function basicDataProvider(): iterable ) ), 'LayerA', - 'LayerE' + 'LayerE', + new DummyViolationCreatingRule() ), ], 'expected-json-report_1.json', @@ -160,7 +164,8 @@ public function basicDataProvider(): iterable ClassLikeToken::fromFQCN('OriginalB'), new FileOccurrence('ClassA.php', 12), DependencyType::PARAMETER ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), ], 'expected-json-report_2.json', @@ -280,7 +285,8 @@ public function basicDataProvider(): iterable ) ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), new SkippedViolation( new InheritDependency( @@ -444,7 +450,8 @@ public function testJsonRenderError(): void ClassLikeToken::fromFQCN('OriginalB'.$malformedCharacters), new FileOccurrence('ClassA.php', 12), DependencyType::PARAMETER ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ); $analysisResult = new AnalysisResult(); diff --git a/tests/Supportive/OutputFormatter/TableOutputFormatterTest.php b/tests/Supportive/OutputFormatter/TableOutputFormatterTest.php index ee76186e6..4ea701336 100644 --- a/tests/Supportive/OutputFormatter/TableOutputFormatterTest.php +++ b/tests/Supportive/OutputFormatter/TableOutputFormatterTest.php @@ -26,6 +26,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Style\SymfonyStyle; +use Tests\Qossmic\Deptrac\Supportive\OutputFormatter\data\DummyViolationCreatingRule; use const PHP_EOL; @@ -73,22 +74,24 @@ public function basicDataProvider(): iterable ) ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), ], [], 'warnings' => [], - ' ----------- ------------------------------------------- - Reason LayerA - ----------- ------------------------------------------- - Violation ClassA must not depend on ClassB (LayerB) - ClassInheritD::6 -> - ClassInheritC::5 -> - ClassInheritB::4 -> - ClassInheritA::3 -> - OriginalB::12 - originalA.php:12 - ----------- ------------------------------------------- + ' ----------- ---------------------------------- + Reason LayerA + ----------- ---------------------------------- + DummyRule ClassA must not depend on ClassB + Why? Because! (LayerB) + ClassInheritD::6 -> + ClassInheritC::5 -> + ClassInheritB::4 -> + ClassInheritA::3 -> + OriginalB::12 + originalA.php:12 + ----------- ---------------------------------- -------------------- ----- @@ -110,17 +113,19 @@ public function basicDataProvider(): iterable new Violation( new Dependency($originalA, $originalB, new FileOccurrence('originalA.php', 12), DependencyType::PARAMETER), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), ], [], 'warnings' => [], - ' ----------- ------------------------------------------------- - Reason LayerA - ----------- ------------------------------------------------- - Violation OriginalA must not depend on OriginalB (LayerB) - originalA.php:12 - ----------- ------------------------------------------------- + ' ----------- ---------------------------------------- + Reason LayerA + ----------- ---------------------------------------- + DummyRule OriginalA must not depend on OriginalB + Why? Because! (LayerB) + originalA.php:12 + ----------- ---------------------------------------- -------------------- ----- diff --git a/tests/Supportive/OutputFormatter/XMLOutputFormatterTest.php b/tests/Supportive/OutputFormatter/XMLOutputFormatterTest.php index 02eed3600..f888361af 100644 --- a/tests/Supportive/OutputFormatter/XMLOutputFormatterTest.php +++ b/tests/Supportive/OutputFormatter/XMLOutputFormatterTest.php @@ -23,6 +23,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Style\SymfonyStyle; +use Tests\Qossmic\Deptrac\Supportive\OutputFormatter\data\DummyViolationCreatingRule; final class XMLOutputFormatterTest extends TestCase { @@ -73,7 +74,8 @@ public function basicDataProvider(): iterable ]) ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), ], 'expected-xml-report_1.xml', @@ -86,7 +88,8 @@ public function basicDataProvider(): iterable new FileOccurrence('ClassA.php', 12), DependencyType::PARAMETER ), 'LayerA', - 'LayerB' + 'LayerB', + new DummyViolationCreatingRule() ), ], 'expected-xml-report_2.xml', diff --git a/tests/Supportive/OutputFormatter/data/DummyViolationCreatingRule.php b/tests/Supportive/OutputFormatter/data/DummyViolationCreatingRule.php new file mode 100644 index 000000000..73e55547d --- /dev/null +++ b/tests/Supportive/OutputFormatter/data/DummyViolationCreatingRule.php @@ -0,0 +1,25 @@ +