From b495050dff093bc216c0676fbf0a4d37192cc5a7 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Mon, 7 Mar 2022 09:17:53 +0100 Subject: [PATCH] Return statement: evaluate content for correct LoC markings --- .../ExecutableLinesFindingVisitor.php | 51 +++++++++++++++ ...rce_with_return_and_array_with_scalars.php | 65 +++++++++++++++++++ tests/tests/Data/RawCodeCoverageDataTest.php | 24 ++++++- 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 tests/_files/source_with_return_and_array_with_scalars.php diff --git a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index d8950333e..ae0b08ae7 100644 --- a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php +++ b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -10,7 +10,9 @@ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; use PhpParser\Node; +use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\ArrayDimFetch; +use PhpParser\Node\Expr\ArrayItem; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\BinaryOp; use PhpParser\Node\Expr\CallLike; @@ -64,6 +66,11 @@ final class ExecutableLinesFindingVisitor extends NodeVisitorAbstract */ private $propertyLines = []; + /** + * @psalm-var array + */ + private $returns = []; + public function enterNode(Node $node): void { $this->savePropertyLines($node); @@ -86,6 +93,8 @@ public function enterNode(Node $node): void */ public function executableLines(): array { + $this->computeReturns(); + sort($this->executableLines); return $this->executableLines; @@ -102,6 +111,25 @@ private function savePropertyLines(Node $node): void } } + private function computeReturns(): void + { + foreach ($this->returns as $return) { + foreach (range($return->getStartLine(), $return->getEndLine()) as $loc) { + if (isset($this->executableLines[$loc])) { + continue 2; + } + } + + $line = $return->getEndLine(); + + if ($return->expr !== null) { + $line = $return->expr->getStartLine(); + } + + $this->executableLines[$line] = $line; + } + } + /** * @return int[] */ @@ -122,6 +150,22 @@ private function getLines(Node $node): array return [$node->dim->getStartLine()]; } + if ($node instanceof Array_) { + $startLine = $node->getStartLine(); + + if (isset($this->executableLines[$startLine])) { + return []; + } + + if ([] === $node->items) { + return [$node->getEndLine()]; + } + + if ($node->items[0] instanceof ArrayItem) { + return [$node->items[0]->getStartLine()]; + } + } + if ($node instanceof ClassMethod) { if ($node->name->name !== '__construct') { return []; @@ -178,6 +222,12 @@ private function getLines(Node $node): array return []; } + if ($node instanceof Return_) { + $this->returns[] = $node; + + return []; + } + return [$node->getStartLine()]; } @@ -185,6 +235,7 @@ private function isExecutable(Node $node): bool { return $node instanceof Assign || $node instanceof ArrayDimFetch || + $node instanceof Array_ || $node instanceof BinaryOp || $node instanceof Break_ || $node instanceof CallLike || diff --git a/tests/_files/source_with_return_and_array_with_scalars.php b/tests/_files/source_with_return_and_array_with_scalars.php new file mode 100644 index 000000000..033d04d5b --- /dev/null +++ b/tests/_files/source_with_return_and_array_with_scalars.php @@ -0,0 +1,65 @@ +assertEquals( + [ + 8, + 15, + 24, + 30, + 40, + 47, + 54, + 63, + ], + array_keys(RawCodeCoverageData::fromUncoveredFile($file, new ParsingFileAnalyser(true, true))->lineCoverage()[$file]) + ); + } + public function testCoverageForFileWithInlineAnnotations(): void { $filename = TEST_FILES_PATH . 'source_with_oneline_annotations.php';