@@ -38290,6 +38290,15 @@ const isValidCoverageContent = (data) => {
3829038290 return wordsToInclude.every((w) => data.includes(w));
3829138291};
3829238292
38293+ // return true if coverage data includes branch coverage columns
38294+ const hasBranchCoverage = (data) => {
38295+ if (!data || !data.length) {
38296+ return false;
38297+ }
38298+
38299+ return data.includes('Branch') && data.includes('BrPart');
38300+ };
38301+
3829338302// return full html coverage report and coverage percentage
3829438303const getCoverageReport = (options) => {
3829538304 const { covFile, covXmlFile } = options;
@@ -38351,8 +38360,9 @@ const getTotal = (data) => {
3835138360
3835238361 const lines = data.split('\n');
3835338362 const line = lines.find((l) => l.includes('TOTAL '));
38363+ const hasBranch = hasBranchCoverage(data);
3835438364
38355- return parseTotalLine(line);
38365+ return parseTotalLine(line, hasBranch );
3835638366};
3835738367
3835838368// get number of warnings from coverage-file
@@ -38374,14 +38384,15 @@ const getWarnings = (data) => {
3837438384};
3837538385
3837638386// parse one line from coverage-file
38377- const parseOneLine = (line) => {
38387+ const parseOneLine = (line, hasBranch = false ) => {
3837838388 if (!line) {
3837938389 return null;
3838038390 }
3838138391
3838238392 const parsedLine = line.split(' ').filter((l) => l);
38393+ const minCols = hasBranch ? 6 : 4;
3838338394
38384- if (parsedLine.length < 4 ) {
38395+ if (parsedLine.length < minCols ) {
3838538396 return null;
3838638397 }
3838738398
@@ -38395,33 +38406,48 @@ const parseOneLine = (line) => {
3839538406 : parsedLine[parsedLine.length - 1] &&
3839638407 parsedLine[parsedLine.length - 1].split(', ');
3839738408
38398- return {
38409+ const result = {
3839938410 name: parsedLine[0],
3840038411 stmts: parsedLine[1].trim(),
3840138412 miss: parsedLine[2].trim(),
3840238413 cover,
3840338414 missing,
3840438415 };
38416+
38417+ if (hasBranch) {
38418+ result.branch = parsedLine[3].trim();
38419+ result.brpart = parsedLine[4].trim();
38420+ }
38421+
38422+ return result;
3840538423};
3840638424
3840738425// parse total line from coverage-file
38408- const parseTotalLine = (line) => {
38426+ const parseTotalLine = (line, hasBranch = false ) => {
3840938427 if (!line) {
3841038428 return null;
3841138429 }
3841238430
3841338431 const parsedLine = line.split(' ').filter((l) => l);
38432+ const minCols = hasBranch ? 6 : 4;
3841438433
38415- if (parsedLine.length < 4 ) {
38434+ if (parsedLine.length < minCols ) {
3841638435 return null;
3841738436 }
3841838437
38419- return {
38438+ const result = {
3842038439 name: parsedLine[0],
3842138440 stmts: parsedLine[1].trim(),
3842238441 miss: parsedLine[2].trim(),
3842338442 cover: parsedLine[parsedLine.length - 1].trim(),
3842438443 };
38444+
38445+ if (hasBranch) {
38446+ result.branch = parsedLine[3].trim();
38447+ result.brpart = parsedLine[4].trim();
38448+ }
38449+
38450+ return result;
3842538451};
3842638452
3842738453// parse coverage-file
@@ -38432,7 +38458,9 @@ const parse = (data) => {
3843238458 return null;
3843338459 }
3843438460
38435- return actualLines.map(parseOneLine);
38461+ const hasBranch = hasBranchCoverage(data);
38462+
38463+ return actualLines.map((line) => parseOneLine(line, hasBranch));
3843638464};
3843738465
3843838466// collapse all lines to folders structure
@@ -38499,6 +38527,7 @@ const toTable = (data, options, dataFromXml = null) => {
3849938527 }
3850038528 const totalLine = dataFromXml ? dataFromXml.total : getTotal(data);
3850138529 options.hasMissing = coverage.some((c) => c.missing);
38530+ options.hasBranch = coverage.some((c) => c.branch !== undefined);
3850238531
3850338532 core.info(`Generating coverage report`);
3850438533 const headTr = toHeadRow(options);
@@ -38545,9 +38574,11 @@ const toTable = (data, options, dataFromXml = null) => {
3854538574
3854638575// make html head row - th
3854738576const toHeadRow = (options) => {
38548- const lastTd = options.hasMissing ? '<th>Missing</th>' : '';
38577+ const branchTh = options.hasBranch ? '<th>Branch</th><th>BrPart</th>' : '';
38578+ const missingTh = options.hasMissing ? '<th>Missing</th>' : '';
3854938579
38550- return `<tr><th>File</th><th>Stmts</th><th>Miss</th><th>Cover</th>${lastTd}</tr>`;
38580+ // prettier-ignore
38581+ return `<tr><th>File</th><th>Stmts</th><th>Miss</th>${branchTh}<th>Cover</th>${missingTh}</tr>`;
3855138582};
3855238583
3855338584// make html row - tr
@@ -38556,17 +38587,26 @@ const toRow = (item, indent = false, options) => {
3855638587
3855738588 const name = toFileNameTd(item, indent, options);
3855838589 const missing = toMissingTd(item, options);
38559- const lastTd = options.hasMissing ? `<td>${missing}</td>` : '';
38590+ const branchTd = options.hasBranch
38591+ ? `<td>${item.branch || 0}</td><td>${item.brpart || 0}</td>`
38592+ : '';
38593+ const missingTd = options.hasMissing ? `<td>${missing}</td>` : '';
3856038594
38561- return `<tr><td>${name}</td><td>${stmts}</td><td>${miss}</td><td>${cover}</td>${lastTd}</tr>`;
38595+ // prettier-ignore
38596+ return `<tr><td>${name}</td><td>${stmts}</td><td>${miss}</td>${branchTd}<td>${cover}</td>${missingTd}</tr>`;
3856238597};
3856338598
3856438599// make summary row - tr
3856538600const toTotalRow = (item, options) => {
3856638601 const { name, stmts, miss, cover } = item;
38567- const emptyCell = options.hasMissing ? '<td> </td>' : '';
38602+ const branchTd = options.hasBranch
38603+ ? `<td><b>${item.branch || 0}</b></td>` +
38604+ `<td><b>${item.brpart || 0}</b></td>`
38605+ : '';
38606+ const missingTd = options.hasMissing ? '<td> </td>' : '';
3856838607
38569- return `<tr><td><b>${name}</b></td><td><b>${stmts}</b></td><td><b>${miss}</b></td><td><b>${cover}</b></td>${emptyCell}</tr>`;
38608+ // prettier-ignore
38609+ return `<tr><td><b>${name}</b></td><td><b>${stmts}</b></td><td><b>${miss}</b></td>${branchTd}<td><b>${cover}</b></td>${missingTd}</tr>`;
3857038610};
3857138611
3857238612// make fileName cell - td
@@ -38589,7 +38629,8 @@ const toFolderTd = (path, options) => {
3858938629 return '';
3859038630 }
3859138631
38592- const colspan = options.hasMissing ? 5 : 4;
38632+ const colspan =
38633+ 4 + (options.hasBranch ? 2 : 0) + (options.hasMissing ? 1 : 0);
3859338634 return `<tr><td colspan="${colspan}"><b>${path}</b></td></tr>`;
3859438635};
3859538636
@@ -38647,13 +38688,22 @@ const getTotalCoverage = (parsedXml) => {
3864738688 const cover = parseInt(parseFloat(coverage['line-rate']) * 100);
3864838689 const linesValid = parseInt(coverage['lines-valid']);
3864938690 const linesCovered = parseInt(coverage['lines-covered']);
38691+ const branchesValid = parseInt(coverage['branches-valid']) || 0;
38692+ const branchesCovered = parseInt(coverage['branches-covered']) || 0;
3865038693
38651- return {
38694+ const result = {
3865238695 name: 'TOTAL',
3865338696 stmts: linesValid,
3865438697 miss: linesValid - linesCovered,
3865538698 cover: cover !== '0' ? `${cover}%` : '0',
3865638699 };
38700+
38701+ if (branchesValid > 0) {
38702+ result.branch = branchesValid.toString();
38703+ result.brpart = (branchesValid - branchesCovered).toString();
38704+ }
38705+
38706+ return result;
3865738707};
3865838708
3865938709// return true if "coverage file" include right structure
@@ -38750,7 +38800,13 @@ const parseClass = (classObj, xmlSkipCovered) => {
3875038800 return null;
3875138801 }
3875238802
38753- const { stmts, missing, totalMissing: miss } = parseLines(classObj.lines);
38803+ const {
38804+ stmts,
38805+ missing,
38806+ totalMissing: miss,
38807+ branchTotal,
38808+ branchMissing,
38809+ } = parseLines(classObj.lines);
3875438810 const { filename: name, 'line-rate': lineRate } = classObj['$'];
3875538811 const isFullCoverage = lineRate === '1';
3875638812
@@ -38762,24 +38818,57 @@ const parseClass = (classObj, xmlSkipCovered) => {
3876238818 ? '100%'
3876338819 : `${parseInt(parseFloat(lineRate) * 100)}%`;
3876438820
38765- return { name, stmts, miss, cover, missing };
38821+ const result = { name, stmts, miss, cover, missing };
38822+
38823+ if (branchTotal > 0) {
38824+ result.branch = branchTotal.toString();
38825+ result.brpart = branchMissing.toString();
38826+ }
38827+
38828+ return result;
3876638829};
3876738830
3876838831const parseLines = (lines) => {
38832+ const emptyResult = {
38833+ stmts: '0',
38834+ missing: '',
38835+ totalMissing: '0',
38836+ branchTotal: 0,
38837+ branchMissing: 0,
38838+ };
38839+
3876938840 if (!lines || !lines.length || !lines[0].line) {
38770- return { stmts: '0', missing: '', totalMissing: '0' } ;
38841+ return emptyResult ;
3877138842 }
3877238843
3877338844 let stmts = 0;
3877438845 const missingLines = [];
38846+ let branchTotal = 0;
38847+ let branchMissing = 0;
3877538848
3877638849 lines[0].line.forEach((line) => {
3877738850 stmts++;
38778- const { hits, number } = line['$'];
38851+ const {
38852+ hits,
38853+ number,
38854+ branch,
38855+ 'condition-coverage': condCoverage,
38856+ } = line['$'];
3877938857
3878038858 if (hits === '0') {
3878138859 missingLines.push(parseInt(number));
3878238860 }
38861+
38862+ if (branch === 'true' && condCoverage) {
38863+ const match = condCoverage.match(/\((\d+)\/(\d+)\)/);
38864+
38865+ if (match) {
38866+ const covered = parseInt(match[1]);
38867+ const total = parseInt(match[2]);
38868+ branchTotal += total;
38869+ branchMissing += total - covered;
38870+ }
38871+ }
3878338872 });
3878438873
3878538874 const missing = missingLines.reduce((arr, val, i, a) => {
@@ -38801,6 +38890,8 @@ const parseLines = (lines) => {
3880138890 stmts: stmts.toString(),
3880238891 missing: missingText,
3880338892 totalMissing: missingLines.length.toString(),
38893+ branchTotal,
38894+ branchMissing,
3880438895 };
3880538896};
3880638897
0 commit comments