mlh-tsd
Version:
Check TypeScript type definitions
87 lines (86 loc) • 3.78 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDiagnostics = void 0;
const typescript_1 = require("../../libraries/typescript");
const parser_1 = require("./parser");
const interfaces_1 = require("./interfaces");
const assertions_1 = require("./assertions");
// List of diagnostic codes that should be ignored in general
const ignoredDiagnostics = new Set([
interfaces_1.DiagnosticCode.TopLevelAwaitOnlyAllowedWhenModuleESNextOrSystem
]);
// List of diagnostic codes which should be ignored inside `expectError` statements
const expectErrordiagnosticCodesToIgnore = new Set([
interfaces_1.DiagnosticCode.ArgumentTypeIsNotAssignableToParameterType,
interfaces_1.DiagnosticCode.PropertyDoesNotExistOnType,
interfaces_1.DiagnosticCode.CannotAssignToReadOnlyProperty,
interfaces_1.DiagnosticCode.TypeIsNotAssignableToOtherType,
interfaces_1.DiagnosticCode.TypeDoesNotSatisfyTheConstraint,
interfaces_1.DiagnosticCode.GenericTypeRequiresTypeArguments,
interfaces_1.DiagnosticCode.ExpectedArgumentsButGotOther,
interfaces_1.DiagnosticCode.NoOverloadMatches,
interfaces_1.DiagnosticCode.PropertyMissingInType1ButRequiredInType2
]);
/**
* Check if the provided diagnostic should be ignored.
*
* @param diagnostic - The diagnostic to validate.
* @param expectedErrors - Map of the expected errors.
* @returns Boolean indicating if the diagnostic should be ignored or not.
*/
const ignoreDiagnostic = (diagnostic, expectedErrors) => {
if (ignoredDiagnostics.has(diagnostic.code)) {
// Filter out diagnostics which are present in the `ignoredDiagnostics` set
return true;
}
if (!expectErrordiagnosticCodesToIgnore.has(diagnostic.code)) {
return false;
}
const diagnosticFileName = diagnostic.file.fileName;
for (const [location] of expectedErrors) {
const start = diagnostic.start;
if (diagnosticFileName === location.fileName && start > location.start && start < location.end) {
// Remove the expected error from the Map so it's not being reported as failure
expectedErrors.delete(location);
return true;
}
}
return false;
};
/**
* Get a list of TypeScript diagnostics within the current context.
*
* @param context - The context object.
* @returns List of diagnostics
*/
exports.getDiagnostics = (context) => {
let numTests = 0;
const diagnostics = [];
const program = typescript_1.createProgram(context.testFiles, context.config.compilerOptions);
const tsDiagnostics = program
.getSemanticDiagnostics()
.concat(program.getSyntacticDiagnostics());
const assertions = parser_1.extractAssertions(program);
for (const assertion of assertions) {
numTests = numTests + assertion[1].size;
}
diagnostics.push(...assertions_1.handle(program.getTypeChecker(), assertions));
const expectedErrors = parser_1.parseErrorAssertionToLocation(assertions);
for (const diagnostic of tsDiagnostics) {
if (!diagnostic.file || ignoreDiagnostic(diagnostic, expectedErrors)) {
continue;
}
const position = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
diagnostics.push({
fileName: diagnostic.file.fileName,
message: typescript_1.flattenDiagnosticMessageText(diagnostic.messageText, '\n'),
severity: 'error',
line: position.line + 1,
column: position.character
});
}
for (const [, diagnostic] of expectedErrors) {
diagnostics.push(Object.assign(Object.assign({}, diagnostic), { message: 'Expected an error, but found none.', severity: 'error' }));
}
return { numTests, diagnostics };
};