2121use function strlen ;
2222use function substr ;
2323use DateTimeImmutable ;
24- use DOMDocument ;
2524use SebastianBergmann \CodeCoverage \CodeCoverage ;
2625use SebastianBergmann \CodeCoverage \Data \ProcessedClassType ;
2726use SebastianBergmann \CodeCoverage \Data \ProcessedFunctionType ;
3130use SebastianBergmann \CodeCoverage \Node \File as FileNode ;
3231use SebastianBergmann \CodeCoverage \PathExistsButIsNotDirectoryException ;
3332use SebastianBergmann \CodeCoverage \Util \Filesystem ;
34- use SebastianBergmann \CodeCoverage \Util \Xml ;
3533use SebastianBergmann \CodeCoverage \Version ;
3634use SebastianBergmann \CodeCoverage \WriteOperationFailedException ;
3735use SebastianBergmann \CodeCoverage \XmlException ;
3836use SebastianBergmann \Environment \Runtime ;
37+ use XMLWriter ;
3938
4039/**
4140 * @phpstan-import-type TestType from CodeCoverage
@@ -68,15 +67,21 @@ public function process(CodeCoverage $coverage, string $target): void
6867
6968 $ report = $ coverage ->getReport ();
7069
70+ $ writer = new XMLWriter ;
71+ $ writer ->openUri ($ this ->targetFilePath ('index ' ));
72+ $ writer ->setIndent (true );
73+ $ writer ->setIndentString (' ' );
7174 $ this ->project = new Project (
75+ $ writer ,
7276 $ coverage ->getReport ()->name (),
7377 );
7478
7579 $ this ->setBuildInformation ();
80+
81+ $ this ->project ->startProject ();
7682 $ this ->processTests ($ coverage ->getTests ());
7783 $ this ->processDirectory ($ report , $ this ->project );
78-
79- $ this ->saveDocument ($ this ->project ->asDom (), 'index ' );
84+ $ this ->project ->finalize ();
8085 }
8186
8287 private function setBuildInformation (): void
@@ -121,7 +126,10 @@ private function processDirectory(DirectoryNode $directory, Node $context): void
121126 $ directoryName = '/ ' ;
122127 }
123128
124- $ directoryObject = $ context ->addDirectory ($ directoryName );
129+ $ writer = $ this ->project ->getWriter ();
130+ $ writer ->startElement ('directory ' );
131+ $ writer ->writeAttribute ('name ' , $ directoryName );
132+ $ directoryObject = $ context ->addDirectory ();
125133
126134 $ this ->setTotals ($ directory , $ directoryObject ->totals ());
127135
@@ -132,27 +140,35 @@ private function processDirectory(DirectoryNode $directory, Node $context): void
132140 foreach ($ directory ->files () as $ node ) {
133141 $ this ->processFile ($ node , $ directoryObject );
134142 }
143+ $ writer ->endElement ();
135144 }
136145
137146 /**
138147 * @throws XmlException
139148 */
140149 private function processFile (FileNode $ file , Directory $ context ): void
141150 {
142- $ fileObject = $ context ->addFile (
143- $ file ->name (),
144- $ file ->id () . '.xml ' ,
145- $ file ->sha1 (),
146- );
151+ $ context ->getWriter ()->startElement ('file ' );
152+ $ context ->getWriter ()->writeAttribute ('name ' , $ file ->name ());
153+ $ context ->getWriter ()->writeAttribute ('href ' , $ file ->id () . '.xml ' );
154+ $ context ->getWriter ()->writeAttribute ('hash ' , $ file ->sha1 ());
155+
156+ $ fileObject = $ context ->addFile ();
147157
148158 $ this ->setTotals ($ file , $ fileObject ->totals ());
149159
160+ $ context ->getWriter ()->endElement ();
161+
150162 $ path = substr (
151163 $ file ->pathAsString (),
152164 strlen ($ this ->project ->projectSourceDirectory ()),
153165 );
154166
155- $ fileReport = new Report ($ path , $ file ->sha1 ());
167+ $ writer = new XMLWriter ;
168+ $ writer ->openUri ($ this ->targetFilePath ($ file ->id ()));
169+ $ writer ->setIndent (true );
170+ $ writer ->setIndentString (' ' );
171+ $ fileReport = new Report ($ writer , $ path , $ file ->sha1 ());
156172
157173 $ this ->setTotals ($ file , $ fileReport ->totals ());
158174
@@ -164,6 +180,8 @@ private function processFile(FileNode $file, Directory $context): void
164180 $ this ->processFunction ($ function , $ fileReport );
165181 }
166182
183+ $ fileReport ->getWriter ()->startElement ('coverage ' );
184+
167185 foreach ($ file ->lineCoverageData () as $ line => $ tests ) {
168186 if (!is_array ($ tests ) || count ($ tests ) === 0 ) {
169187 continue ;
@@ -172,19 +190,22 @@ private function processFile(FileNode $file, Directory $context): void
172190 $ coverage = $ fileReport ->lineCoverage ((string ) $ line );
173191 $ coverage ->finalize ($ tests );
174192 }
193+ $ fileReport ->getWriter ()->endElement ();
175194
176195 if ($ this ->includeSource ) {
177196 $ fileReport ->source ()->setSourceCode (
178197 file_get_contents ($ file ->pathAsString ()),
179198 );
180199 }
181200
182- $ this -> saveDocument ( $ fileReport ->asDom (), $ file -> id () );
201+ $ fileReport ->finalize ( );
183202 }
184203
185204 private function processUnit (ProcessedClassType |ProcessedTraitType $ unit , Report $ report ): void
186205 {
187206 if ($ unit instanceof ProcessedClassType) {
207+ $ report ->getWriter ()->startElement ('class ' );
208+
188209 $ unitObject = $ report ->classObject (
189210 $ unit ->className ,
190211 $ unit ->namespace ,
@@ -194,6 +215,8 @@ private function processUnit(ProcessedClassType|ProcessedTraitType $unit, Report
194215 (float ) $ unit ->crap ,
195216 );
196217 } else {
218+ $ report ->getWriter ()->startElement ('trait ' );
219+
197220 $ unitObject = $ report ->traitObject (
198221 $ unit ->traitName ,
199222 $ unit ->namespace ,
@@ -205,6 +228,8 @@ private function processUnit(ProcessedClassType|ProcessedTraitType $unit, Report
205228 }
206229
207230 foreach ($ unit ->methods as $ method ) {
231+ $ report ->getWriter ()->startElement ('method ' );
232+
208233 $ unitObject ->addMethod (
209234 $ method ->methodName ,
210235 $ method ->signature ,
@@ -215,11 +240,17 @@ private function processUnit(ProcessedClassType|ProcessedTraitType $unit, Report
215240 (string ) $ method ->coverage ,
216241 $ method ->crap ,
217242 );
243+
244+ $ report ->getWriter ()->endElement ();
218245 }
246+
247+ $ report ->getWriter ()->endElement ();
219248 }
220249
221250 private function processFunction (ProcessedFunctionType $ function , Report $ report ): void
222251 {
252+ $ report ->getWriter ()->startElement ('function ' );
253+
223254 $ report ->functionObject (
224255 $ function ->functionName ,
225256 $ function ->signature ,
@@ -230,22 +261,30 @@ private function processFunction(ProcessedFunctionType $function, Report $report
230261 (string ) $ function ->coverage ,
231262 $ function ->crap ,
232263 );
264+
265+ $ report ->getWriter ()->endElement ();
233266 }
234267
235268 /**
236269 * @param array<string, TestType> $tests
237270 */
238271 private function processTests (array $ tests ): void
239272 {
273+ $ this ->project ->getWriter ()->startElement ('tests ' );
274+
240275 $ testsObject = $ this ->project ->tests ();
241276
242277 foreach ($ tests as $ test => $ result ) {
243278 $ testsObject ->addTest ($ test , $ result );
244279 }
280+
281+ $ this ->project ->getWriter ()->endElement ();
245282 }
246283
247284 private function setTotals (AbstractNode $ node , Totals $ totals ): void
248285 {
286+ $ totals ->getWriter ()->startElement ('totals ' );
287+
249288 $ loc = $ node ->linesOfCode ();
250289
251290 $ totals ->setNumLines (
@@ -256,6 +295,16 @@ private function setTotals(AbstractNode $node, Totals $totals): void
256295 $ node ->numberOfExecutedLines (),
257296 );
258297
298+ $ totals ->setNumMethods (
299+ $ node ->numberOfMethods (),
300+ $ node ->numberOfTestedMethods (),
301+ );
302+
303+ $ totals ->setNumFunctions (
304+ $ node ->numberOfFunctions (),
305+ $ node ->numberOfTestedFunctions (),
306+ );
307+
259308 $ totals ->setNumClasses (
260309 $ node ->numberOfClasses (),
261310 $ node ->numberOfTestedClasses (),
@@ -266,15 +315,7 @@ private function setTotals(AbstractNode $node, Totals $totals): void
266315 $ node ->numberOfTestedTraits (),
267316 );
268317
269- $ totals ->setNumMethods (
270- $ node ->numberOfMethods (),
271- $ node ->numberOfTestedMethods (),
272- );
273-
274- $ totals ->setNumFunctions (
275- $ node ->numberOfFunctions (),
276- $ node ->numberOfTestedFunctions (),
277- );
318+ $ totals ->getWriter ()->endElement ();
278319 }
279320
280321 private function targetDirectory (): string
@@ -290,12 +331,4 @@ private function targetFilePath(string $name): string
290331
291332 return $ filename ;
292333 }
293-
294- /**
295- * @throws XmlException
296- */
297- private function saveDocument (DOMDocument $ document , string $ name ): void
298- {
299- Filesystem::write ($ this ->targetFilePath ($ name ), Xml::asString ($ document ));
300- }
301334}
0 commit comments