Skip to content

Commit 8c95e20

Browse files
Merge branch '9.2'
2 parents 5c85a2c + 6882cdb commit 8c95e20

File tree

60 files changed

+670
-523
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+670
-523
lines changed

ChangeLog.md

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](htt
1414
* This component is no longer supported on PHP 7.3 and PHP 7.4
1515
* This component no longer supports Xdebug 2
1616

17+
## [9.2.11] - 2022-MM-DD
18+
19+
### Fixed
20+
21+
* [#889](https://github.com/sebastianbergmann/php-code-coverage/issues/889): Code Coverage depends on autoload order
22+
1723
## [9.2.10] - 2021-12-05
1824

1925
### Fixed
@@ -362,6 +368,7 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](htt
362368
* This component is no longer supported on PHP 7.1
363369

364370
[10.0.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2...master
371+
[9.2.11]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.10...9.2
365372
[9.2.10]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.9...9.2.10
366373
[9.2.9]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.8...9.2.9
367374
[9.2.8]: https://github.com/sebastianbergmann/php-code-coverage/compare/9.2.7...9.2.8

src/CodeCoverage.php

+14-1
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ public function append(RawCodeCoverageData $rawData, PhptTestCase|string|TestCas
190190

191191
$this->applyFilter($rawData);
192192

193+
$this->applyExecutableLinesFilter($rawData);
194+
193195
if ($this->useAnnotationsForIgnoringCode) {
194196
$this->applyIgnoredLinesFilter($rawData);
195197
}
@@ -378,7 +380,8 @@ private function applyCoversAnnotationFilter(RawCodeCoverageData $rawData, array
378380

379381
if (is_array($linesToBeCovered)) {
380382
foreach ($linesToBeCovered as $fileToBeCovered => $includedLines) {
381-
$rawData->keepCoverageDataOnlyForLines($fileToBeCovered, $includedLines);
383+
$rawData->keepLineCoverageDataOnlyForLines($fileToBeCovered, $includedLines);
384+
$rawData->keepFunctionCoverageDataOnlyForLines($fileToBeCovered, $includedLines);
382385
}
383386
}
384387
}
@@ -396,6 +399,16 @@ private function applyFilter(RawCodeCoverageData $data): void
396399
}
397400
}
398401

402+
private function applyExecutableLinesFilter(RawCodeCoverageData $data): void
403+
{
404+
foreach (array_keys($data->lineCoverage()) as $filename) {
405+
$data->keepLineCoverageDataOnlyForLines(
406+
$filename,
407+
$this->uncoveredFileAnalyser()->executableLinesIn($filename)
408+
);
409+
}
410+
}
411+
399412
private function applyIgnoredLinesFilter(RawCodeCoverageData $data): void
400413
{
401414
foreach (array_keys($data->lineCoverage()) as $filename) {

src/RawCodeCoverageData.php

+18-10
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public function removeCoverageDataForFile(string $filename): void
101101
/**
102102
* @param int[] $lines
103103
*/
104-
public function keepCoverageDataOnlyForLines(string $filename, array $lines): void
104+
public function keepLineCoverageDataOnlyForLines(string $filename, array $lines): void
105105
{
106106
if (!isset($this->lineCoverage[$filename])) {
107107
return;
@@ -111,17 +111,25 @@ public function keepCoverageDataOnlyForLines(string $filename, array $lines): vo
111111
$this->lineCoverage[$filename],
112112
array_flip($lines)
113113
);
114+
}
114115

115-
if (isset($this->functionCoverage[$filename])) {
116-
foreach ($this->functionCoverage[$filename] as $functionName => $functionData) {
117-
foreach ($functionData['branches'] as $branchId => $branch) {
118-
if (count(array_diff(range($branch['line_start'], $branch['line_end']), $lines)) > 0) {
119-
unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]);
116+
/**
117+
* @param int[] $lines
118+
*/
119+
public function keepFunctionCoverageDataOnlyForLines(string $filename, array $lines): void
120+
{
121+
if (!isset($this->functionCoverage[$filename])) {
122+
return;
123+
}
120124

121-
foreach ($functionData['paths'] as $pathId => $path) {
122-
if (in_array($branchId, $path['path'], true)) {
123-
unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]);
124-
}
125+
foreach ($this->functionCoverage[$filename] as $functionName => $functionData) {
126+
foreach ($functionData['branches'] as $branchId => $branch) {
127+
if (count(array_diff(range($branch['line_start'], $branch['line_end']), $lines)) > 0) {
128+
unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]);
129+
130+
foreach ($functionData['paths'] as $pathId => $path) {
131+
if (in_array($branchId, $path['path'], true)) {
132+
unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]);
125133
}
126134
}
127135
}

src/StaticAnalysis/CachingCoveredFileAnalyser.php

+7-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
final class CachingCoveredFileAnalyser extends Cache implements CoveredFileAnalyser
1818
{
19+
private const CACHE_FORMAT_VERSION = 2;
20+
1921
private CoveredFileAnalyser $coveredFileAnalyser;
2022

2123
private array $cache = [];
@@ -74,8 +76,10 @@ public function ignoredLinesFor(string $filename): array
7476

7577
public function process(string $filename): void
7678
{
77-
if ($this->has($filename, __CLASS__)) {
78-
$this->cache[$filename] = $this->read($filename, __CLASS__, [LinesOfCode::class]);
79+
$cacheKey = __CLASS__ . self::CACHE_FORMAT_VERSION;
80+
81+
if ($this->has($filename, $cacheKey)) {
82+
$this->cache[$filename] = $this->read($filename, $cacheKey, [LinesOfCode::class]);
7983

8084
return;
8185
}
@@ -88,6 +92,6 @@ public function process(string $filename): void
8892
'ignoredLinesFor' => $this->coveredFileAnalyser->ignoredLinesFor($filename),
8993
];
9094

91-
$this->write($filename, __CLASS__, $this->cache[$filename]);
95+
$this->write($filename, $cacheKey, $this->cache[$filename]);
9296
}
9397
}

src/StaticAnalysis/CachingUncoveredFileAnalyser.php

+7-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
*/
1515
final class CachingUncoveredFileAnalyser extends Cache implements UncoveredFileAnalyser
1616
{
17+
private const CACHE_FORMAT_VERSION = 2;
18+
1719
private UncoveredFileAnalyser $uncoveredFileAnalyser;
1820

1921
public function __construct(string $directory, UncoveredFileAnalyser $uncoveredFileAnalyser)
@@ -25,13 +27,15 @@ public function __construct(string $directory, UncoveredFileAnalyser $uncoveredF
2527

2628
public function executableLinesIn(string $filename): array
2729
{
28-
if ($this->has($filename, __METHOD__)) {
29-
return $this->read($filename, __METHOD__);
30+
$cacheKey = __CLASS__ . self::CACHE_FORMAT_VERSION;
31+
32+
if ($this->has($filename, $cacheKey)) {
33+
return $this->read($filename, $cacheKey);
3034
}
3135

3236
$data = $this->uncoveredFileAnalyser->executableLinesIn($filename);
3337

34-
$this->write($filename, __METHOD__, $data);
38+
$this->write($filename, $cacheKey, $data);
3539

3640
return $data;
3741
}

src/StaticAnalysis/ExecutableLinesFindingVisitor.php

+51-9
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
*/
1010
namespace SebastianBergmann\CodeCoverage\StaticAnalysis;
1111

12-
use function array_unique;
13-
use function sort;
1412
use PhpParser\Node;
13+
use PhpParser\Node\Expr\BinaryOp;
14+
use PhpParser\Node\Expr\CallLike;
15+
use PhpParser\Node\Scalar;
1516
use PhpParser\Node\Stmt\Break_;
1617
use PhpParser\Node\Stmt\Case_;
1718
use PhpParser\Node\Stmt\Catch_;
@@ -26,6 +27,7 @@
2627
use PhpParser\Node\Stmt\Foreach_;
2728
use PhpParser\Node\Stmt\Goto_;
2829
use PhpParser\Node\Stmt\If_;
30+
use PhpParser\Node\Stmt\Property;
2931
use PhpParser\Node\Stmt\Return_;
3032
use PhpParser\Node\Stmt\Switch_;
3133
use PhpParser\Node\Stmt\Throw_;
@@ -40,34 +42,69 @@
4042
final class ExecutableLinesFindingVisitor extends NodeVisitorAbstract
4143
{
4244
/**
43-
* @psalm-var list<int>
45+
* @psalm-var array<int, int>
4446
*/
4547
private array $executableLines = [];
4648

49+
/**
50+
* @psalm-var array<int, int>
51+
*/
52+
private $propertyLines = [];
53+
4754
public function enterNode(Node $node): void
4855
{
56+
$this->savePropertyLines($node);
57+
4958
if (!$this->isExecutable($node)) {
5059
return;
5160
}
5261

53-
$this->executableLines[] = $node->getStartLine();
62+
$line = $this->getLine($node);
63+
64+
if (isset($this->propertyLines[$line])) {
65+
return;
66+
}
67+
68+
$this->executableLines[$line] = $line;
5469
}
5570

5671
/**
57-
* @psalm-return list<int>
72+
* @psalm-return array<int, int>
5873
*/
5974
public function executableLines(): array
6075
{
61-
$executableLines = array_unique($this->executableLines);
76+
return $this->executableLines;
77+
}
78+
79+
private function savePropertyLines(Node $node): void
80+
{
81+
if (!$node instanceof Property && !$node instanceof Node\Stmt\ClassConst) {
82+
return;
83+
}
6284

63-
sort($executableLines);
85+
foreach (range($node->getStartLine(), $node->getEndLine()) as $index) {
86+
$this->propertyLines[$index] = $index;
87+
}
88+
}
89+
90+
private function getLine(Node $node): int
91+
{
92+
if (
93+
$node instanceof Node\Expr\PropertyFetch ||
94+
$node instanceof Node\Expr\NullsafePropertyFetch ||
95+
$node instanceof Node\Expr\StaticPropertyFetch
96+
) {
97+
return $node->getEndLine();
98+
}
6499

65-
return $executableLines;
100+
return $node->getStartLine();
66101
}
67102

68103
private function isExecutable(Node $node): bool
69104
{
70-
return $node instanceof Break_ ||
105+
return $node instanceof BinaryOp ||
106+
$node instanceof Break_ ||
107+
$node instanceof CallLike ||
71108
$node instanceof Case_ ||
72109
$node instanceof Catch_ ||
73110
$node instanceof Continue_ ||
@@ -82,10 +119,15 @@ private function isExecutable(Node $node): bool
82119
$node instanceof Goto_ ||
83120
$node instanceof If_ ||
84121
$node instanceof Return_ ||
122+
$node instanceof Scalar ||
85123
$node instanceof Switch_ ||
86124
$node instanceof Throw_ ||
87125
$node instanceof TryCatch ||
88126
$node instanceof Unset_ ||
127+
$node instanceof Node\Expr\Assign ||
128+
$node instanceof Node\Expr\PropertyFetch ||
129+
$node instanceof Node\Expr\NullsafePropertyFetch ||
130+
$node instanceof Node\Expr\StaticPropertyFetch ||
89131
$node instanceof While_;
90132
}
91133
}

tests/TestCase.php

+4-6
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ protected function getLineCoverageXdebugDataForBankAccount()
4545
29 => -1,
4646
31 => -1,
4747
32 => -2,
48+
33 => -2,
49+
35 => 1,
4850
],
4951
]),
5052
RawCodeCoverageData::fromXdebugWithoutPathCoverage([
@@ -59,6 +61,7 @@ protected function getLineCoverageXdebugDataForBankAccount()
5961
29 => 1,
6062
31 => -1,
6163
32 => -2,
64+
33 => -2,
6265
],
6366
]),
6467
RawCodeCoverageData::fromXdebugWithoutPathCoverage([
@@ -90,6 +93,7 @@ protected function getLineCoverageXdebugDataForBankAccount()
9093
29 => 1,
9194
31 => 1,
9295
32 => -2,
96+
33 => -2,
9397
],
9498
]),
9599
];
@@ -1346,20 +1350,17 @@ protected function getExpectedLineCoverageDataArrayForBankAccount(): array
13461350
0 => 'BankAccountTest::testBalanceIsInitiallyZero',
13471351
1 => 'BankAccountTest::testDepositWithdrawMoney',
13481352
],
1349-
9 => null,
13501353
13 => [],
13511354
14 => [],
13521355
15 => [],
13531356
16 => [],
1354-
18 => [],
13551357
22 => [
13561358
0 => 'BankAccountTest::testBalanceCannotBecomeNegative2',
13571359
1 => 'BankAccountTest::testDepositWithdrawMoney',
13581360
],
13591361
24 => [
13601362
0 => 'BankAccountTest::testDepositWithdrawMoney',
13611363
],
1362-
25 => null,
13631364
29 => [
13641365
0 => 'BankAccountTest::testBalanceCannotBecomeNegative',
13651366
1 => 'BankAccountTest::testDepositWithdrawMoney',
@@ -1380,20 +1381,17 @@ protected function getExpectedLineCoverageDataArrayForBankAccountInReverseOrder(
13801381
0 => 'BankAccountTest::testDepositWithdrawMoney',
13811382
1 => 'BankAccountTest::testBalanceIsInitiallyZero',
13821383
],
1383-
9 => null,
13841384
13 => [],
13851385
14 => [],
13861386
15 => [],
13871387
16 => [],
1388-
18 => [],
13891388
22 => [
13901389
0 => 'BankAccountTest::testBalanceCannotBecomeNegative2',
13911390
1 => 'BankAccountTest::testDepositWithdrawMoney',
13921391
],
13931392
24 => [
13941393
0 => 'BankAccountTest::testDepositWithdrawMoney',
13951394
],
1396-
25 => null,
13971395
29 => [
13981396
0 => 'BankAccountTest::testDepositWithdrawMoney',
13991397
1 => 'BankAccountTest::testBalanceCannotBecomeNegative',

tests/_files/BankAccount-clover-line.xml

+3-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<project timestamp="%i" name="BankAccount">
44
<file name="%s%eBankAccount.php">
55
<class name="BankAccount" namespace="global">
6-
<metrics complexity="5" methods="4" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="10" coveredstatements="5" elements="14" coveredelements="8"/>
6+
<metrics complexity="5" methods="4" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="9" coveredstatements="5" elements="13" coveredelements="8"/>
77
</class>
88
<line num="6" type="method" name="getBalance" visibility="public" complexity="1" crap="1" count="2"/>
99
<line num="8" type="stmt" count="2"/>
@@ -12,15 +12,14 @@
1212
<line num="14" type="stmt" count="0"/>
1313
<line num="15" type="stmt" count="0"/>
1414
<line num="16" type="stmt" count="0"/>
15-
<line num="18" type="stmt" count="0"/>
1615
<line num="20" type="method" name="depositMoney" visibility="public" complexity="1" crap="1" count="2"/>
1716
<line num="22" type="stmt" count="2"/>
1817
<line num="24" type="stmt" count="1"/>
1918
<line num="27" type="method" name="withdrawMoney" visibility="public" complexity="1" crap="1" count="2"/>
2019
<line num="29" type="stmt" count="2"/>
2120
<line num="31" type="stmt" count="1"/>
22-
<metrics loc="33" ncloc="33" classes="1" methods="4" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="10" coveredstatements="5" elements="14" coveredelements="8"/>
21+
<metrics loc="34" ncloc="34" classes="1" methods="4" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="9" coveredstatements="5" elements="13" coveredelements="8"/>
2322
</file>
24-
<metrics files="1" loc="33" ncloc="33" classes="1" methods="4" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="10" coveredstatements="5" elements="14" coveredelements="8"/>
23+
<metrics files="1" loc="34" ncloc="34" classes="1" methods="4" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="9" coveredstatements="5" elements="13" coveredelements="8"/>
2524
</project>
2625
</coverage>

tests/_files/BankAccount-clover-path.xml

+3-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<project timestamp="%i" name="BankAccount">
44
<file name="%s%eBankAccount.php">
55
<class name="BankAccount" namespace="global">
6-
<metrics complexity="5" methods="4" coveredmethods="3" conditionals="7" coveredconditionals="3" statements="10" coveredstatements="5" elements="21" coveredelements="11"/>
6+
<metrics complexity="5" methods="4" coveredmethods="3" conditionals="7" coveredconditionals="3" statements="9" coveredstatements="5" elements="20" coveredelements="11"/>
77
</class>
88
<line num="6" type="method" name="getBalance" visibility="public" complexity="1" crap="1" count="2"/>
99
<line num="8" type="stmt" count="2"/>
@@ -12,15 +12,14 @@
1212
<line num="14" type="stmt" count="0"/>
1313
<line num="15" type="stmt" count="0"/>
1414
<line num="16" type="stmt" count="0"/>
15-
<line num="18" type="stmt" count="0"/>
1615
<line num="20" type="method" name="depositMoney" visibility="public" complexity="1" crap="1" count="2"/>
1716
<line num="22" type="stmt" count="2"/>
1817
<line num="24" type="stmt" count="1"/>
1918
<line num="27" type="method" name="withdrawMoney" visibility="public" complexity="1" crap="1" count="2"/>
2019
<line num="29" type="stmt" count="2"/>
2120
<line num="31" type="stmt" count="1"/>
22-
<metrics loc="33" ncloc="33" classes="1" methods="4" coveredmethods="3" conditionals="7" coveredconditionals="3" statements="10" coveredstatements="5" elements="21" coveredelements="11"/>
21+
<metrics loc="34" ncloc="34" classes="1" methods="4" coveredmethods="3" conditionals="7" coveredconditionals="3" statements="9" coveredstatements="5" elements="20" coveredelements="11"/>
2322
</file>
24-
<metrics files="1" loc="33" ncloc="33" classes="1" methods="4" coveredmethods="3" conditionals="7" coveredconditionals="3" statements="10" coveredstatements="5" elements="21" coveredelements="11"/>
23+
<metrics files="1" loc="34" ncloc="34" classes="1" methods="4" coveredmethods="3" conditionals="7" coveredconditionals="3" statements="9" coveredstatements="5" elements="20" coveredelements="11"/>
2524
</project>
2625
</coverage>

0 commit comments

Comments
 (0)