@@ -19,22 +19,32 @@ class MetricsFactory
19
19
*
20
20
* @param DOMDocument[] $documents
21
21
*
22
- * @return FileMetric[]
22
+ * @return array<string, FileMetric>
23
23
*/
24
24
public static function getFilesMetrics (array $ documents ): array
25
25
{
26
+ /** @var array<string, FileMetric> $metrics */
26
27
$ metrics = [];
27
28
28
29
foreach ($ documents as $ document ) {
29
30
$ foundMetrics = self ::getFileMetrics ($ document );
30
31
foreach ($ foundMetrics as $ metric ) {
31
- if (isset ($ metrics [$ metric ->getFilepath ()])) {
32
- $ previousMetric = $ metrics [$ metric ->getFilepath ()];
33
- if ($ previousMetric ->getCoverage () > $ metric ->getCoverage ()) {
34
- continue ;
35
- }
32
+ $ existingMetric = $ metrics [$ metric ->getFilepath ()] ?? null ;
33
+ if ($ existingMetric === null ) {
34
+ $ metrics [$ metric ->getFilepath ()] = $ metric ;
35
+ continue ;
36
36
}
37
- $ metrics [$ metric ->getFilepath ()] = $ metric ;
37
+
38
+ if ($ existingMetric ->getCoverage () === 100.0 ) {
39
+ continue ;
40
+ }
41
+
42
+ if ($ metric ->getCoverage () === 100.0 ) {
43
+ $ metrics [$ metric ->getFilepath ()] = $ metric ;
44
+ continue ;
45
+ }
46
+
47
+ self ::mergeFileMetrics ($ existingMetric , $ metric );
38
48
}
39
49
}
40
50
@@ -44,7 +54,7 @@ public static function getFilesMetrics(array $documents): array
44
54
/**
45
55
* Get metrics information from coverage.xml file
46
56
*
47
- * @return FileMetric[]
57
+ * @return array<string, FileMetric>
48
58
*/
49
59
public static function getFileMetrics (DOMDocument $ document ): array
50
60
{
@@ -72,14 +82,16 @@ public static function getFileMetrics(DOMDocument $document): array
72
82
// gather metrics per method
73
83
$ methodMetrics = self ::getMethodMetrics ($ xpath , $ parentNode );
74
84
75
- $ metrics [] = new FileMetric ($ filename , $ coveragePercentage , $ methodMetrics );
85
+ $ coveredStatements = self ::getCoveredStatements ($ xpath , $ parentNode );
86
+
87
+ $ metrics [$ filename ] = new FileMetric ($ filename , $ statements , $ coveragePercentage , $ methodMetrics , $ coveredStatements );
76
88
}
77
89
78
90
return $ metrics ;
79
91
}
80
92
81
93
/**
82
- * @return MethodMetric[]
94
+ * @return array<string, MethodMetric>
83
95
*/
84
96
public static function getMethodMetrics (DOMXPath $ xpath , DOMNode $ fileNode ): array
85
97
{
@@ -95,9 +107,54 @@ public static function getMethodMetrics(DOMXPath $xpath, DOMNode $fileNode): arr
95
107
$ lineNumber = (int )XMLUtil::getAttribute ($ methodNode , 'num ' );
96
108
$ count = (int )XMLUtil::getAttribute ($ methodNode , 'count ' );
97
109
98
- $ metrics [] = new MethodMetric ($ methodName , $ lineNumber , $ count );
110
+ $ metrics [$ methodName ] = new MethodMetric ($ methodName , $ lineNumber , $ count );
99
111
}
100
112
101
113
return $ metrics ;
102
114
}
115
+
116
+ /**
117
+ * @return int[]
118
+ */
119
+ private static function getCoveredStatements (DOMXPath $ xpath , DOMNode $ fileNode ): array
120
+ {
121
+ $ statementNodes = $ xpath ->query ('line[@type="stmt"] ' , $ fileNode );
122
+ if ($ statementNodes === false || count ($ statementNodes ) === 0 ) {
123
+ return [];
124
+ }
125
+
126
+ $ coveredStatements = [];
127
+ foreach ($ statementNodes as $ node ) {
128
+ $ count = (int )XMLUtil::getAttribute ($ node , 'count ' );
129
+ if ($ count === 0 ) {
130
+ continue ;
131
+ }
132
+ $ lineNumber = (int )XMLUtil::getAttribute ($ node , 'num ' );
133
+
134
+ $ coveredStatements [] = $ lineNumber ;
135
+ }
136
+
137
+ return $ coveredStatements ;
138
+ }
139
+
140
+ private static function mergeFileMetrics (FileMetric $ existingMetric , FileMetric $ metric ): void
141
+ {
142
+ $ existingMetricMethods = $ existingMetric ->getMethods ();
143
+ $ metricMethods = $ metric ->getMethods ();
144
+ foreach ($ metricMethods as $ methodName => $ methodMetric ) {
145
+ if (isset ($ existingMetricMethods [$ methodName ]) === false || $ existingMetricMethods [$ methodName ]->getCount () < $ methodMetric ->getCount ()) {
146
+ $ existingMetricMethods [$ methodName ] = $ methodMetric ;
147
+ }
148
+ }
149
+
150
+ $ existingCovered = $ existingMetric ->getCoveredStatements ();
151
+ $ metricCovered = $ metric ->getCoveredStatements ();
152
+ $ existingMetric ->setCoveredStatements (array_merge ($ existingCovered , array_diff ($ metricCovered , $ existingCovered )));
153
+ $ existingMetric ->setMethods ($ existingMetricMethods );
154
+ $ coveragePercentage = round (
155
+ count ($ existingMetric ->getCoveredStatements ()) / $ existingMetric ->getStatements () * 100 ,
156
+ self ::COVERAGE_PERCENTAGE_PRECISION
157
+ );
158
+ $ existingMetric ->setCoverage ($ coveragePercentage );
159
+ }
103
160
}
0 commit comments