From 463f0b18f4e7c6a330f24fe21cd19a253eb72459 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 20 Jul 2026 16:01:27 +0700 Subject: [PATCH] fix: report first side effect line instead of last in PSR-1 file analysis --- src/Analyser/FileAnalysisProvider.php | 13 +++++-- tests/Analyser/FileAnalysisProviderTest.php | 38 +++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/Analyser/FileAnalysisProvider.php b/src/Analyser/FileAnalysisProvider.php index 53c2277..afe7092 100644 --- a/src/Analyser/FileAnalysisProvider.php +++ b/src/Analyser/FileAnalysisProvider.php @@ -253,8 +253,12 @@ private function fileState(array $nodes): array if (($node instanceof Namespace_ || $node instanceof Declare_) && $node->stmts !== null) { $state = $this->fileState($node->stmts); $declaresSymbols = $declaresSymbols || $state['declaresSymbols']; - $hasSideEffects = $hasSideEffects || $state['hasSideEffects']; - $sideEffectLine = $state['hasSideEffects'] ? $state['sideEffectLine'] : $sideEffectLine; + + if (! $hasSideEffects && $state['hasSideEffects']) { + $sideEffectLine = $state['sideEffectLine']; + } + + $hasSideEffects = $hasSideEffects || $state['hasSideEffects']; continue; } @@ -273,8 +277,11 @@ private function fileState(array $nodes): array continue; } + if (! $hasSideEffects) { + $sideEffectLine = $node->getStartLine(); + } + $hasSideEffects = true; - $sideEffectLine = $node->getStartLine(); } return [ diff --git a/tests/Analyser/FileAnalysisProviderTest.php b/tests/Analyser/FileAnalysisProviderTest.php index b69d0f4..85d951c 100644 --- a/tests/Analyser/FileAnalysisProviderTest.php +++ b/tests/Analyser/FileAnalysisProviderTest.php @@ -187,6 +187,44 @@ final class Foo {} $this->assertSame(4, $fileAnalysis->sideEffectLine); } + public function testReportsFirstSideEffectLineWhenMultipleSideEffectsExist(): void + { + $file = $this->source(<<<'PHP' + analyse($file); + + $this->assertTrue($fileAnalysis->declaresSymbols); + $this->assertTrue($fileAnalysis->hasSideEffects); + $this->assertSame(4, $fileAnalysis->sideEffectLine); + } + + public function testKeepsFirstSideEffectLineAcrossNamespaceBlocks(): void + { + $file = $this->source(<<<'PHP' + analyse($file); + + $this->assertTrue($fileAnalysis->hasSideEffects); + $this->assertSame(4, $fileAnalysis->sideEffectLine); + } + public function testRejectsConditionalDeclarationsWithBranchesOrSideEffects(): void { $elseIfFile = $this->source(<<<'PHP'