UNPKG

svelte-language-server

Version:
258 lines 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SourceMapDocumentMapper = exports.FragmentMapper = exports.IdentityMapper = void 0; exports.mapRangeToOriginal = mapRangeToOriginal; exports.mapLocationToOriginal = mapLocationToOriginal; exports.mapRangeToGenerated = mapRangeToGenerated; exports.mapCompletionItemToOriginal = mapCompletionItemToOriginal; exports.mapHoverToParent = mapHoverToParent; exports.mapObjWithRangeToOriginal = mapObjWithRangeToOriginal; exports.mapInsertReplaceEditToOriginal = mapInsertReplaceEditToOriginal; exports.mapEditToOriginal = mapEditToOriginal; exports.mapDiagnosticToGenerated = mapDiagnosticToGenerated; exports.mapColorPresentationToOriginal = mapColorPresentationToOriginal; exports.mapSymbolInformationToOriginal = mapSymbolInformationToOriginal; exports.mapLocationLinkToOriginal = mapLocationLinkToOriginal; exports.mapTextDocumentEditToOriginal = mapTextDocumentEditToOriginal; exports.mapCodeActionToOriginal = mapCodeActionToOriginal; exports.mapSelectionRangeToParent = mapSelectionRangeToParent; const vscode_languageserver_1 = require("vscode-languageserver"); const utils_1 = require("./utils"); const logger_1 = require("../../logger"); const trace_mapping_1 = require("@jridgewell/trace-mapping"); /** * Does not map, returns positions as is. */ class IdentityMapper { constructor(url, parent) { this.url = url; this.parent = parent; } getOriginalPosition(generatedPosition) { if (this.parent) { generatedPosition = this.getOriginalPosition(generatedPosition); } return generatedPosition; } getGeneratedPosition(originalPosition) { if (this.parent) { originalPosition = this.getGeneratedPosition(originalPosition); } return originalPosition; } isInGenerated(position) { if (this.parent && !this.parent.isInGenerated(position)) { return false; } return true; } getURL() { return this.url; } } exports.IdentityMapper = IdentityMapper; /** * Maps positions in a fragment relative to a parent. */ class FragmentMapper { constructor(originalText, tagInfo, url) { this.originalText = originalText; this.tagInfo = tagInfo; this.url = url; this.lineOffsetsOriginal = (0, utils_1.getLineOffsets)(this.originalText); this.lineOffsetsGenerated = (0, utils_1.getLineOffsets)(this.tagInfo.content); } getOriginalPosition(generatedPosition) { const parentOffset = this.offsetInParent((0, utils_1.offsetAt)(generatedPosition, this.tagInfo.content, this.lineOffsetsGenerated)); return (0, utils_1.positionAt)(parentOffset, this.originalText, this.lineOffsetsOriginal); } offsetInParent(offset) { return this.tagInfo.start + offset; } getGeneratedPosition(originalPosition) { const fragmentOffset = (0, utils_1.offsetAt)(originalPosition, this.originalText, this.lineOffsetsOriginal) - this.tagInfo.start; return (0, utils_1.positionAt)(fragmentOffset, this.tagInfo.content, this.lineOffsetsGenerated); } isInGenerated(pos) { const offset = (0, utils_1.offsetAt)(pos, this.originalText, this.lineOffsetsOriginal); return offset >= this.tagInfo.start && offset <= this.tagInfo.end; } getURL() { return this.url; } } exports.FragmentMapper = FragmentMapper; class SourceMapDocumentMapper { constructor(traceMap, sourceUri, parent) { this.traceMap = traceMap; this.sourceUri = sourceUri; this.parent = parent; } getOriginalPosition(generatedPosition) { if (this.parent) { generatedPosition = this.parent.getOriginalPosition(generatedPosition); } if (generatedPosition.line < 0) { return { line: -1, character: -1 }; } const mapped = (0, trace_mapping_1.originalPositionFor)(this.traceMap, { line: generatedPosition.line + 1, column: generatedPosition.character }); if (!mapped) { return { line: -1, character: -1 }; } if (mapped.line === 0) { logger_1.Logger.debug('Got 0 mapped line from', generatedPosition, 'col was', mapped.column); } return { line: (mapped.line || 0) - 1, character: mapped.column || 0 }; } getGeneratedPosition(originalPosition) { if (this.parent) { originalPosition = this.parent.getGeneratedPosition(originalPosition); } const mapped = (0, trace_mapping_1.generatedPositionFor)(this.traceMap, { line: originalPosition.line + 1, column: originalPosition.character, source: this.sourceUri }); if (!mapped) { return { line: -1, character: -1 }; } const result = { line: (mapped.line || 0) - 1, character: mapped.column || 0 }; if (result.line < 0) { return result; } return result; } isInGenerated(position) { if (this.parent && !this.isInGenerated(position)) { return false; } const generated = this.getGeneratedPosition(position); return generated.line >= 0; } getURL() { return this.sourceUri; } } exports.SourceMapDocumentMapper = SourceMapDocumentMapper; function mapRangeToOriginal(fragment, range) { // DON'T use Range.create here! Positions might not be mapped // and therefore return negative numbers, which makes Range.create throw. // These invalid position need to be handled // on a case-by-case basis in the calling functions. const originalRange = { start: fragment.getOriginalPosition(range.start), end: fragment.getOriginalPosition(range.end) }; checkRangeLength(originalRange, range); return originalRange; } /** Range may be mapped one character short - reverse that for "in the same line" cases*/ function checkRangeLength(originalRange, range) { if (originalRange.start.line === originalRange.end.line && range.start.line === range.end.line && originalRange.end.character - originalRange.start.character === range.end.character - range.start.character - 1) { originalRange.end.character += 1; } } function mapLocationToOriginal(fragment, range) { const map = (fragment.getOriginalFilePosition ?? fragment.getOriginalPosition).bind(fragment); const start = map(range.start); const end = map(range.end); const originalRange = { start: { line: start.line, character: start.character }, end: { line: end.line, character: end.character } }; checkRangeLength(originalRange, range); return { range: originalRange, uri: start.uri ? start.uri : fragment.getURL() }; } function mapRangeToGenerated(fragment, range) { return vscode_languageserver_1.Range.create(fragment.getGeneratedPosition(range.start), fragment.getGeneratedPosition(range.end)); } function mapCompletionItemToOriginal(fragment, item) { if (!item.textEdit) { return item; } return { ...item, textEdit: mapEditToOriginal(fragment, item.textEdit) }; } function mapHoverToParent(fragment, hover) { if (!hover.range) { return hover; } return { ...hover, range: mapRangeToOriginal(fragment, hover.range) }; } function mapObjWithRangeToOriginal(fragment, objWithRange) { return { ...objWithRange, range: mapRangeToOriginal(fragment, objWithRange.range) }; } function mapInsertReplaceEditToOriginal(fragment, edit) { return { ...edit, insert: mapRangeToOriginal(fragment, edit.insert), replace: mapRangeToOriginal(fragment, edit.replace) }; } function mapEditToOriginal(fragment, edit) { return vscode_languageserver_1.TextEdit.is(edit) ? mapObjWithRangeToOriginal(fragment, edit) : mapInsertReplaceEditToOriginal(fragment, edit); } function mapDiagnosticToGenerated(fragment, diagnostic) { return { ...diagnostic, range: mapRangeToGenerated(fragment, diagnostic.range) }; } function mapColorPresentationToOriginal(fragment, presentation) { const item = { ...presentation }; if (item.textEdit) { item.textEdit = mapObjWithRangeToOriginal(fragment, item.textEdit); } if (item.additionalTextEdits) { item.additionalTextEdits = item.additionalTextEdits.map((edit) => mapObjWithRangeToOriginal(fragment, edit)); } return item; } function mapSymbolInformationToOriginal(fragment, info) { return { ...info, location: mapObjWithRangeToOriginal(fragment, info.location) }; } function mapLocationLinkToOriginal(fragment, def) { return vscode_languageserver_1.LocationLink.create(def.targetUri, fragment.getURL() === def.targetUri ? mapRangeToOriginal(fragment, def.targetRange) : def.targetRange, fragment.getURL() === def.targetUri ? mapRangeToOriginal(fragment, def.targetSelectionRange) : def.targetSelectionRange, def.originSelectionRange ? mapRangeToOriginal(fragment, def.originSelectionRange) : undefined); } function mapTextDocumentEditToOriginal(fragment, edit) { if (edit.textDocument.uri !== fragment.getURL()) { return edit; } return vscode_languageserver_1.TextDocumentEdit.create(edit.textDocument, edit.edits.map((textEdit) => mapObjWithRangeToOriginal(fragment, textEdit))); } function mapCodeActionToOriginal(fragment, codeAction) { return vscode_languageserver_1.CodeAction.create(codeAction.title, { documentChanges: codeAction.edit.documentChanges.map((edit) => mapTextDocumentEditToOriginal(fragment, edit)) }, codeAction.kind); } function mapSelectionRangeToParent(fragment, selectionRange) { const { range, parent } = selectionRange; return vscode_languageserver_1.SelectionRange.create(mapRangeToOriginal(fragment, range), parent && mapSelectionRangeToParent(fragment, parent)); } //# sourceMappingURL=DocumentMapper.js.map