codecheck-type-coverage
Version:
Track missing type coverage in TypeScript projects to ensure type safety
85 lines (84 loc) • 3.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const client_1 = require("@codechecks/client");
const type_coverage_1 = require("type-coverage");
const lodash_1 = require("lodash");
const ARTIFACT_KEY = "type-coverage";
const defaultOptions = {
tsconfigPath: "tsconfig.json",
};
async function typeCoverageWatcher(_options) {
const options = Object.assign({}, defaultOptions, _options);
const _typeCoverage = await type_coverage_1.lint(options.tsconfigPath, true, false);
const typeCoverage = normalizeTypeCoverage(_typeCoverage);
await client_1.codeChecks.saveValue(ARTIFACT_KEY, typeCoverage);
if (!client_1.codeChecks.isPr()) {
return;
}
const baseTypeCoverage = await client_1.codeChecks.getValue(ARTIFACT_KEY);
const report = getReport(typeCoverage, baseTypeCoverage);
await client_1.codeChecks.report(report);
}
exports.typeCoverageWatcher = typeCoverageWatcher;
function getReport(headTypeCoverageArtifact, baseTypeCoverageArtifact) {
const headTypeCoverage = (headTypeCoverageArtifact.typedSymbols / headTypeCoverageArtifact.totalSymbols) * 100;
const baseTypeCoverage = baseTypeCoverageArtifact
? (baseTypeCoverageArtifact.typedSymbols / baseTypeCoverageArtifact.totalSymbols) * 100
: 0;
const coverageDiff = headTypeCoverage - baseTypeCoverage;
const shortDescription = `Change: ${renderSign(coverageDiff)}${perc(coverageDiff)} Total: ${perc(headTypeCoverage)}`;
const newUntypedSymbols = findNew(headTypeCoverageArtifact.allUntypedSymbols, baseTypeCoverageArtifact ? baseTypeCoverageArtifact.allUntypedSymbols : []);
let longDescription = `New untyped symbols: ${newUntypedSymbols.length}`;
if (newUntypedSymbols.length > 0) {
longDescription += `
| File | line:character | Symbol |
|:-----:|:-----:|:-----:|
${newUntypedSymbols
.slice(0, 100)
.map(s => `| ${s.filename} | ${s.line}:${s.character} | ${s.symbol} |`)
.join("\n")}`;
}
return {
name: "Type Coverage",
status: "success",
shortDescription,
longDescription,
};
}
function findNew(headSymbols, baseSymbols) {
const baseSymbolsByFilename = lodash_1.groupBy(baseSymbols, s => s.filename);
const newSymbols = [];
for (const headSymbol of headSymbols) {
// we assess if symbols are the same only by looking at filename and symbol name (we ignore line and character)
const baseSymbolMatch = (baseSymbolsByFilename[headSymbol.filename] || []).filter(s => s.symbol === headSymbol.symbol).length > 0;
if (!baseSymbolMatch) {
newSymbols.push(headSymbol);
}
}
return newSymbols;
}
function perc(n) {
return n.toFixed(2) + "%";
}
function normalizeTypeCoverage(rawTypeCoverage) {
return {
typedSymbols: rawTypeCoverage.correctCount,
totalSymbols: rawTypeCoverage.totalCount,
allUntypedSymbols: rawTypeCoverage.anys.map(a => ({
filename: a.file,
line: a.line,
character: a.character,
symbol: a.text,
})),
};
}
function renderSign(value) {
if (value > 0) {
return "+";
}
else {
// we dont' render signs for negative (it's part of a number xD) or 0
return "";
}
}
//# sourceMappingURL=index.js.map