Skip to content

Commit 9910da8

Browse files
committed
Represent FunctionCover in objects
1 parent 3b267ae commit 9910da8

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 <[email protected]>
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
* @phpstan-type LineCoverageType array<string, array<int, null|list<TestIdType>>>
4531
*/
@@ -99,13 +85,13 @@ public function markCodeAsExecutedByTestCase(string $testCaseId, RawCodeCoverage
9985
foreach ($functions as $functionName => $functionData) {
10086
foreach ($functionData['branches'] as $branchId => $branchData) {
10187
if ($branchData['hit'] === Driver::BRANCH_HIT) {
102-
$this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'][] = $testCaseId;
88+
$this->functionCoverage[$file][$functionName]->recordBranchHit($branchId, $testCaseId);
10389
}
10490
}
10591

10692
foreach ($functionData['paths'] as $pathId => $pathData) {
10793
if ($pathData['hit'] === Driver::BRANCH_HIT) {
108-
$this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'][] = $testCaseId;
94+
$this->functionCoverage[$file][$functionName]->recordPathHit($pathId, $testCaseId);
10995
}
11096
}
11197
}
@@ -213,14 +199,6 @@ public function merge(self $newData): void
213199
} else {
214200
$this->initPreviouslyUnseenFunction($file, $functionName, $functionData);
215201
}
216-
217-
foreach ($functionData['branches'] as $branchId => $branchData) {
218-
$this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'], $branchData['hit']));
219-
}
220-
221-
foreach ($functionData['paths'] as $pathId => $pathData) {
222-
$this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'], $pathData['hit']));
223-
}
224202
}
225203
}
226204
}
@@ -259,17 +237,13 @@ private function priorityForLine(array $data, int $line): int
259237
*
260238
* @param FunctionCoverageDataType|XdebugFunctionCoverageType $functionData
261239
*/
262-
private function initPreviouslyUnseenFunction(string $file, string $functionName, array $functionData): void
240+
private function initPreviouslyUnseenFunction(string $file, string $functionName, ProcessedFunctionCoverageData|array $functionData): void
263241
{
264-
$this->functionCoverage[$file][$functionName] = $functionData;
265-
266-
foreach (array_keys($functionData['branches']) as $branchId) {
267-
$this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = [];
242+
if (is_array($functionData)) {
243+
$functionData = ProcessedFunctionCoverageData::fromXdebugCoverage($functionData);
268244
}
269245

270-
foreach (array_keys($functionData['paths']) as $pathId) {
271-
$this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = [];
272-
}
246+
$this->functionCoverage[$file][$functionName] = $functionData;
273247
}
274248

275249
/**
@@ -279,20 +253,14 @@ private function initPreviouslyUnseenFunction(string $file, string $functionName
279253
*
280254
* @param FunctionCoverageDataType|XdebugFunctionCoverageType $functionData
281255
*/
282-
private function initPreviouslySeenFunction(string $file, string $functionName, array $functionData): void
256+
private function initPreviouslySeenFunction(string $file, string $functionName, ProcessedFunctionCoverageData|array $functionData): void
283257
{
284-
foreach ($functionData['branches'] as $branchId => $branchData) {
285-
if (!isset($this->functionCoverage[$file][$functionName]['branches'][$branchId])) {
286-
$this->functionCoverage[$file][$functionName]['branches'][$branchId] = $branchData;
287-
$this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = [];
288-
}
258+
if (is_array($functionData)) {
259+
$functionData = ProcessedFunctionCoverageData::fromXdebugCoverage($functionData);
289260
}
290261

291-
foreach ($functionData['paths'] as $pathId => $pathData) {
292-
if (!isset($this->functionCoverage[$file][$functionName]['paths'][$pathId])) {
293-
$this->functionCoverage[$file][$functionName]['paths'][$pathId] = $pathData;
294-
$this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = [];
295-
}
296-
}
262+
$this->functionCoverage[$file][$functionName] = $this->functionCoverage[$file][$functionName]->merge(
263+
$functionData
264+
);
297265
}
298266
}
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 <[email protected]>
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 <[email protected]>
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)