diff --git a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index d031a9773..2c8f03f1d 100644 --- a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php +++ b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -39,6 +39,7 @@ use PhpParser\Node\Stmt\Finally_; use PhpParser\Node\Stmt\For_; use PhpParser\Node\Stmt\Foreach_; +use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Goto_; use PhpParser\Node\Stmt\If_; use PhpParser\Node\Stmt\Property; @@ -165,6 +166,14 @@ private function getLines(NodeAbstract $node, bool $fromReturns): array } if ($node instanceof BinaryOp) { + if ($node instanceof BinaryOp\Concat && + ( + $node->left instanceof Node\Expr\Variable || + $node->right instanceof Node\Expr\Variable + )) { + return [$this->getNodeStartLine($node->right)]; + } + return $fromReturns ? $this->getLines($node->right, $fromReturns) : []; } @@ -180,6 +189,10 @@ private function getLines(NodeAbstract $node, bool $fromReturns): array if ($node instanceof ClassMethod) { if ($node->name->name !== '__construct') { + if ($node->stmts === []) { + return [$node->getEndLine()]; + } + return []; } @@ -232,6 +245,14 @@ private function getLines(NodeAbstract $node, bool $fromReturns): array return [$this->getNodeStartLine($node->cond)]; } + if ($node instanceof Function_) { + if ($node->stmts === []) { + return [$node->getEndLine()]; + } + + return []; + } + return [$this->getNodeStartLine($node)]; } @@ -292,6 +313,7 @@ private function isExecutable(Node $node): bool $node instanceof Finally_ || $node instanceof For_ || $node instanceof Foreach_ || + $node instanceof Function_ || $node instanceof Goto_ || $node instanceof If_ || $node instanceof Match_ || diff --git a/tests/_files/source_with_multiline_constant_return.php b/tests/_files/source_with_multiline_constant_return.php index e129ec660..08d32a43b 100644 --- a/tests/_files/source_with_multiline_constant_return.php +++ b/tests/_files/source_with_multiline_constant_return.php @@ -485,10 +485,44 @@ public function unaryMinusNowdoc(): float { return - + (int) <<<'EOF' 1. 2 EOF ; } + + public function concatWithVar(): string + { + $var1 = 'start'; + + $var1 = + <<<'EOF' +right +EOF + . + $var1 + ; + + $var1 = + $var1 + . + <<<'EOF' +left +EOF + ; + + return $var1; + } + + public + function + emptyMethod + ( + ) + : + void + { + } } diff --git a/tests/_files/source_with_oneline_annotations.php b/tests/_files/source_with_oneline_annotations.php index 7b1cb1cbd..7d3981e0a 100644 --- a/tests/_files/source_with_oneline_annotations.php +++ b/tests/_files/source_with_oneline_annotations.php @@ -34,3 +34,7 @@ function baz() print '*'; } + +function xyz() +{ +} diff --git a/tests/tests/Data/RawCodeCoverageDataTest.php b/tests/tests/Data/RawCodeCoverageDataTest.php index dcb639d6b..893177968 100644 --- a/tests/tests/Data/RawCodeCoverageDataTest.php +++ b/tests/tests/Data/RawCodeCoverageDataTest.php @@ -312,6 +312,7 @@ public function testInlineCommentsKeepTheLine(): void $this->assertEquals( [ + 13, 19, 22, 26, @@ -320,6 +321,7 @@ public function testInlineCommentsKeepTheLine(): void 32, 33, 35, + 40, ], array_keys(RawCodeCoverageData::fromUncoveredFile($file, new ParsingFileAnalyser(true, true))->lineCoverage()[$file]) ); @@ -497,7 +499,14 @@ public function testReturnStatementWithConstantExprOnlyReturnTheLineOfLast(): vo 456, 466, 478, - 489, + 490, + 498, + 500, + 505, + 508, + 512, // This is correct: not the line with the $var1, but the right operand of the Concat + 516, + 527, ], array_keys(RawCodeCoverageData::fromUncoveredFile($file, new ParsingFileAnalyser(true, true))->lineCoverage()[$file]) );