2
2
using System . Collections . Generic ;
3
3
using System . IO ;
4
4
using System . Linq ;
5
+ using System . Text ;
5
6
using System . Xml ;
7
+ using System . Xml . Linq ;
6
8
7
9
namespace Coverlet . Core . Reporters
8
10
{
@@ -16,94 +18,140 @@ public string Report(CoverageResult result)
16
18
{
17
19
CoverageSummary summary = new CoverageSummary ( ) ;
18
20
19
- XmlDocument xml = new XmlDocument ( ) ;
20
- XmlElement coverage = xml . CreateElement ( "coverage" ) ;
21
- coverage . SetAttribute ( "line-rate" , summary . CalculateLineCoverage ( result . Modules ) . ToString ( ) ) ;
22
- coverage . SetAttribute ( "branch-rate" , summary . CalculateBranchCoverage ( result . Modules ) . ToString ( ) ) ;
23
- coverage . SetAttribute ( "version" , "1.9" ) ;
24
- coverage . SetAttribute ( "timestamp" , ( ( int ) ( DateTime . UtcNow - new DateTime ( 1970 , 1 , 1 ) ) . TotalSeconds ) . ToString ( ) ) ;
21
+ int totalLines = 0 , coveredLines = 0 , totalBranches = 0 , coveredBranches = 0 ;
25
22
26
- XmlElement sources = xml . CreateElement ( "sources" ) ;
27
- foreach ( var src in GetSources ( result . Modules ) )
28
- {
29
- XmlElement source = xml . CreateElement ( "source" ) ;
30
- source . AppendChild ( xml . CreateTextNode ( src ) ) ;
31
- sources . AppendChild ( source ) ;
32
- }
23
+ XDocument xml = new XDocument ( ) ;
24
+ XElement coverage = new XElement ( "coverage" ) ;
25
+ coverage . Add ( new XAttribute ( "line-rate" , summary . CalculateLineCoverage ( result . Modules ) . ToString ( ) ) ) ;
26
+ coverage . Add ( new XAttribute ( "branch-rate" , summary . CalculateBranchCoverage ( result . Modules ) . ToString ( ) ) ) ;
27
+ coverage . Add ( new XAttribute ( "version" , "1.9" ) ) ;
28
+ coverage . Add ( new XAttribute ( "timestamp" , ( ( int ) ( DateTime . UtcNow - new DateTime ( 1970 , 1 , 1 ) ) . TotalSeconds ) . ToString ( ) ) ) ;
29
+
30
+ XElement sources = new XElement ( "sources" ) ;
31
+ var basePath = GetBasePath ( result . Modules ) ;
32
+ sources . Add ( new XElement ( "source" , basePath ) ) ;
33
33
34
- XmlElement packages = xml . CreateElement ( "packages" ) ;
34
+ XElement packages = new XElement ( "packages" ) ;
35
35
foreach ( var module in result . Modules )
36
36
{
37
- XmlElement package = xml . CreateElement ( "package" ) ;
38
- package . SetAttribute ( "line-rate" , summary . CalculateLineCoverage ( module . Value ) . ToString ( ) ) ;
39
- package . SetAttribute ( "branch-rate" , summary . CalculateBranchCoverage ( module . Value ) . ToString ( ) ) ;
40
- package . SetAttribute ( "complexity" , "0" ) ;
37
+ XElement package = new XElement ( "package" ) ;
38
+ package . Add ( new XAttribute ( "name" , Path . GetFileNameWithoutExtension ( module . Key ) ) ) ;
39
+ package . Add ( new XAttribute ( "line-rate" , summary . CalculateLineCoverage ( module . Value ) . ToString ( ) ) ) ;
40
+ package . Add ( new XAttribute ( "branch-rate" , summary . CalculateBranchCoverage ( module . Value ) . ToString ( ) ) ) ;
41
+ package . Add ( new XAttribute ( "complexity" , "0" ) ) ;
41
42
42
- XmlElement classes = xml . CreateElement ( "classes" ) ;
43
+ XElement classes = new XElement ( "classes" ) ;
43
44
foreach ( var document in module . Value )
44
45
{
45
46
foreach ( var cls in document . Value )
46
47
{
47
- XmlElement @class = xml . CreateElement ( "class" ) ;
48
- @class . SetAttribute ( "name" , cls . Key ) ;
49
- @class . SetAttribute ( "filename" , Path . GetFileName ( document . Key ) ) ;
50
- @class . SetAttribute ( "line-rate" , summary . CalculateLineCoverage ( cls . Value ) . ToString ( ) ) ;
51
- @class . SetAttribute ( "branch-rate" , summary . CalculateBranchCoverage ( cls . Value ) . ToString ( ) ) ;
52
- @class . SetAttribute ( "complexity" , "0" ) ;
53
-
54
- XmlElement methods = xml . CreateElement ( "methods" ) ;
48
+ XElement @class = new XElement ( "class" ) ;
49
+ @class . Add ( new XAttribute ( "name" , cls . Key ) ) ;
50
+ @class . Add ( new XAttribute ( "filename" , GetRelativePathFromBase ( basePath , document . Key ) ) ) ;
51
+ @class . Add ( new XAttribute ( "line-rate" , summary . CalculateLineCoverage ( cls . Value ) . ToString ( ) ) ) ;
52
+ @class . Add ( new XAttribute ( "branch-rate" , summary . CalculateBranchCoverage ( cls . Value ) . ToString ( ) ) ) ;
53
+ @class . Add ( new XAttribute ( "complexity" , "0" ) ) ;
54
+
55
+ XElement classLines = new XElement ( "lines" ) ;
56
+ XElement methods = new XElement ( "methods" ) ;
57
+
55
58
foreach ( var meth in cls . Value )
56
59
{
57
- XmlElement method = xml . CreateElement ( "method" ) ;
58
- method . SetAttribute ( "name" , meth . Key . Split ( ':' ) [ 2 ] . Split ( '(' ) [ 0 ] ) ;
59
- method . SetAttribute ( "signature" , meth . Key ) ;
60
- method . SetAttribute ( "line-rate" , summary . CalculateLineCoverage ( meth . Value ) . ToString ( ) ) ;
61
- method . SetAttribute ( "branch-rate" , summary . CalculateBranchCoverage ( meth . Value ) . ToString ( ) ) ;
60
+ XElement method = new XElement ( "method" ) ;
61
+ method . Add ( new XAttribute ( "name" , meth . Key . Split ( ':' ) [ 2 ] . Split ( '(' ) [ 0 ] ) ) ;
62
+ method . Add ( new XAttribute ( "signature" , "(" + meth . Key . Split ( ':' ) [ 2 ] . Split ( '(' ) [ 1 ] ) ) ;
63
+ method . Add ( new XAttribute ( "line-rate" , summary . CalculateLineCoverage ( meth . Value ) . ToString ( ) ) ) ;
64
+ method . Add ( new XAttribute ( "branch-rate" , summary . CalculateBranchCoverage ( meth . Value ) . ToString ( ) ) ) ;
62
65
63
- XmlElement lines = xml . CreateElement ( "lines" ) ;
66
+ XElement lines = new XElement ( "lines" ) ;
64
67
foreach ( var ln in meth . Value )
65
68
{
66
- XmlElement line = xml . CreateElement ( "line" ) ;
67
- line . SetAttribute ( "number" , ln . Key . ToString ( ) ) ;
68
- line . SetAttribute ( "hits" , ln . Value . Hits . ToString ( ) ) ;
69
- line . SetAttribute ( "branch" , ln . Value . IsBranchPoint . ToString ( ) ) ;
69
+ XElement line = new XElement ( "line" ) ;
70
+ line . Add ( new XAttribute ( "number" , ln . Key . ToString ( ) ) ) ;
71
+ line . Add ( new XAttribute ( "hits" , ln . Value . Hits . ToString ( ) ) ) ;
72
+ line . Add ( new XAttribute ( "branch" , ln . Value . IsBranchPoint . ToString ( ) ) ) ;
73
+
74
+ totalLines ++ ;
75
+ if ( ln . Value . Hits > 0 ) coveredLines ++ ;
76
+
77
+
78
+ if ( ln . Value . IsBranchPoint )
79
+ {
80
+ line . Add ( new XAttribute ( "condition-coverage" , "100% (1/1)" ) ) ;
81
+ XElement conditions = new XElement ( "conditions" ) ;
82
+ XElement condition = new XElement ( "condition" ) ;
83
+ condition . Add ( new XAttribute ( "number" , "0" ) ) ;
84
+ condition . Add ( new XAttribute ( "type" , "jump" ) ) ;
85
+ condition . Add ( new XAttribute ( "coverage" , "100%" ) ) ;
86
+
87
+ totalBranches ++ ;
88
+ if ( ln . Value . Hits > 0 ) coveredBranches ++ ;
89
+
90
+ conditions . Add ( condition ) ;
91
+ line . Add ( conditions ) ;
92
+ }
70
93
71
- lines . AppendChild ( line ) ;
94
+
95
+ lines . Add ( line ) ;
96
+ classLines . Add ( line ) ;
72
97
}
73
98
74
- method . AppendChild ( lines ) ;
75
- methods . AppendChild ( method ) ;
99
+ method . Add ( lines ) ;
100
+ methods . Add ( method ) ;
76
101
}
77
102
78
- @class . AppendChild ( methods ) ;
79
- classes . AppendChild ( @class ) ;
103
+ @class . Add ( methods ) ;
104
+ @class . Add ( classLines ) ;
105
+ classes . Add ( @class ) ;
80
106
}
81
107
}
82
108
83
- package . AppendChild ( classes ) ;
84
- packages . AppendChild ( package ) ;
109
+ package . Add ( classes ) ;
110
+ packages . Add ( package ) ;
85
111
}
86
112
87
- coverage . AppendChild ( sources ) ;
88
- coverage . AppendChild ( packages ) ;
89
- xml . AppendChild ( coverage ) ;
113
+ coverage . Add ( new XAttribute ( "lines-covered" , coveredLines . ToString ( ) ) ) ;
114
+ coverage . Add ( new XAttribute ( "lines-valid" , totalLines . ToString ( ) ) ) ;
115
+ coverage . Add ( new XAttribute ( "branches-covered" , coveredBranches . ToString ( ) ) ) ;
116
+ coverage . Add ( new XAttribute ( "branches-valid" , totalBranches . ToString ( ) ) ) ;
117
+
118
+ coverage . Add ( sources ) ;
119
+ coverage . Add ( packages ) ;
120
+ xml . Add ( coverage ) ;
90
121
91
- StringWriter writer = new StringWriter ( ) ;
92
- xml . Save ( writer ) ;
122
+ var stream = new MemoryStream ( ) ;
123
+ xml . Save ( stream ) ;
93
124
94
- return writer . ToString ( ) ;
125
+ return Encoding . UTF8 . GetString ( stream . ToArray ( ) ) ;
95
126
}
96
127
97
- private string [ ] GetSources ( Modules modules )
128
+ private string GetBasePath ( Modules modules )
98
129
{
99
130
List < string > sources = new List < string > ( ) ;
131
+ string source = string . Empty ;
132
+
100
133
foreach ( var module in modules )
101
134
{
102
135
sources . AddRange (
103
136
module . Value . Select ( d => Path . GetDirectoryName ( d . Key ) ) ) ;
104
137
}
105
138
106
- return sources . Distinct ( ) . ToArray ( ) ;
139
+ sources = sources . Distinct ( ) . ToList ( ) ;
140
+ var segments = sources [ 0 ] . Split ( Path . DirectorySeparatorChar ) ;
141
+
142
+ foreach ( var segment in segments )
143
+ {
144
+ var startsWith = sources . All ( s => s . StartsWith ( source + segment ) ) ;
145
+ if ( ! startsWith )
146
+ break ;
147
+
148
+ source += segment + Path . DirectorySeparatorChar ;
149
+ }
150
+
151
+ return source ;
107
152
}
153
+
154
+ private string GetRelativePathFromBase ( string source , string path )
155
+ => path . Replace ( source , string . Empty ) ;
108
156
}
109
157
}
0 commit comments