From f795a1a9c4e022caba4bd9d50b9522c9c1258d5e Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Tue, 8 Nov 2022 10:33:46 +0100 Subject: [PATCH 1/5] Fix Concat operations with variables #953 --- .../ExecutableLinesFindingVisitor.php | 8 +++++++ .../source_with_multiline_constant_return.php | 22 ++++++++++++++++++- tests/tests/Data/RawCodeCoverageDataTest.php | 8 ++++++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index d031a9773..4dad2110c 100644 --- a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php +++ b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -165,6 +165,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 [$node->right->getStartLine()]; + } + return $fromReturns ? $this->getLines($node->right, $fromReturns) : []; } diff --git a/tests/_files/source_with_multiline_constant_return.php b/tests/_files/source_with_multiline_constant_return.php index e129ec660..44cab12aa 100644 --- a/tests/_files/source_with_multiline_constant_return.php +++ b/tests/_files/source_with_multiline_constant_return.php @@ -396,7 +396,7 @@ public function unaryLogicalNotWithNotConstInTheMiddle(): bool public function unaryMinusWithNotConstInTheMiddle(): float { return - - ( + (int) ( '' . phpversion() @@ -485,10 +485,30 @@ public function unaryMinusNowdoc(): float { return - + (int) <<<'EOF' 1. 2 EOF ; } + + public function concatWithVar(): string + { + $var1 = 'start'; + + $var1 = + 'right' + . + $var1 + ; + + $var1 = + $var1 + . + 'left' + ; + + return $var1; + } } diff --git a/tests/tests/Data/RawCodeCoverageDataTest.php b/tests/tests/Data/RawCodeCoverageDataTest.php index dcb639d6b..fbf7ece1b 100644 --- a/tests/tests/Data/RawCodeCoverageDataTest.php +++ b/tests/tests/Data/RawCodeCoverageDataTest.php @@ -497,7 +497,13 @@ public function testReturnStatementWithConstantExprOnlyReturnTheLineOfLast(): vo 456, 466, 478, - 489, + 490, + 498, + 500, + 503, + 506, + 509, // This is correct: not the line with the $var1, but the right operand of the Concat + 512, ], array_keys(RawCodeCoverageData::fromUncoveredFile($file, new ParsingFileAnalyser(true, true))->lineCoverage()[$file]) ); From 33b6f30ecfc67eb3e495aecaecd771c6992261b0 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Thu, 10 Nov 2022 08:42:34 +0100 Subject: [PATCH 2/5] Test against heredocs to ensure first line gets always counted correctly --- src/StaticAnalysis/ExecutableLinesFindingVisitor.php | 2 +- tests/_files/source_with_multiline_constant_return.php | 8 ++++++-- tests/tests/Data/RawCodeCoverageDataTest.php | 8 ++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index 4dad2110c..cc8b7ee53 100644 --- a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php +++ b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -170,7 +170,7 @@ private function getLines(NodeAbstract $node, bool $fromReturns): array $node->left instanceof Node\Expr\Variable || $node->right instanceof Node\Expr\Variable )) { - return [$node->right->getStartLine()]; + return [$this->getNodeStartLine($node->right)]; } return $fromReturns ? $this->getLines($node->right, $fromReturns) : []; diff --git a/tests/_files/source_with_multiline_constant_return.php b/tests/_files/source_with_multiline_constant_return.php index 44cab12aa..4f6232646 100644 --- a/tests/_files/source_with_multiline_constant_return.php +++ b/tests/_files/source_with_multiline_constant_return.php @@ -498,7 +498,9 @@ public function concatWithVar(): string $var1 = 'start'; $var1 = - 'right' + <<<'EOF' +right +EOF . $var1 ; @@ -506,7 +508,9 @@ public function concatWithVar(): string $var1 = $var1 . - 'left' + <<<'EOF' +left +EOF ; return $var1; diff --git a/tests/tests/Data/RawCodeCoverageDataTest.php b/tests/tests/Data/RawCodeCoverageDataTest.php index fbf7ece1b..b97cfe76b 100644 --- a/tests/tests/Data/RawCodeCoverageDataTest.php +++ b/tests/tests/Data/RawCodeCoverageDataTest.php @@ -500,10 +500,10 @@ public function testReturnStatementWithConstantExprOnlyReturnTheLineOfLast(): vo 490, 498, 500, - 503, - 506, - 509, // This is correct: not the line with the $var1, but the right operand of the Concat - 512, + 505, + 508, + 512, // This is correct: not the line with the $var1, but the right operand of the Concat + 516, ], array_keys(RawCodeCoverageData::fromUncoveredFile($file, new ParsingFileAnalyser(true, true))->lineCoverage()[$file]) ); From 97359710a23be8f9fc509188a7dfd859641c5ccf Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Thu, 10 Nov 2022 08:50:13 +0100 Subject: [PATCH 3/5] Add coverage for empty methods --- src/StaticAnalysis/ExecutableLinesFindingVisitor.php | 4 ++++ tests/_files/source_with_multiline_constant_return.php | 10 ++++++++++ tests/tests/Data/RawCodeCoverageDataTest.php | 1 + 3 files changed, 15 insertions(+) diff --git a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index cc8b7ee53..8c96db1bf 100644 --- a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php +++ b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -188,6 +188,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 []; } diff --git a/tests/_files/source_with_multiline_constant_return.php b/tests/_files/source_with_multiline_constant_return.php index 4f6232646..00275a3f3 100644 --- a/tests/_files/source_with_multiline_constant_return.php +++ b/tests/_files/source_with_multiline_constant_return.php @@ -515,4 +515,14 @@ public function concatWithVar(): string return $var1; } + + public + function + emptyMethod + ( + ) + : + void + { + } } diff --git a/tests/tests/Data/RawCodeCoverageDataTest.php b/tests/tests/Data/RawCodeCoverageDataTest.php index b97cfe76b..94a297eec 100644 --- a/tests/tests/Data/RawCodeCoverageDataTest.php +++ b/tests/tests/Data/RawCodeCoverageDataTest.php @@ -504,6 +504,7 @@ public function testReturnStatementWithConstantExprOnlyReturnTheLineOfLast(): vo 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]) ); From abe0c547f301bef1c1167d884b1f1d87d8515ba4 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Thu, 10 Nov 2022 08:58:44 +0100 Subject: [PATCH 4/5] Gather CC of empty functions too --- src/StaticAnalysis/ExecutableLinesFindingVisitor.php | 10 ++++++++++ tests/_files/source_with_oneline_annotations.php | 4 ++++ tests/tests/Data/RawCodeCoverageDataTest.php | 2 ++ 3 files changed, 16 insertions(+) diff --git a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index 8c96db1bf..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; @@ -244,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)]; } @@ -304,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_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 94a297eec..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]) ); From c4eaf4dc556eeab12e0117bc7e352c23ae4e70a2 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Thu, 10 Nov 2022 15:02:38 +0100 Subject: [PATCH 5/5] Revert unnecessary cast --- tests/_files/source_with_multiline_constant_return.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/_files/source_with_multiline_constant_return.php b/tests/_files/source_with_multiline_constant_return.php index 00275a3f3..08d32a43b 100644 --- a/tests/_files/source_with_multiline_constant_return.php +++ b/tests/_files/source_with_multiline_constant_return.php @@ -396,7 +396,7 @@ public function unaryLogicalNotWithNotConstInTheMiddle(): bool public function unaryMinusWithNotConstInTheMiddle(): float { return - - (int) ( + ( '' . phpversion()