UNPKG

@typespec/compiler

Version:

TypeSpec Compiler Preview

106 lines 4.19 kB
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