From 23553757f2faf6c0f9e63ddf85bb17d381727813 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Thu, 27 Oct 2022 16:15:21 +0200 Subject: [PATCH 1/5] Preserve meaningful test cases --- .../source_with_multiline_constant_return.php | 219 +++--------------- tests/tests/Data/RawCodeCoverageDataTest.php | 58 ++--- 2 files changed, 45 insertions(+), 232 deletions(-) diff --git a/tests/_files/source_with_multiline_constant_return.php b/tests/_files/source_with_multiline_constant_return.php index 6c8a6bf4a..5acdc6b25 100644 --- a/tests/_files/source_with_multiline_constant_return.php +++ b/tests/_files/source_with_multiline_constant_return.php @@ -245,22 +245,7 @@ public function Spaceship(): int ; } - public function nowdocSimpleA(): string - { - return <<<'EOF' - foo - EOF; - } - - public function nowdocSimpleB(): string - { - return - <<<'EOF' - foo - EOF; - } - - public function nowdocSimpleC(): string + public function nowdoc(): string { return <<<'EOF' @@ -316,17 +301,8 @@ public function complexAssociativityRight(): int ** 2 ** - 3; - } - - public function complexAssociativityLeft(): int - { - return - 1 - >> - 2 - >> - 3; + 3 + ; } public function complexAssociativityNa(): bool @@ -335,7 +311,8 @@ public function complexAssociativityNa(): bool ! ! ! - false; + false + ; } public function complexTernary(): int @@ -347,17 +324,8 @@ public function complexTernary(): int ? 3 : 4 ) - : 5; - } - - public function complexNullCoalescing(): int - { - return - null - ?? - 1 - ?? - null; + : 5 + ; } public function constFromArray(): string @@ -368,165 +336,38 @@ public function constFromArray(): string 'ro', 'fi', 'omega', - ][2]; + ] + [2] + ; } public function withNotConstInTheMiddle(): string { return '' - . '' - . phpversion() - . '' - . ''; - } - - public function andA(): bool - { - return - true - && false; - } - - public function andB(): bool - { - return - true - && true; - } - - public function andC(): bool - { - return - false - && true; - } - - public function andD(): bool - { - return - false - && false; - } - - public function andE(): bool - { - return - __TRAIT__ // compile time constant evaluated to false - && 1 - && 0; - } - - public function andF(): bool - { - return - PHP_VERSION_ID // compile time constant evaluated to true - && 1 - && 0; - } - - public function orA(): bool - { - return - true - || false; - } - - public function orB(): bool - { - return - true - || true; - } - - public function orC(): bool - { - return - false - || true; - } - - public function orD(): bool - { - return - false - || false; - } - - public function orE(): bool - { - return - __TRAIT__ - || true - || false; - } - - public function orF(): bool - { - return - PHP_VERSION_ID - || true - || false; - } - - public function orG(): bool - { - return - PHP_VERSION_ID === PHP_VERSION_ID - || true - || false; + . + '' + . + phpversion() + . + '' + . + '' + ; } - public function orH(): bool + public function multipleConcats(): string { return - PHP_VERSION_ID !== PHP_VERSION_ID - || true - || false; - } - - public function constIfFalseA(): bool - { - if (false) { - return true; - } - - return false; - } - - public function constIfFalseB(): bool - { - if (__TRAIT__) { - return true; - } - - return false; - } - - public function constIfTrueA(): bool - { - if (true) { - return true; - } - - return false; - } - - public function constIfTrueB(): bool - { - if (PHP_VERSION_ID) { - return true; - } - - return false; - } - - public function constIfUnknown(): bool - { - if (__NOT_EXPECTED_TO_BE_KNOWN_CONSTANT__) { - return true; - } - - return false; + 'a' + . + 'b' + . + 'c' + . + 'd' + . + 'e' + ; } } diff --git a/tests/tests/Data/RawCodeCoverageDataTest.php b/tests/tests/Data/RawCodeCoverageDataTest.php index d1391ee83..c8136c764 100644 --- a/tests/tests/Data/RawCodeCoverageDataTest.php +++ b/tests/tests/Data/RawCodeCoverageDataTest.php @@ -438,7 +438,6 @@ public function testReturnStatementWithConstantExprOnlyReturnTheLineOfLast(): vo 28, 37, 46, - 53, 55, 64, 73, @@ -447,7 +446,7 @@ public function testReturnStatementWithConstantExprOnlyReturnTheLineOfLast(): vo 100, 109, 118, - 125, + 127, 136, 145, 154, @@ -461,48 +460,21 @@ public function testReturnStatementWithConstantExprOnlyReturnTheLineOfLast(): vo 226, 235, 244, - 251, - 259, - 267, - 276, - 284, + 252, + 261, + 269, + 278, 293, - 308, - 319, - 329, - 338, - 344, - 350, - 356, - 360, - 371, - 379, - 381, - 388, - 395, - 401, - 408, - 415, - 425, - 431, - 438, - 446, - 453, - 460, - 467, - 475, - 484, - 490, - 494, - 499, - 503, - 508, - 509, - 517, - 518, - 526, - 527, - 530, + 304, + 314, + 321, + 323, + 324, + 325, + 327, + 340, + 351, + 370, ], array_keys(RawCodeCoverageData::fromUncoveredFile($file, new ParsingFileAnalyser(true, true))->lineCoverage()[$file]) ); From b6d1fe675e813f4ac2ff79adfabbec9e54a0cfbe Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Thu, 27 Oct 2022 16:16:06 +0200 Subject: [PATCH 2/5] Fix BinaryOp, Scalar and ArrayDimFetch return cases --- .../ExecutableLinesFindingVisitor.php | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index f69363caf..443d3073a 100644 --- a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php +++ b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -49,6 +49,7 @@ use PhpParser\Node\Stmt\TryCatch; use PhpParser\Node\Stmt\Unset_; use PhpParser\Node\Stmt\While_; +use PhpParser\NodeAbstract; use PhpParser\NodeVisitorAbstract; /** @@ -71,6 +72,11 @@ final class ExecutableLinesFindingVisitor extends NodeVisitorAbstract */ private $returns = []; + /** + * @psalm-var array + */ + private $arrayDimFetchVars = []; + public function enterNode(Node $node): void { $this->savePropertyLines($node); @@ -123,7 +129,7 @@ private function computeReturns(): void $line = $return->getEndLine(); if ($return->expr !== null) { - $line = $return->expr->getStartLine(); + $line = $this->getNodeStartLine($return->expr); } $this->executableLines[$line] = $line; @@ -136,13 +142,6 @@ private function computeReturns(): void private function getLines(Node $node): array { if ($node instanceof BinaryOp) { - if (($node->left instanceof Node\Scalar || - $node->left instanceof Node\Expr\ConstFetch) && - ($node->right instanceof Node\Scalar || - $node->right instanceof Node\Expr\ConstFetch)) { - return [$node->right->getStartLine()]; - } - return []; } @@ -154,6 +153,8 @@ private function getLines(Node $node): array } if ($node instanceof ArrayDimFetch) { + $this->arrayDimFetchVars[spl_object_hash($node->var)] = true; + if (null === $node->dim) { return []; } @@ -162,6 +163,10 @@ private function getLines(Node $node): array } if ($node instanceof Array_) { + if (isset($this->arrayDimFetchVars[spl_object_hash($node)])) { + return []; + } + $startLine = $node->getStartLine(); if (isset($this->executableLines[$startLine])) { @@ -242,6 +247,29 @@ private function getLines(Node $node): array return [$node->getStartLine()]; } + private function getNodeStartLine(NodeAbstract $node): int + { + if ($node instanceof Node\Expr\BooleanNot || + $node instanceof Node\Expr\AssignOp\ShiftLeft || + $node instanceof Node\Expr\AssignOp\ShiftRight + ) { + return $node->getEndLine(); + } + + if ($node instanceof BinaryOp) { + return $this->getNodeStartLine($node->right); + } + + if ($node instanceof Node\Scalar\String_ && ( + $node->getAttribute('kind') === Node\Scalar\String_::KIND_HEREDOC || + $node->getAttribute('kind') === Node\Scalar\String_::KIND_NOWDOC + )) { + return $node->getStartLine() + 1; + } + + return $node->getStartLine(); + } + private function isExecutable(Node $node): bool { return $node instanceof Assign || From 14e606835a9935a395961619c279f44ccfa63917 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Fri, 28 Oct 2022 08:17:12 +0200 Subject: [PATCH 3/5] Prefer spl_object_id over spl_object_hash --- src/StaticAnalysis/ExecutableLinesFindingVisitor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index 443d3073a..f654c9bcc 100644 --- a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php +++ b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -153,7 +153,7 @@ private function getLines(Node $node): array } if ($node instanceof ArrayDimFetch) { - $this->arrayDimFetchVars[spl_object_hash($node->var)] = true; + $this->arrayDimFetchVars[spl_object_id($node->var)] = true; if (null === $node->dim) { return []; @@ -163,7 +163,7 @@ private function getLines(Node $node): array } if ($node instanceof Array_) { - if (isset($this->arrayDimFetchVars[spl_object_hash($node)])) { + if (isset($this->arrayDimFetchVars[spl_object_id($node)])) { return []; } From 92d36ee84941dd172d6ba1c062eb2d1bbbc24711 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Fri, 28 Oct 2022 08:18:25 +0200 Subject: [PATCH 4/5] Test multiline heredoc as well --- tests/_files/source_with_multiline_constant_return.php | 10 ++++++++++ tests/tests/Data/RawCodeCoverageDataTest.php | 1 + 2 files changed, 11 insertions(+) diff --git a/tests/_files/source_with_multiline_constant_return.php b/tests/_files/source_with_multiline_constant_return.php index 5acdc6b25..9ccfed9b0 100644 --- a/tests/_files/source_with_multiline_constant_return.php +++ b/tests/_files/source_with_multiline_constant_return.php @@ -370,4 +370,14 @@ public function multipleConcats(): string 'e' ; } + + public function multilineHeredoc(): string + { + return <<lineCoverage()[$file]) ); From 929645693fa072519af30043292499db57154967 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Fri, 28 Oct 2022 08:23:10 +0200 Subject: [PATCH 5/5] Adapt array types to spl_object_id return type --- src/StaticAnalysis/ExecutableLinesFindingVisitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index f654c9bcc..821701a3a 100644 --- a/src/StaticAnalysis/ExecutableLinesFindingVisitor.php +++ b/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -73,7 +73,7 @@ final class ExecutableLinesFindingVisitor extends NodeVisitorAbstract private $returns = []; /** - * @psalm-var array + * @psalm-var array */ private $arrayDimFetchVars = [];