@@ -11,31 +11,37 @@ public extension Xccov.Converters {
11
11
enum CoberturaXml { }
12
12
}
13
13
14
- public extension Xccov . Converters . CoberturaXml {
14
+ extension XMLNode {
15
+ static func nodeAttribute( withName name: String , stringValue value: String ) -> XMLNode {
16
+ guard let attribute = XMLNode . attribute ( withName: name, stringValue: value) as? XMLNode else {
17
+ return XMLNode ( )
18
+ }
15
19
20
+ return attribute
21
+ }
22
+ }
23
+
24
+ public extension Xccov . Converters . CoberturaXml {
16
25
static func convert( coverageReport: CoverageReport ) -> Result < String , Xccov . Error > {
17
26
Self . convert ( coverageReport: coverageReport,
18
27
timeStamp: Date ( ) . timeIntervalSince1970,
19
28
currentDirectoryPath: FileManager . default. currentDirectoryPath)
20
29
}
21
30
31
+ //swiftlint:disable:next function_body_length
22
32
static func convert( coverageReport: CoverageReport ,
23
33
timeStamp: TimeInterval = Date ( ) . timeIntervalSince1970,
24
34
currentDirectoryPath: String = FileManager . default. currentDirectoryPath) -> Result < String , Xccov . Error > {
25
- let dtd = try ! XMLDTD ( contentsOf: URL ( string: " http://cobertura.sourceforge.net/xml/coverage-04.dtd " ) !)
35
+ guard
36
+ let dtdUrl = URL ( string: " http://cobertura.sourceforge.net/xml/coverage-04.dtd " ) ,
37
+ let dtd = try ? XMLDTD ( contentsOf: dtdUrl) else {
38
+ return . failure( . conversionFailed( " DTD could not be constructed " ) )
39
+ }
40
+
26
41
dtd. name = " coverage "
27
42
dtd. systemID = " http://cobertura.sourceforge.net/xml/coverage-04.dtd "
28
43
29
- let rootElement = XMLElement ( name: " coverage " )
30
- rootElement. addAttribute ( XMLNode . attribute ( withName: " line-rate " , stringValue: " \( coverageReport. lineCoverage) " ) as! XMLNode )
31
- rootElement. addAttribute ( XMLNode . attribute ( withName: " branch-rate " , stringValue: " 1.0 " ) as! XMLNode )
32
- rootElement. addAttribute ( XMLNode . attribute ( withName: " lines-covered " , stringValue: " \( coverageReport. coveredLines) " ) as! XMLNode )
33
- rootElement. addAttribute ( XMLNode . attribute ( withName: " lines-valid " , stringValue: " \( coverageReport. executableLines) " ) as! XMLNode )
34
- rootElement. addAttribute ( XMLNode . attribute ( withName: " timestamp " , stringValue: " \( timeStamp) " ) as! XMLNode )
35
- rootElement. addAttribute ( XMLNode . attribute ( withName: " version " , stringValue: " diff_coverage 0.1 " ) as! XMLNode )
36
- rootElement. addAttribute ( XMLNode . attribute ( withName: " complexity " , stringValue: " 0.0 " ) as! XMLNode )
37
- rootElement. addAttribute ( XMLNode . attribute ( withName: " branches-valid " , stringValue: " 1.0 " ) as! XMLNode )
38
- rootElement. addAttribute ( XMLNode . attribute ( withName: " branches-covered " , stringValue: " 1.0 " ) as! XMLNode )
44
+ let rootElement = Self . makeRootElement ( coverageReport: coverageReport, timeStamp: timeStamp)
39
45
40
46
let doc = XMLDocument ( rootElement: rootElement)
41
47
doc. version = " 1.0 "
@@ -48,7 +54,7 @@ public extension Xccov.Converters.CoberturaXml {
48
54
49
55
let packagesElement = XMLElement ( name: " packages " )
50
56
rootElement. addChild ( packagesElement)
51
-
57
+
52
58
// Sort files to avoid duplicated packages
53
59
let allFiles = coverageReport. targets. flatMap { $0. files } . sorted { $0. path > $1. path }
54
60
@@ -71,30 +77,32 @@ public extension Xccov.Converters.CoberturaXml {
71
77
72
78
currentPackage = packageName
73
79
if isNewPackage {
74
- currentPackageElement. addAttribute ( XMLNode . attribute ( withName: " name " , stringValue: packageName) as! XMLNode )
75
- currentPackageElement. addAttribute ( XMLNode . attribute ( withName: " line-rate " , stringValue: " \( fileCoverageReport. lineCoverage) " ) as! XMLNode )
76
- currentPackageElement. addAttribute ( XMLNode . attribute ( withName: " branch-rate " , stringValue: " 1.0 " ) as! XMLNode )
77
- currentPackageElement. addAttribute ( XMLNode . attribute ( withName: " complexity " , stringValue: " 0.0 " ) as! XMLNode )
80
+ currentPackageElement. addAttribute ( XMLNode . nodeAttribute ( withName: " name " , stringValue: packageName) )
81
+ currentPackageElement. addAttribute ( XMLNode . nodeAttribute ( withName: " line-rate " , stringValue: " \( fileCoverageReport. lineCoverage) " ) )
82
+ currentPackageElement. addAttribute ( XMLNode . nodeAttribute ( withName: " branch-rate " , stringValue: " 1.0 " ) )
83
+ currentPackageElement. addAttribute ( XMLNode . nodeAttribute ( withName: " complexity " , stringValue: " 0.0 " ) )
78
84
}
79
85
80
86
let classElement = XMLElement ( name: " class " )
81
- classElement. addAttribute ( XMLNode . attribute ( withName: " name " , stringValue: " \( packageName) . \( ( fileCoverageReport. name as NSString ) . deletingPathExtension) " ) as! XMLNode )
82
- classElement. addAttribute ( XMLNode . attribute ( withName: " filename " , stringValue: " \( filePath) " ) as! XMLNode )
83
- classElement. addAttribute ( XMLNode . attribute ( withName: " line-rate " , stringValue: " \( fileCoverageReport. lineCoverage) " ) as! XMLNode )
84
- classElement. addAttribute ( XMLNode . attribute ( withName: " branch-rate " , stringValue: " 1.0 " ) as! XMLNode )
85
- classElement. addAttribute ( XMLNode . attribute ( withName: " complexity " , stringValue: " 0.0 " ) as! XMLNode )
87
+ classElement. addAttribute ( XMLNode . nodeAttribute ( withName: " name " ,
88
+ stringValue: " \( packageName) . \( ( fileCoverageReport. name as NSString ) . deletingPathExtension) " ) )
89
+ classElement. addAttribute ( XMLNode . nodeAttribute ( withName: " filename " , stringValue: " \( filePath) " ) )
90
+ classElement. addAttribute ( XMLNode . nodeAttribute ( withName: " line-rate " , stringValue: " \( fileCoverageReport. lineCoverage) " ) )
91
+ classElement. addAttribute ( XMLNode . nodeAttribute ( withName: " branch-rate " , stringValue: " 1.0 " ) )
92
+ classElement. addAttribute ( XMLNode . nodeAttribute ( withName: " complexity " , stringValue: " 0.0 " ) )
86
93
currentPackageElement. addChild ( classElement)
87
94
88
95
let linesElement = XMLElement ( name: " lines " )
89
96
classElement. addChild ( linesElement)
90
97
91
98
for functionCoverageReport in fileCoverageReport. functions {
92
99
for index in 0 ..< functionCoverageReport. executableLines {
93
- // Function coverage report won't be 100% reliable without parsing it by file (would need to use xccov view --file filePath currentDirectory + Build/Logs/Test/*.xccovarchive)
100
+ // Function coverage report won't be 100% reliable without parsing it by file
101
+ // (would need to use xccov view --file filePath currentDirectory + Build/Logs/Test/*.xccovarchive)
94
102
let lineElement = XMLElement ( kind: . element, options: . nodeCompactEmptyElement)
95
103
lineElement. name = " line "
96
- lineElement. addAttribute ( XMLNode . attribute ( withName: " number " , stringValue: " \( functionCoverageReport. lineNumber + index) " ) as! XMLNode )
97
- lineElement. addAttribute ( XMLNode . attribute ( withName: " branch " , stringValue: " false " ) as! XMLNode )
104
+ lineElement. addAttribute ( XMLNode . nodeAttribute ( withName: " number " , stringValue: " \( functionCoverageReport. lineNumber + index) " ) )
105
+ lineElement. addAttribute ( XMLNode . nodeAttribute ( withName: " branch " , stringValue: " false " ) )
98
106
99
107
let lineHits : Int
100
108
if index < functionCoverageReport. coveredLines {
@@ -103,12 +111,27 @@ public extension Xccov.Converters.CoberturaXml {
103
111
lineHits = 0
104
112
}
105
113
106
- lineElement. addAttribute ( XMLNode . attribute ( withName: " hits " , stringValue: " \( lineHits) " ) as! XMLNode )
114
+ lineElement. addAttribute ( XMLNode . nodeAttribute ( withName: " hits " , stringValue: " \( lineHits) " ) )
107
115
linesElement. addChild ( lineElement)
108
116
}
109
117
}
110
118
}
111
119
112
120
return . success( doc. xmlString ( options: [ . nodePrettyPrint] ) )
113
121
}
122
+
123
+ static func makeRootElement( coverageReport: CoverageReport , timeStamp: TimeInterval ) -> XMLElement {
124
+ let rootElement = XMLElement ( name: " coverage " )
125
+ rootElement. addAttribute ( XMLNode . nodeAttribute ( withName: " line-rate " , stringValue: " \( coverageReport. lineCoverage) " ) )
126
+ rootElement. addAttribute ( XMLNode . nodeAttribute ( withName: " branch-rate " , stringValue: " 1.0 " ) )
127
+ rootElement. addAttribute ( XMLNode . nodeAttribute ( withName: " lines-covered " , stringValue: " \( coverageReport. coveredLines) " ) )
128
+ rootElement. addAttribute ( XMLNode . nodeAttribute ( withName: " lines-valid " , stringValue: " \( coverageReport. executableLines) " ) )
129
+ rootElement. addAttribute ( XMLNode . nodeAttribute ( withName: " timestamp " , stringValue: " \( timeStamp) " ) )
130
+ rootElement. addAttribute ( XMLNode . nodeAttribute ( withName: " version " , stringValue: " diff_coverage 0.1 " ) )
131
+ rootElement. addAttribute ( XMLNode . nodeAttribute ( withName: " complexity " , stringValue: " 0.0 " ) )
132
+ rootElement. addAttribute ( XMLNode . nodeAttribute ( withName: " branches-valid " , stringValue: " 1.0 " ) )
133
+ rootElement. addAttribute ( XMLNode . nodeAttribute ( withName: " branches-covered " , stringValue: " 1.0 " ) )
134
+
135
+ return rootElement
136
+ }
114
137
}
0 commit comments