diff --git a/src/Testing/CompositeRule.php b/src/Testing/CompositeRule.php new file mode 100644 index 0000000000..b1403d53bd --- /dev/null +++ b/src/Testing/CompositeRule.php @@ -0,0 +1,53 @@ + + * + * @api + */ +final class CompositeRule implements Rule +{ + + private DirectRegistry $registry; + + /** + * @param array> $rules + * + * @api + */ + public function __construct(array $rules) + { + $this->registry = new DirectRegistry($rules); + } + + public function getNodeType(): string + { + return Node::class; + } + + public function processNode(Node $node, Scope&NodeCallbackInvoker $scope): array + { + $errors = []; + + $nodeType = get_class($node); + foreach ($this->registry->getRules($nodeType) as $rule) { + foreach ($rule->processNode($node, $scope) as $error) { + $errors[] = $error; + } + } + + return $errors; + } + +} diff --git a/tests/PHPStan/Testing/CompositeRuleTest.php b/tests/PHPStan/Testing/CompositeRuleTest.php new file mode 100644 index 0000000000..2539a53c6b --- /dev/null +++ b/tests/PHPStan/Testing/CompositeRuleTest.php @@ -0,0 +1,98 @@ + + */ +final class CompositeRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new CompositeRule([ + /** + * @implements Rule + */ + new class implements Rule { + + public function getNodeType(): string + { + return String_::class; + } + + /** + * @param String_ $node + */ + public function processNode(Node $node, Scope&NodeCallbackInvoker $scope): array + { + if (ctype_digit($node->value)) { + $scope->invokeNodeCallback( + new Int_((int) $node->value, ['startLine' => $node->getStartLine()]), + ); + + return []; + } + + return [ + RuleErrorBuilder::message('Error from String_ Rule.')->identifier('CompositeRuleString')->build(), + ]; + } + + }, + /** + * @implements Rule + */ + new class implements Rule { + + public function getNodeType(): string + { + return Int_::class; + } + + /** + * @param Int_ $node + */ + public function processNode(Node $node, Scope $scope): array + { + return [ + RuleErrorBuilder::message('Error from Int_ Rule.')->identifier('CompositeRuleInt')->build(), + ]; + } + + }, + ]); + } + + public function testRule(): void + { + $this->analyse([__DIR__ . '/data/composite-rule.php'], [ + [ + 'Error from String_ Rule.', + 6, + ], + [ + 'Error from Int_ Rule.', + 7, + ], + [ + 'Error from Int_ Rule.', + 9, + ], + [ + 'Error from Int_ Rule.', + 13, + ], + ]); + } + +} diff --git a/tests/PHPStan/Testing/data/composite-rule.php b/tests/PHPStan/Testing/data/composite-rule.php new file mode 100644 index 0000000000..b7adcb348b --- /dev/null +++ b/tests/PHPStan/Testing/data/composite-rule.php @@ -0,0 +1,14 @@ +