Skip to content

Commit 60ca290

Browse files
Consider child classes of child classes for ClassesThatExtendClass target
1 parent 044468b commit 60ca290

File tree

4 files changed

+65
-12
lines changed

4 files changed

+65
-12
lines changed

ChangeLog-12.1.md

+7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@
22

33
All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
44

5+
## [12.1.1] - 2025-MM-DD
6+
7+
### Fixed
8+
9+
* Child classes of child classes are not considered for `ClassesThatExtendClass` target
10+
511
## [12.1.0] - 2025-03-17
612

713
### Changed
814

915
* `CacheWarmer::warmCache()` now returns the number of cache hits and cache misses
1016

17+
[12.1.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/12.1.0...main
1118
[12.1.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/12.0.5...12.1.0

src/Target/MapBuilder.php

+41-11
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@
4040
*/
4141
public function build(Filter $filter, FileAnalyser $analyser): array
4242
{
43+
/**
44+
* @var array<non-empty-string, Class_> $classDetails
45+
*/
46+
$classDetails = [];
47+
4348
$namespaces = [];
4449
$classes = [];
45-
$classDetails = [];
4650
$classesThatExtendClass = [];
4751
$classesThatImplementInterface = [];
4852
$traits = [];
@@ -122,7 +126,7 @@ public function build(Filter $filter, FileAnalyser $analyser): array
122126
$this->processMethods($class, $file, $methods, $reverseLookup);
123127

124128
$classesThatExtendClass[$class->namespacedName()] = [];
125-
$classDetails[] = $class;
129+
$classDetails[$class->namespacedName()] = $class;
126130
}
127131

128132
foreach ($analyser->functionsIn($file) as $function) {
@@ -153,19 +157,15 @@ public function build(Filter $filter, FileAnalyser $analyser): array
153157
$this->process($classesThatImplementInterface, $interfaceName, $class->file(), $class->startLine(), $class->endLine());
154158
}
155159

156-
if (!$class->hasParent()) {
157-
continue;
158-
}
159-
160-
if (isset($classes[$class->parentClass()])) {
160+
foreach ($this->parentClasses($classDetails, $class) as $parentClass) {
161161
$classes[$class->namespacedName()] = array_merge_recursive(
162162
$classes[$class->namespacedName()],
163-
$classes[$class->parentClass()],
163+
$classes[$parentClass->namespacedName()],
164164
);
165-
}
166165

167-
if (isset($classesThatExtendClass[$class->parentClass()])) {
168-
$this->process($classesThatExtendClass, $class->parentClass(), $class->file(), $class->startLine(), $class->endLine());
166+
if (isset($classesThatExtendClass[$parentClass->namespacedName()])) {
167+
$this->process($classesThatExtendClass, $parentClass->namespacedName(), $class->file(), $class->startLine(), $class->endLine());
168+
}
169169
}
170170
}
171171

@@ -185,6 +185,15 @@ public function build(Filter $filter, FileAnalyser $analyser): array
185185
unset($classesThatExtendClass[$className]);
186186
}
187187

188+
/**
189+
* @todo Avoid duplication and remove this loop
190+
*/
191+
foreach (array_keys($classes) as $className) {
192+
foreach (array_keys($classes[$className]) as $file) {
193+
$classes[$className][$file] = array_unique($classes[$className][$file]);
194+
}
195+
}
196+
188197
return [
189198
'namespaces' => $namespaces,
190199
'traits' => $traits,
@@ -252,4 +261,25 @@ private function process(array &$data, string $unit, string $file, int $startLin
252261
range($startLine, $endLine),
253262
);
254263
}
264+
265+
/**
266+
* @param array<non-empty-string, Class_> $classDetails
267+
*
268+
* @return array<Class_>
269+
*/
270+
private function parentClasses(array $classDetails, Class_ $class): array
271+
{
272+
if (!$class->hasParent()) {
273+
return [];
274+
}
275+
276+
if (!isset($classDetails[$class->parentClass()])) {
277+
return [];
278+
}
279+
280+
return array_merge(
281+
[$classDetails[$class->parentClass()]],
282+
$this->parentClasses($classDetails, $classDetails[$class->parentClass()]),
283+
);
284+
}
255285
}

tests/tests/Target/MapBuilderTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ public static function provider(): array
375375
'classesThatExtendClass' => [
376376
GrandParentClass::class => [
377377
$parentClass => range(4, 9),
378+
$childClass => range(4, 9),
378379
],
379380
ParentClass::class => [
380381
$childClass => range(4, 9),

tests/tests/Target/MapperTest.php

+16-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use PHPUnit\Framework\TestCase;
2323
use SebastianBergmann\CodeCoverage\Filter;
2424
use SebastianBergmann\CodeCoverage\StaticAnalysis\ParsingFileAnalyser;
25+
use SebastianBergmann\CodeCoverage\TestFixture\Target\GrandParentClass;
2526
use SebastianBergmann\CodeCoverage\TestFixture\Target\Issue1066\DummyWithTrait;
2627
use SebastianBergmann\CodeCoverage\TestFixture\Target\TargetClass;
2728
use SebastianBergmann\CodeCoverage\TestFixture\Target\TargetEnumeration;
@@ -70,7 +71,7 @@ public static function provider(): array
7071
),
7172
],
7273

73-
'classes that extend class' => [
74+
'classes that extend class (parent and child)' => [
7475
[
7576
$file => range(33, 52),
7677
],
@@ -81,6 +82,20 @@ public static function provider(): array
8182
),
8283
],
8384

85+
'classes that extend class (grand parent, parent, and child)' => [
86+
[
87+
realpath(__DIR__ . '/../../_files/Target/GrandParentClass.php') => range(4, 9),
88+
realpath(__DIR__ . '/../../_files/Target/ParentClass.php') => range(4, 9),
89+
realpath(__DIR__ . '/../../_files/Target/ChildClass.php') => range(4, 9),
90+
],
91+
TargetCollection::fromArray(
92+
[
93+
Target::forClass(GrandParentClass::class),
94+
Target::forClassesThatExtendClass(GrandParentClass::class),
95+
],
96+
),
97+
],
98+
8499
'classes that implement interface' => [
85100
[
86101
$file => range(26, 31),

0 commit comments

Comments
 (0)