@typespec/compiler
Version:
TypeSpec Compiler Preview
106 lines • 4.19 kB
JavaScript
import { DiagnosticSeverity } from "vscode-languageserver/node.js";
import { getDiagnosticTemplateInstantitationTrace, getSourceLocation, } from "../core/diagnostics.js";
import { getTypeName } from "../core/helpers/type-name-utils.js";
import { isDefined } from "../utils/misc.js";
/** Convert TypeSpec Diagnostic to Lsp diagnostic. Each TypeSpec diagnostic could produce multiple lsp ones when it involve multiple locations. */
export function convertDiagnosticToLsp(fileService, program, document, diagnostic) {
const root = getVSLocation(getSourceLocation(diagnostic.target, { locateId: true }), document);
if (root === undefined || !fileService.upToDate(root.document))
return [];
const instantiationNodes = getDiagnosticTemplateInstantitationTrace(diagnostic.target);
const relatedInformation = [];
const relatedDiagnostics = [];
if (instantiationNodes.length > 0) {
const items = instantiationNodes
.map((node) => getVSLocationWithTypeInfo(program, node, document))
.filter(isDefined);
for (const location of items) {
relatedInformation.push({
location: { uri: location.document.uri, range: location.range },
message: `in instantiation of template \`${location.typeName}\``,
});
}
const [last, ...rest] = [...items].reverse();
if (last) {
relatedDiagnostics.push([
createLspDiagnostic({
range: last.range,
message: `In instantiation of this template:`,
severity: DiagnosticSeverity.Warning,
code: diagnostic.code,
relatedInformation: [
...rest.map((location) => ({
location: { uri: location.document.uri, range: location.range },
message: `in instantiation of template \`${location.typeName}\``,
})),
{
location: { uri: root.document.uri, range: root.range },
message: diagnostic.message,
},
],
}),
last.document,
]);
}
}
const rootDiagnostic = [
createLspDiagnostic({
range: root.range,
message: diagnostic.message,
severity: convertSeverity(diagnostic.severity),
code: diagnostic.code,
relatedInformation,
}),
root.document,
];
return [rootDiagnostic, ...relatedDiagnostics];
}
function createLspDiagnostic(diag) {
return {
source: "TypeSpec",
...diag,
};
}
function getDocumentForLocation(location, currentDocument) {
if (location?.file) {
return location.file.document;
}
else {
// https://github.com/microsoft/language-server-protocol/issues/256
//
// LSP does not currently allow sending a diagnostic with no location so
// we report diagnostics with no location on the document that changed to
// trigger.
return currentDocument;
}
}
function getVSLocation(location, currentDocument) {
if (location === undefined)
return undefined;
const document = getDocumentForLocation(location, currentDocument);
if (!document) {
return undefined;
}
const start = document.positionAt(location?.pos ?? 0);
const end = document.positionAt(location?.end ?? 0);
return { range: { start, end }, document };
}
function getVSLocationWithTypeInfo(program, node, document) {
const location = getVSLocation(getSourceLocation(node, { locateId: true }), document);
if (location === undefined)
return undefined;
return {
...location,
node,
typeName: getTypeName(program.checker.getTypeForNode(node)),
};
}
function convertSeverity(severity) {
switch (severity) {
case "warning":
return DiagnosticSeverity.Warning;
case "error":
return DiagnosticSeverity.Error;
}
}
//# sourceMappingURL=diagnostics.js.map