@@ -44,9 +44,17 @@ type coverage_level_type =
4444 | 'stmt+decision'
4545 | 'stmt+mcdc'
4646 | 'stmt+uc_mcdc' ;
47+
4748type sources_type = {
48- source : source_type [ ] ;
49+ source ?: source_type [ ] ;
50+ 'xi:include' : xi_include_type [ ] ;
51+ } ;
52+
53+ type xi_include_type = {
54+ '@_parse' : string ;
55+ '@_href' : string ;
4956} ;
57+
5058type source_type = {
5159 '@_file' : string ;
5260 '@_coverage_level' : coverage_level_type ;
@@ -102,7 +110,34 @@ type statement_type = {
102110 '@_id' : number ;
103111 '@_text' : string ;
104112} ;
113+
114+ /**
115+ *
116+ * . | No coverage obligation is attached to the line
117+ *
118+ * - | Coverage obligations attached to the line, none satisfied
119+ * ! | Coverage obligations attached to the line, some satisfied
120+ * ? | Coverage obligations attached to the line, undetermined coverage state
121+ * | (in the absence of other violations)
122+ * + | Coverage obligations attached to the line, all satisfied
123+ *
124+ * # | Zero violations in exempted region
125+ * * | One violation in exempted region
126+ * \@ | Also related to exemptions, unclear semantics
127+ *
128+ * 0 | not coverable code, only relevant in binary traces mode (no
129+ * | instrumentation) which is unsupported in VS Code
130+ *
131+ * v, \> | symbols for object level coverage which is not supported in VS
132+ * | Code. We only support source level coverage.
133+ * See
134+ * https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#annotated-sources-text-xcov
135+ * and
136+ * https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/exemptions.html#reporting-about-coverage-exemptions
137+ * for more information.
138+ */
105139type coverage_type = '.' | '+' | '-' | '!' | '?' | '#' | '@' | '*' | '0' | 'v' | '>' ;
140+
106141type decision_type = {
107142 src ?: src_type ;
108143 condition : condition_type [ ] ;
@@ -159,3 +194,40 @@ export function parseGnatcovIndexXml(path: string): CovIndex {
159194 throw Error ( `Could not parse GNATcoverage report: ${ path } ` ) ;
160195 }
161196}
197+
198+ /**
199+ *
200+ * @param path - path to GNATcoverage <source-file>.xml report
201+ * @returns parsed report
202+ */
203+ export function parseGnatcovFileXml ( path : string ) : source_type {
204+ const fileContentAsBuffer = fs . readFileSync ( path ) ;
205+
206+ const options : Partial < X2jOptions > = {
207+ // By default the parser ignores attributes, so we set this option
208+ // to obtain attributes.
209+ ignoreAttributes : false ,
210+ // This prefix is used in the JS objects resulting from the parsing
211+ // to differentiate attributes from child nodes.
212+ attributeNamePrefix : '@_' ,
213+ isArray : ( _ , jPath ) => {
214+ return ( [ 'source.src_mapping.src.line' ] as string [ ] ) . indexOf ( jPath ) !== - 1 ;
215+ } ,
216+ /**
217+ * By default, attribute values are trimmed from leading and trailing
218+ * whitespace. GNATcov stores the content of source code lines in XML
219+ * attributes so we don't want to trim in order to preserve the
220+ * original content.
221+ */
222+ trimValues : false ,
223+ } ;
224+ const parser = new XMLParser ( options ) ;
225+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
226+ const parseResult = parser . parse ( fileContentAsBuffer ) ;
227+ if ( 'source' in parseResult ) {
228+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
229+ return parseResult . source as source_type ;
230+ } else {
231+ throw Error ( `Could not parse GNATcoverage report: ${ path } ` ) ;
232+ }
233+ }
0 commit comments