@@ -102,6 +102,11 @@ class PHP_CodeCoverage
102102 */
103103 private $ tests = [];
104104
105+ /**
106+ * @var string[]
107+ */
108+ private $ unintentionallyCoveredSubclassesWhitelist = [];
109+
105110 /**
106111 * Constructor.
107112 *
@@ -547,6 +552,15 @@ public function setIgnoreDeprecatedCode($flag)
547552 $ this ->ignoreDeprecatedCode = $ flag ;
548553 }
549554
555+ /**
556+ * @param array $whitelist
557+ * @since Method available since Release 3.3.0
558+ */
559+ public function setUnintentionallyCoveredSubclassesWhitelist (array $ whitelist )
560+ {
561+ $ this ->unintentionallyCoveredSubclassesWhitelist = $ whitelist ;
562+ }
563+
550564 /**
551565 * Applies the @covers annotation filtering.
552566 *
@@ -905,10 +919,9 @@ private function performUnintentionallyCoveredCodeCheck(array &$data, array $lin
905919 }
906920 }
907921
908- if (!empty ($ unintentionallyCoveredUnits )) {
909- $ unintentionallyCoveredUnits = array_unique ($ unintentionallyCoveredUnits );
910- sort ($ unintentionallyCoveredUnits );
922+ $ unintentionallyCoveredUnits = $ this ->processUnintentionallyCoveredUnits ($ unintentionallyCoveredUnits );
911923
924+ if (!empty ($ unintentionallyCoveredUnits )) {
912925 throw new PHP_CodeCoverage_UnintentionallyCoveredCodeException (
913926 $ unintentionallyCoveredUnits
914927 );
@@ -1017,4 +1030,34 @@ private function selectDriver()
10171030 return new PHP_CodeCoverage_Driver_Xdebug ;
10181031 }
10191032 }
1033+
1034+ /**
1035+ * @param array $unintentionallyCoveredUnits
1036+ *
1037+ * @return array
1038+ */
1039+ private function processUnintentionallyCoveredUnits (array $ unintentionallyCoveredUnits )
1040+ {
1041+ $ unintentionallyCoveredUnits = array_unique ($ unintentionallyCoveredUnits );
1042+ sort ($ unintentionallyCoveredUnits );
1043+
1044+ foreach (array_keys ($ unintentionallyCoveredUnits ) as $ k => $ v ) {
1045+ $ unit = explode (':: ' , $ unintentionallyCoveredUnits [$ k ]);
1046+
1047+ if (count ($ unit ) != 2 ) {
1048+ continue ;
1049+ }
1050+
1051+ $ class = new ReflectionClass ($ unit [0 ]);
1052+
1053+ foreach ($ this ->unintentionallyCoveredSubclassesWhitelist as $ whitelisted ) {
1054+ if ($ class ->isSubclassOf ($ whitelisted )) {
1055+ unset($ unintentionallyCoveredUnits [$ k ]);
1056+ break ;
1057+ }
1058+ }
1059+ }
1060+
1061+ return array_values ($ unintentionallyCoveredUnits );
1062+ }
10201063}
0 commit comments