UNPKG

svelte-language-server

Version:
318 lines 14.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SvelteFragmentMapper = exports.FallbackTranspiledSvelteDocument = exports.TranspiledSvelteDocument = exports.SvelteDocument = exports.TranspileErrorSource = void 0; const trace_mapping_1 = require("@jridgewell/trace-mapping"); const documents_1 = require("../../lib/documents"); const utils_1 = require("../../utils"); var TranspileErrorSource; (function (TranspileErrorSource) { TranspileErrorSource["Script"] = "Script"; TranspileErrorSource["Style"] = "Style"; })(TranspileErrorSource || (exports.TranspileErrorSource = TranspileErrorSource = {})); /** * Represents a text document that contains a svelte component. */ class SvelteDocument { get config() { return this.parent.configPromise; } constructor(parent) { this.parent = parent; this.languageId = 'svelte'; this.version = 0; this.uri = this.parent.uri; this.script = this.parent.scriptInfo; this.moduleScript = this.parent.moduleScriptInfo; this.style = this.parent.styleInfo; this.version = this.parent.version; } getText() { return this.parent.getText(); } getFilePath() { return this.parent.getFilePath() || ''; } offsetAt(position) { return this.parent.offsetAt(position); } async getTranspiled() { if (!this.transpiledDoc) { const [major, minor] = this.parent.getSvelteVersion(); if (major > 3 || (major === 3 && minor >= 32)) { this.transpiledDoc = TranspiledSvelteDocument.create(this.parent, await this.config); } else { this.transpiledDoc = FallbackTranspiledSvelteDocument.create(this.parent, (await this.config)?.preprocess); } } return this.transpiledDoc; } async getCompiled() { if (!this.compileResult) { this.compileResult = this.getCompiledWith((await this.config)?.compilerOptions); } return this.compileResult; } async getCompiledWith(options = {}) { return this.parent.compiler.compile((await this.getTranspiled()).getText(), options); } } exports.SvelteDocument = SvelteDocument; class TranspiledSvelteDocument { static async create(document, config) { if (!config?.preprocess) { return new TranspiledSvelteDocument(document.getText()); } const filename = document.getFilePath() || ''; const preprocessed = await document.compiler.preprocess(document.getText(), wrapPreprocessors(config?.preprocess), { filename }); if (preprocessed.code === document.getText()) { return new TranspiledSvelteDocument(document.getText()); } return new TranspiledSvelteDocument(preprocessed.code, preprocessed.map ? new documents_1.SourceMapDocumentMapper(createTraceMap(preprocessed.map), // The "sources" array only contains the Svelte filename, not its path. // For getting generated positions, the sourcemap consumer wants an exact match // of the source filepath. Therefore only pass in the filename here. (0, utils_1.getLastPartOfPath)(filename)) : undefined); } constructor(code, mapper) { this.code = code; this.mapper = mapper; } getOriginalPosition(generatedPosition) { return this.mapper?.getOriginalPosition(generatedPosition) || generatedPosition; } getText() { return this.code; } getGeneratedPosition(originalPosition) { return this.mapper?.getGeneratedPosition(originalPosition) || originalPosition; } } exports.TranspiledSvelteDocument = TranspiledSvelteDocument; /** * Only used when the user has an old Svelte version installed where source map support * for preprocessors is not built in yet. * This fallback version does not map correctly when there's both a module and instance script. * It isn't worth fixing these cases though now that Svelte ships a preprocessor with source maps. */ class FallbackTranspiledSvelteDocument { static async create(document, preprocessors = []) { const { transpiled, processedScripts, processedStyles } = await transpile(document, preprocessors); const scriptMapper = SvelteFragmentMapper.createScript(document, transpiled, processedScripts); const styleMapper = SvelteFragmentMapper.createStyle(document, transpiled, processedStyles); return new FallbackTranspiledSvelteDocument(document, transpiled, scriptMapper, styleMapper); } constructor(parent, transpiled, scriptMapper, styleMapper) { this.parent = parent; this.transpiled = transpiled; this.scriptMapper = scriptMapper; this.styleMapper = styleMapper; this.fragmentInfos = [this.scriptMapper?.fragmentInfo, this.styleMapper?.fragmentInfo] .filter(utils_1.isNotNullOrUndefined) .sort((i1, i2) => i1.end - i2.end); } getOriginalPosition(generatedPosition) { if (this.scriptMapper?.isInTranspiledFragment(generatedPosition)) { return this.scriptMapper.getOriginalPosition(generatedPosition); } if (this.styleMapper?.isInTranspiledFragment(generatedPosition)) { return this.styleMapper.getOriginalPosition(generatedPosition); } // Position is not in fragments, but we still need to account for // the length differences of the fragments before the position. let offset = (0, documents_1.offsetAt)(generatedPosition, this.transpiled); for (const fragmentInfo of this.fragmentInfos) { if (offset > fragmentInfo.end) { offset += fragmentInfo.diff; } } return this.parent.positionAt(offset); } getURL() { return this.parent.getURL(); } getText() { return this.transpiled; } getGeneratedPosition(originalPosition) { const { styleInfo, scriptInfo } = this.parent; if ((0, documents_1.isInTag)(originalPosition, scriptInfo) && this.scriptMapper) { return this.scriptMapper.getGeneratedPosition(originalPosition); } if ((0, documents_1.isInTag)(originalPosition, styleInfo) && this.styleMapper) { return this.styleMapper.getGeneratedPosition(originalPosition); } // Add length difference of each fragment let offset = (0, documents_1.offsetAt)(originalPosition, this.parent.getText()); for (const fragmentInfo of this.fragmentInfos) { if (offset > fragmentInfo.end) { offset -= fragmentInfo.diff; } } return (0, documents_1.positionAt)(offset, this.getText()); } } exports.FallbackTranspiledSvelteDocument = FallbackTranspiledSvelteDocument; class SvelteFragmentMapper { static createStyle(originalDoc, transpiled, processed) { return SvelteFragmentMapper.create(originalDoc, transpiled, originalDoc.styleInfo, (0, documents_1.extractStyleTag)(transpiled), processed); } static createScript(originalDoc, transpiled, processed) { const scriptInfo = originalDoc.scriptInfo || originalDoc.moduleScriptInfo; const maybeScriptTag = (0, documents_1.extractScriptTags)(transpiled); const maybeScriptTagInfo = maybeScriptTag && (maybeScriptTag.script || maybeScriptTag.moduleScript); return SvelteFragmentMapper.create(originalDoc, transpiled, scriptInfo, maybeScriptTagInfo || null, processed); } static create(originalDoc, transpiled, originalTagInfo, transpiledTagInfo, processed) { const sourceMapper = processed.length > 0 ? SvelteFragmentMapper.createSourceMapper(processed, originalDoc) : new documents_1.IdentityMapper(originalDoc.uri); if (originalTagInfo && transpiledTagInfo) { const sourceLength = originalTagInfo.container.end - originalTagInfo.container.start; const transpiledLength = transpiledTagInfo.container.end - transpiledTagInfo.container.start; const diff = sourceLength - transpiledLength; return new SvelteFragmentMapper({ end: transpiledTagInfo.container.end, diff }, new documents_1.FragmentMapper(originalDoc.getText(), originalTagInfo, originalDoc.uri), new documents_1.FragmentMapper(transpiled, transpiledTagInfo, originalDoc.uri), sourceMapper); } return null; } static createSourceMapper(processed, originalDoc) { return processed.reduce((parent, processedSingle) => processedSingle?.map ? new documents_1.SourceMapDocumentMapper(createTraceMap(processedSingle.map), originalDoc.uri, parent) : new documents_1.IdentityMapper(originalDoc.uri, parent), undefined); } constructor( /** * End offset + length difference to original */ fragmentInfo, /** * Maps between full original source and fragment within that original. */ originalFragmentMapper, /** * Maps between full transpiled source and fragment within that transpiled. */ transpiledFragmentMapper, /** * Maps between original and transpiled, within fragment. */ sourceMapper) { this.fragmentInfo = fragmentInfo; this.originalFragmentMapper = originalFragmentMapper; this.transpiledFragmentMapper = transpiledFragmentMapper; this.sourceMapper = sourceMapper; } isInTranspiledFragment(generatedPosition) { return this.transpiledFragmentMapper.isInGenerated(generatedPosition); } getOriginalPosition(generatedPosition) { // Map the position to be relative to the transpiled fragment const positionInTranspiledFragment = this.transpiledFragmentMapper.getGeneratedPosition(generatedPosition); // Map the position, using the sourcemap, to the original position in the source fragment const positionInOriginalFragment = this.sourceMapper.getOriginalPosition(positionInTranspiledFragment); // Map the position to be in the original fragment's parent return this.originalFragmentMapper.getOriginalPosition(positionInOriginalFragment); } /** * Reversing `getOriginalPosition` */ getGeneratedPosition(originalPosition) { const positionInOriginalFragment = this.originalFragmentMapper.getGeneratedPosition(originalPosition); const positionInTranspiledFragment = this.sourceMapper.getGeneratedPosition(positionInOriginalFragment); return this.transpiledFragmentMapper.getOriginalPosition(positionInTranspiledFragment); } } exports.SvelteFragmentMapper = SvelteFragmentMapper; /** * Wrap preprocessors and rethrow on errors with more info on where the error came from. */ function wrapPreprocessors(preprocessors = []) { preprocessors = Array.isArray(preprocessors) ? preprocessors : [preprocessors]; return preprocessors.map((preprocessor) => { const wrappedPreprocessor = { markup: preprocessor.markup }; if (preprocessor.script) { wrappedPreprocessor.script = async (args) => { try { return await preprocessor.script(args); } catch (e) { e.__source = TranspileErrorSource.Script; throw e; } }; } if (preprocessor.style) { wrappedPreprocessor.style = async (args) => { try { return await preprocessor.style(args); } catch (e) { e.__source = TranspileErrorSource.Style; throw e; } }; } return wrappedPreprocessor; }); } async function transpile(document, preprocessors = []) { preprocessors = Array.isArray(preprocessors) ? preprocessors : [preprocessors]; const processedScripts = []; const processedStyles = []; const wrappedPreprocessors = preprocessors.map((preprocessor) => { const wrappedPreprocessor = { markup: preprocessor.markup }; if (preprocessor.script) { wrappedPreprocessor.script = async (args) => { try { const res = await preprocessor.script(args); if (res && res.map) { processedScripts.push(res); } return res; } catch (e) { e.__source = TranspileErrorSource.Script; throw e; } }; } if (preprocessor.style) { wrappedPreprocessor.style = async (args) => { try { const res = await preprocessor.style(args); if (res && res.map) { processedStyles.push(res); } return res; } catch (e) { e.__source = TranspileErrorSource.Style; throw e; } }; } return wrappedPreprocessor; }); const result = await document.compiler.preprocess(document.getText(), wrappedPreprocessors, { filename: document.getFilePath() || '' }); const transpiled = result.code || result.toString?.() || ''; return { transpiled, processedScripts, processedStyles }; } function createTraceMap(map) { return new trace_mapping_1.TraceMap(normalizeMap(map)); function normalizeMap(map) { // We don't know what we get, could be a stringified sourcemap, // or a class which has the required properties on it, or a class // which we need to call toString() on to get the correct format. if (typeof map === 'string' || map.version) { return map; } return map.toString(); } } //# sourceMappingURL=SvelteDocument.js.map