Skip to content

Commit 4543e7e

Browse files
committed
Represent FunctionCover in objects
1 parent 0373bbb commit 4543e7e

File tree

4 files changed

+236
-45
lines changed

4 files changed

+236
-45
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of phpunit/php-code-coverage.
4+
*
5+
* (c) Sebastian Bergmann <sebastian@phpunit.de>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace SebastianBergmann\CodeCoverage\Data;
11+
12+
use SebastianBergmann\CodeCoverage\Driver\XdebugDriver;
13+
14+
/**
15+
* @phpstan-import-type TestIdType from ProcessedCodeCoverageData
16+
* @phpstan-import-type XdebugBranchCoverageType from XdebugDriver
17+
*/
18+
final readonly class ProcessedBranchCoverageData
19+
{
20+
public function __construct(
21+
public int $op_start,
22+
public int $op_end,
23+
public int $line_start,
24+
public int $line_end,
25+
/** @var list<TestIdType> */
26+
public array $hit,
27+
/** @var array<int, int> */
28+
public array $out,
29+
/** @var array<int, int> */
30+
public array $out_hit,
31+
32+
)
33+
{
34+
}
35+
36+
/**
37+
* @param XdebugBranchCoverageType $xdebugCoverageData
38+
*/
39+
static public function fromXdebugCoverage(array $xdebugCoverageData): self
40+
{
41+
return new self(
42+
$xdebugCoverageData['op_start'],
43+
$xdebugCoverageData['op_end'],
44+
$xdebugCoverageData['line_start'],
45+
$xdebugCoverageData['line_end'],
46+
[],
47+
$xdebugCoverageData['out'],
48+
$xdebugCoverageData['out_hit'],
49+
);
50+
}
51+
52+
public function merge(self $data): self
53+
{
54+
return new self(
55+
$this->op_start,
56+
$this->op_end,
57+
$this->line_start,
58+
$this->line_end,
59+
array_unique(array_merge($this->hit, $data->hit)),
60+
$this->out,
61+
$this->out_hit,
62+
);
63+
}
64+
65+
/**
66+
* @param TestIdType $testCaseId
67+
*/
68+
public function recordHit(string $testCaseId): self {
69+
$hit = $this->hit;
70+
$hit[] = $testCaseId;
71+
72+
return new self(
73+
$this->op_start,
74+
$this->op_end,
75+
$this->line_start,
76+
$this->line_end,
77+
$hit,
78+
$this->out,
79+
$this->out_hit,
80+
);
81+
82+
}
83+
}

src/Data/ProcessedCodeCoverageData.php

