fix: refactor converter and add comments

Signed-off-by: Anton Ganhammar <ganhammar@gmail.com>
This commit is contained in:
Anton Ganhammar
2023-08-20 21:29:04 +02:00
parent 9601909430
commit 499e76c934
@@ -22,58 +22,105 @@ export class Lcov implements Converter {
this.logger = logger;
}
/**
* convert lcov into shared json coverage format
*
* @param raw - raw lcov report
* @param scmFiles - list of files that are committed to SCM
*/
convert(raw: string, scmFiles: string[]): FileEntry[] {
const lines = raw.split(/\r?\n/);
const jscov: Array<FileEntry> = [];
let currentFile: FileEntry | null = null;
lines.forEach(line => {
// If the line starts with SF, it's a new file
if (/^SF:/.test(line)) {
const coverageFilename = line.replace(/^SF:/, '');
const filename = scmFiles
.map(f => f.trimEnd())
.find(f => coverageFilename.endsWith(f));
this.logger.debug(`matched ${coverageFilename} to ${currentFile}`);
if (filename) {
currentFile = {
filename,
lineHits: {},
branchHits: {},
};
}
const [section, value] = line.split(':');
switch (section) {
// If the line starts with SF, it's a new file
case 'SF':
currentFile = this.processNewFile(value, scmFiles);
break;
// If the line starts with DA, it's a line hit
} else if (currentFile && /^DA:/.test(line)) {
const [, lineNumber, hits] = line.split(/[,:]+/);
currentFile.lineHits[Number(lineNumber)] = Number(hits);
// If the line starts with BRDA, it's a branch
} else if (currentFile && /^BRDA:/.test(line)) {
const [, lineNumber, , , hits] = line.split(/[,:]+/);
const isHit = Number(hits) > 0;
if (!currentFile.branchHits[Number(lineNumber)]) {
currentFile.branchHits[Number(lineNumber)] = {
covered: isHit ? 1 : 0,
available: 1,
missed: isHit ? 0 : 1,
};
} else {
currentFile.branchHits[Number(lineNumber)].available += 1;
currentFile.branchHits[Number(lineNumber)].covered += isHit ? 1 : 0;
currentFile.branchHits[Number(lineNumber)].missed += isHit ? 0 : 1;
}
case 'DA':
this.processLineHit(currentFile, value);
break;
// If the line starts with BRDA, it's a branch line
case 'BRDA':
this.processBranchHit(currentFile, value);
break;
// If the line starts with end_of_record, it's the end of current file
} else if (currentFile && /^end_of_record/.test(line)) {
jscov.push(currentFile);
currentFile = null;
case 'end_of_record':
if (currentFile) {
jscov.push(currentFile);
currentFile = null;
}
break;
default:
break;
}
});
return jscov;
}
/**
* Parses a new file entry
*
* @param file - file name from coverage report
* @param scmFiles - list of files that are committed to SCM
*/
private processNewFile(file: string, scmFiles: string[]): FileEntry | null {
const filename = scmFiles.map(f => f.trimEnd()).find(f => file.endsWith(f));
this.logger.debug(`matched ${file} to ${filename}`);
if (filename) {
return {
filename,
lineHits: {},
branchHits: {},
};
}
return null;
}
/**
* Parses line coverage information
*
* @param currentFile - current file entry
* @param value - line coverage information
*/
private processLineHit(currentFile: FileEntry | null, value: string): void {
if (!currentFile) return;
const [lineNumber, hits] = value.split(',');
currentFile.lineHits[Number(lineNumber)] = Number(hits);
}
/**
* Parses branch coverage information
*
* @param currentFile - current file entry
* @param value - branch coverage information
*/
private processBranchHit(currentFile: FileEntry | null, value: string): void {
if (!currentFile) return;
const [lineNumber, , , hits] = value.split(',');
const lineNumberNum = Number(lineNumber);
const isHit = Number(hits) > 0;
const branch = currentFile.branchHits[lineNumberNum] || {
covered: 0,
available: 0,
missed: 0,
};
branch.available++;
branch.covered += isHit ? 1 : 0;
branch.missed += isHit ? 0 : 1;
currentFile.branchHits[lineNumberNum] = branch;
}
}