diff --git a/src/Rules/MaxLinePerClassRule.php b/src/Rules/MaxLinePerClassRule.php index 4ed7a47..4ed3321 100644 --- a/src/Rules/MaxLinePerClassRule.php +++ b/src/Rules/MaxLinePerClassRule.php @@ -20,6 +20,10 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { + if ($node->name === null) { + return []; + } + $startLine = $node->getStartLine() + 1; $endLine = $node->getEndLine() - 1; $lineCount = $endLine - $startLine; @@ -33,14 +37,14 @@ public function processNode(Node $node, Scope $scope): array self::MAX_LINES ) ) - ->tip( - sprintf( - 'The recommended class length is %d lines.', - self::RECOMMENDED_LINES + ->tip( + sprintf( + 'The recommended class length is %d lines.', + self::RECOMMENDED_LINES + ) ) - ) - ->identifier('xefi.maxLinePerClass') - ->build(), + ->identifier('xefi.maxLinePerClass') + ->build(), ]; } diff --git a/src/Rules/NoLaravelObserverRule.php b/src/Rules/NoLaravelObserverRule.php index d0d01d4..33320f2 100644 --- a/src/Rules/NoLaravelObserverRule.php +++ b/src/Rules/NoLaravelObserverRule.php @@ -30,26 +30,44 @@ public function processNode(Node $node, Scope $scope): array return $errors; } - protected function checkObserveMethod(array &$errors, Node $node) : void + protected function checkObserveMethod(array &$errors, Node $node): void { - if ($node instanceof Node\Expr\StaticCall && $node->name?->toString() === 'observe') { + if (! $node instanceof Node\Expr\StaticCall) { + return; + } + + if ($this->resolveCallName($node) === 'observe') { $errors[] = RuleErrorBuilder::message('Observers are forbidden because it can create technical debt. Please use Event & Listeners instead.') ->identifier(self::$ruleIdentifier) ->build(); } } + private function resolveCallName(Node $node): ?string + { + $name = match (true) { + $node instanceof Node\Expr\StaticCall, + $node instanceof Node\Expr\MethodCall, + $node instanceof Node\Expr\NullsafeMethodCall => $node->name, + default => null, + }; + + return $name instanceof Node\Identifier ? $name->toString() : null; + } + protected function checkClassesAndNamespaces(array &$errors, Node $node, Scope $scope) : void { - if ($node instanceof Node\Stmt\Class_) { - $className = $node->name->toString(); - $namespace = $scope->getNamespace(); + if (! $node instanceof Node\Stmt\Class_) { + return; + } - if (str_ends_with($className, 'Observer') || str_contains($namespace, 'Observers')) { - $errors[] = RuleErrorBuilder::message('Observers are forbidden because it can create technical debt. Please use Event & Listeners instead.') - ->identifier(self::$ruleIdentifier) - ->build(); - } + $className = $node->name?->toString() ?? ''; + $namespace = $scope->getNamespace() ?? ''; + + if (str_ends_with($className, 'Observer') || str_contains($namespace, 'Observers')) { + $errors[] = RuleErrorBuilder::message('Observers are forbidden because it can create technical debt. Please use Event & Listeners instead.') + ->identifier(self::$ruleIdentifier) + ->build(); } } diff --git a/tests/Rules/NoLaravelObserverRuleTest.php b/tests/Rules/NoLaravelObserverRuleTest.php index bed1bd8..c89aacd 100644 --- a/tests/Rules/NoLaravelObserverRuleTest.php +++ b/tests/Rules/NoLaravelObserverRuleTest.php @@ -63,4 +63,23 @@ public function testRuleDoesNotDumpExceptionInAttribute(): void { $this->analyse([__DIR__ . '/data/NoLaravelObserverRule/NoObservedByAttribute.php'], []); } + public function testDynamicStaticCallDoesNotCrash(): void + { + $this->analyse([__DIR__ . '/data/NoLaravelObserverRule/DynamicObserveCall.php'], []); + } + + public function testAnonymousClassDoesNotCrash(): void + { + $this->analyse([__DIR__ . '/data/NoLaravelObserverRule/AnonymousClass.php'], []); + } + + public function testStaticObserveCallIsStillDetected(): void + { + $this->analyse([__DIR__ . '/data/NoLaravelObserverRule/StaticObserveCall.php'], [ + [ + 'Observers are forbidden because it can create technical debt. Please use Event & Listeners instead.', + 8, + ], + ]); + } } \ No newline at end of file diff --git a/tests/Rules/data/NoLaravelObserverRule/AnonymousClass.php b/tests/Rules/data/NoLaravelObserverRule/AnonymousClass.php new file mode 100644 index 0000000..904e360 --- /dev/null +++ b/tests/Rules/data/NoLaravelObserverRule/AnonymousClass.php @@ -0,0 +1,13 @@ +