Lines changed: 13 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,7 @@
2525
* @phpstan-import-type XdebugFunctionCoverageType from XdebugDriver
2626
*
2727
* @phpstan-type TestIdType string
28-
* @phpstan-type FunctionCoverageDataType array{
29-
* branches: array<int, array{
30-
* op_start: int,
31-
* op_end: int,
32-
* line_start: int,
33-
* line_end: int,
34-
* hit: list<TestIdType>,
35-
* out: array<int, int>,
36-
* out_hit: array<int, int>,
37-
* }>,
38-
* paths: array<int, array{
39-
* path: array<int, int>,
40-
* hit: list<TestIdType>,
41-
* }>
42-
* }
28+
* @phpstan-type FunctionCoverageDataType ProcessedFunctionCoverageData
4329
* @phpstan-type FunctionCoverageType array<string, array<string, FunctionCoverageDataType>>
4430
*/
4531
final class ProcessedCodeCoverageData
@@ -98,13 +84,13 @@ public function markCodeAsExecutedByTestCase(string $testCaseId, RawCodeCoverage
9884
foreach ($functions as $functionName => $functionData) {
9985
foreach ($functionData['branches'] as $branchId => $branchData) {
10086
if ($branchData['hit'] === Driver::BRANCH_HIT) {
101-
$this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'][] = $testCaseId;
87+
$this->functionCoverage[$file][$functionName]->recordBranchHit($branchId, $testCaseId);
10288
}
10389
}
10490

10591
foreach ($functionData['paths'] as $pathId => $pathData) {
10692
if ($pathData['hit'] === Driver::BRANCH_HIT) {
107-
$this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'][] = $testCaseId;
93+
$this->functionCoverage[$file][$functionName]->recordPathHit($pathId, $testCaseId);
10894
}
10995
}
11096
}
@@ -197,14 +183,6 @@ public function merge(self $newData): void
197183
} else {
198184
$this->initPreviouslyUnseenFunction($file, $functionName, $functionData);
199185
}
200-
201-
foreach ($functionData['branches'] as $branchId => $branchData) {
202-
$this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'], $branchData['hit']));
203-
}
204-
205-
foreach ($functionData['paths'] as $pathId => $pathData) {
206-
$this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'], $pathData['hit']));
207-
}
208186
}
209187
}
210188
}
@@ -243,17 +221,13 @@ private function priorityForLine(array $data, int $line): int
243221
*
244222
* @param FunctionCoverageDataType|XdebugFunctionCoverageType $functionData
245223
*/
246-
private function initPreviouslyUnseenFunction(string $file, string $functionName, array $functionData): void
224+
private function initPreviouslyUnseenFunction(string $file, string $functionName, ProcessedFunctionCoverageData|array $functionData): void
247225
{
248-
$this->functionCoverage[$file][$functionName] = $functionData;
249-
250-
foreach (array_keys($functionData['branches']) as $branchId) {
251-
$this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = [];
226+
if (is_array($functionData)) {
227+
$functionData = ProcessedFunctionCoverageData::fromXdebugCoverage($functionData);
252228
}
253229

254-
foreach (array_keys($functionData['paths']) as $pathId) {
255-
$this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = [];
256-
}
230+
$this->functionCoverage[$file][$functionName] = $functionData;
257231
}
258232

259233
/**
@@ -263,20 +237,14 @@ private function initPreviouslyUnseenFunction(string $file, string $functionName
263237
*
264238
* @param FunctionCoverageDataType|XdebugFunctionCoverageType $functionData
265239
*/
266-
private function initPreviouslySeenFunction(string $file, string $functionName, array $functionData): void
240+
private function initPreviouslySeenFunction(string $file, string $functionName, ProcessedFunctionCoverageData|array $functionData): void
267241
{
268-
foreach ($functionData['branches'] as $branchId => $branchData) {
269-
if (!isset($this->functionCoverage[$file][$functionName]['branches'][$branchId])) {
270-
$this->functionCoverage[$file][$functionName]['branches'][$branchId] = $branchData;
271-
$this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = [];
272-
}
242+
if (is_array($functionData)) {
243+
$functionData = ProcessedFunctionCoverageData::fromXdebugCoverage($functionData);
273244
}
274245

275-
foreach ($functionData['paths'] as $pathId => $pathData) {
276-
if (!isset($this->functionCoverage[$file][$functionName]['paths'][$pathId])) {
277-
$this->functionCoverage[$file][$functionName]['paths'][$pathId] = $pathData;
278-
$this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = [];
279-
}
280-
}
246+
$this->functionCoverage[$file][$functionName] = $this->functionCoverage[$file][$functionName]->merge(
247+
$functionData
248+
);
281249
}
282250
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of phpunit/php-code-coverage.
4+
*
5+
* (c) Sebastian Bergmann <sebastian@phpunit.de>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace SebastianBergmann\CodeCoverage\Data;
11+
12+
use SebastianBergmann\CodeCoverage\Driver\XdebugDriver;
13+
14+
/**
15+
* @phpstan-import-type TestIdType from ProcessedCodeCoverageData
16+
* @phpstan-import-type XdebugFunctionCoverageType from XdebugDriver
17+
*/
18+
final class ProcessedFunctionCoverageData {
19+
public function __construct(
20+
/** @var array<int, ProcessedBranchCoverageData> */
21+
public array $branches,
22+
/** @var array<int, ProcessedPathCoverageData> */
23+
public array $paths,
24+
25+
) {}
26+
27+
/**
28+
* @param XdebugFunctionCoverageType $xdebugCoverageData
29+
*/
30+
static public function fromXdebugCoverage(array $xdebugCoverageData): self
31+
{
32+
$branches = [];
33+
foreach($xdebugCoverageData['branches'] as $branchId => $branch) {
34+
$branches[$branchId] = ProcessedBranchCoverageData::fromXdebugCoverage($branch);
35+
}
36+
$paths = [];
37+
foreach($xdebugCoverageData['paths'] as $pathId => $path) {
38+
$paths[$pathId] = ProcessedPathCoverageData::fromXdebugCoverage($path);
39+
}
40+
41+
return new self(
42+
$branches,
43+
$paths
44+
);
45+
}
46+
47+
public function merge(self $data): self
48+
{
49+
$branches = $this->branches;
50+
foreach($data->branches as $branchId => $branch) {
51+
if (isset($branches[$branchId])) {
52+
continue;
53+
}
54+
$branches[$branchId] = $branches[$branchId]->merge($branch);
55+
}
56+
57+
$paths = $this->paths;
58+
foreach($data->paths as $pathId => $path) {
59+
if (isset($paths[$pathId])) {
60+
continue;
61+
}
62+
$paths[$pathId] = $paths[$pathId]->merge($path);
63+
}
64+
65+
return new self(
66+
$branches,
67+
$paths
68+
);
69+
}
70+
71+
/**
72+
* @param TestIdType $testCaseId
73+
*/
74+
public function recordBranchHit(int $branchId, string $testCaseId): void {
75+
$this->branches[$branchId]->recordHit($testCaseId);
76+
}
77+
78+
public function recordPathHit(int $pathId, string $testCaseId): void {
79+
$this->paths[$pathId]->recordHit($testCaseId);
80+
}
81+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of phpunit/php-code-coverage.
4+
*
5+
* (c) Sebastian Bergmann <sebastian@phpunit.de>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace SebastianBergmann\CodeCoverage\Data;
11+
12+
use SebastianBergmann\CodeCoverage\Driver\XdebugDriver;
13+
14+
/**
15+
* @phpstan-import-type TestIdType from ProcessedCodeCoverageData
16+
* @phpstan-import-type XdebugPathCoverageType from XdebugDriver
17+
*/
18+
final readonly class ProcessedPathCoverageData {
19+
public function __construct(
20+
/** @var array<int, int> */
21+
public array $path,
22+
/** @var list<TestIdType> */
23+
public array $hit,
24+
) {}
25+
26+
/**
27+
* @param XdebugPathCoverageType $xdebugCoverageData
28+
*/
29+
static public function fromXdebugCoverage(array $xdebugCoverageData): self
30+
{
31+
return new self(
32+
$xdebugCoverageData['path'],
33+
[],
34+
);
35+
}
36+
37+
public function merge(self $data): self
38+
{
39+
return new self(
40+
$this->path,
41+
array_unique(array_merge($this->hit, $data->hit)),
42+
);
43+
}
44+
45+
/**
46+
* @param TestIdType $testCaseId
47+
*/
48+
public function recordHit(string $testCaseId): self
49+
{
50+
$hit = $this->hit;
51+
$hit[] = $testCaseId;
52+
53+
return new self(
54+
$this->path,
55+
$hit
56+
);
57+
}
58+
59+
}

0 commit comments

Comments
 (0)