UNPKG

svelte-language-server

Version:
330 lines 15.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getScriptKindFromFileName = getScriptKindFromFileName; exports.getExtensionFromScriptKind = getExtensionFromScriptKind; exports.getScriptKindFromAttributes = getScriptKindFromAttributes; exports.isSvelteFilePath = isSvelteFilePath; exports.isVirtualSvelteFilePath = isVirtualSvelteFilePath; exports.toRealSvelteFilePath = toRealSvelteFilePath; exports.toVirtualSvelteFilePath = toVirtualSvelteFilePath; exports.ensureRealSvelteFilePath = ensureRealSvelteFilePath; exports.convertRange = convertRange; exports.convertToLocationRange = convertToLocationRange; exports.convertToLocationForReferenceOrDefinition = convertToLocationForReferenceOrDefinition; exports.hasNonZeroRange = hasNonZeroRange; exports.rangeToTextSpan = rangeToTextSpan; exports.findTsConfigPath = findTsConfigPath; exports.isSubPath = isSubPath; exports.getNearestWorkspaceUri = getNearestWorkspaceUri; exports.symbolKindFromString = symbolKindFromString; exports.scriptElementKindToCompletionItemKind = scriptElementKindToCompletionItemKind; exports.mapSeverity = mapSeverity; exports.getTsCheckComment = getTsCheckComment; exports.convertToTextSpan = convertToTextSpan; exports.isInScript = isInScript; exports.getDiagnosticTag = getDiagnosticTag; exports.changeSvelteComponentName = changeSvelteComponentName; exports.isGeneratedSvelteComponentName = isGeneratedSvelteComponentName; exports.offsetOfGeneratedComponentExport = offsetOfGeneratedComponentExport; exports.toGeneratedSvelteComponentName = toGeneratedSvelteComponentName; exports.hasTsExtensions = hasTsExtensions; exports.isSvelte2tsxShimFile = isSvelte2tsxShimFile; const path_1 = require("path"); const typescript_1 = __importDefault(require("typescript")); const vscode_languageserver_1 = require("vscode-languageserver"); const documents_1 = require("../../lib/documents"); const utils_1 = require("../../utils"); function getScriptKindFromFileName(fileName) { const ext = fileName.substr(fileName.lastIndexOf('.')); switch (ext.toLowerCase()) { case typescript_1.default.Extension.Js: return typescript_1.default.ScriptKind.JS; case typescript_1.default.Extension.Jsx: return typescript_1.default.ScriptKind.JSX; case typescript_1.default.Extension.Ts: return typescript_1.default.ScriptKind.TS; case typescript_1.default.Extension.Tsx: return typescript_1.default.ScriptKind.TSX; case typescript_1.default.Extension.Json: return typescript_1.default.ScriptKind.JSON; default: return typescript_1.default.ScriptKind.Unknown; } } function getExtensionFromScriptKind(kind) { switch (kind) { case typescript_1.default.ScriptKind.JSX: return typescript_1.default.Extension.Jsx; case typescript_1.default.ScriptKind.TS: return typescript_1.default.Extension.Ts; case typescript_1.default.ScriptKind.TSX: return typescript_1.default.Extension.Tsx; case typescript_1.default.ScriptKind.JSON: return typescript_1.default.Extension.Json; case typescript_1.default.ScriptKind.JS: default: return typescript_1.default.Extension.Js; } } function getScriptKindFromAttributes(attrs) { const type = attrs.lang || attrs.type; switch (type) { case 'ts': case 'typescript': case 'text/ts': case 'text/typescript': return typescript_1.default.ScriptKind.TSX; case 'javascript': case 'text/javascript': default: return typescript_1.default.ScriptKind.JSX; } } function isSvelteFilePath(filePath) { return filePath.endsWith('.svelte'); } function isVirtualSvelteFilePath(filePath) { return filePath.endsWith('.d.svelte.ts'); } function toRealSvelteFilePath(filePath) { return filePath.slice(0, -11 /* 'd.svelte.ts'.length */) + 'svelte'; } function toVirtualSvelteFilePath(svelteFilePath) { return isVirtualSvelteFilePath(svelteFilePath) ? svelteFilePath : svelteFilePath.slice(0, -6 /* 'svelte'.length */) + 'd.svelte.ts'; } function ensureRealSvelteFilePath(filePath) { return isVirtualSvelteFilePath(filePath) ? toRealSvelteFilePath(filePath) : filePath; } function convertRange(document, range) { return vscode_languageserver_1.Range.create(document.positionAt(range.start || 0), document.positionAt((range.start || 0) + (range.length || 0))); } function convertToLocationRange(snapshot, textSpan) { const range = (0, documents_1.mapRangeToOriginal)(snapshot, convertRange(snapshot, textSpan)); mapUnmappedToTheStartOfFile(range); return range; } function convertToLocationForReferenceOrDefinition(snapshot, textSpan) { const location = (0, documents_1.mapLocationToOriginal)(snapshot, convertRange(snapshot, textSpan)); mapUnmappedToTheStartOfFile(location.range); return location; } /**Some definition like the svelte component class definition don't exist in the original, so we map to 0,1*/ function mapUnmappedToTheStartOfFile(range) { if (range.start.line < 0) { range.start.line = 0; range.start.character = 1; } if (range.end.line < 0) { range.end = range.start; } } function hasNonZeroRange({ range }) { return (!!range && (range.start.line !== range.end.line || range.start.character !== range.end.character)); } function rangeToTextSpan(range, document) { const start = document.offsetAt(range.start); const end = document.offsetAt(range.end); return { start, length: end - start }; } function findTsConfigPath(fileName, rootUris, fileExists, getCanonicalFileName) { const searchDir = (0, path_1.dirname)(fileName); const tsconfig = typescript_1.default.findConfigFile(searchDir, fileExists, 'tsconfig.json') || ''; const jsconfig = typescript_1.default.findConfigFile(searchDir, fileExists, 'jsconfig.json') || ''; // Prefer closest config file const config = tsconfig.length >= jsconfig.length ? tsconfig : jsconfig; // Don't return config files that exceed the current workspace context or cross a node_modules folder return !!config && rootUris.some((rootUri) => isSubPath(rootUri, config, getCanonicalFileName)) && !fileName .substring(config.length - 13) .split('/') .includes('node_modules') ? config : ''; } function isSubPath(uri, possibleSubPath, getCanonicalFileName) { // URL escape codes are in upper-case // so getCanonicalFileName should be called after converting to file url return getCanonicalFileName((0, utils_1.pathToUrl)(possibleSubPath)).startsWith(getCanonicalFileName(uri)); } function getNearestWorkspaceUri(workspaceUris, path, getCanonicalFileName) { return Array.from(workspaceUris) .sort((a, b) => b.length - a.length) .find((workspaceUri) => isSubPath(workspaceUri, path, getCanonicalFileName)); } function symbolKindFromString(kind) { switch (kind) { case 'module': return vscode_languageserver_1.SymbolKind.Module; case 'class': return vscode_languageserver_1.SymbolKind.Class; case 'local class': return vscode_languageserver_1.SymbolKind.Class; case 'interface': return vscode_languageserver_1.SymbolKind.Interface; case 'enum': return vscode_languageserver_1.SymbolKind.Enum; case 'enum member': return vscode_languageserver_1.SymbolKind.Constant; case 'var': return vscode_languageserver_1.SymbolKind.Variable; case 'local var': return vscode_languageserver_1.SymbolKind.Variable; case 'function': return vscode_languageserver_1.SymbolKind.Function; case 'local function': return vscode_languageserver_1.SymbolKind.Function; case 'method': return vscode_languageserver_1.SymbolKind.Method; case 'getter': return vscode_languageserver_1.SymbolKind.Method; case 'setter': return vscode_languageserver_1.SymbolKind.Method; case 'property': return vscode_languageserver_1.SymbolKind.Property; case 'constructor': return vscode_languageserver_1.SymbolKind.Constructor; case 'parameter': return vscode_languageserver_1.SymbolKind.Variable; case 'type parameter': return vscode_languageserver_1.SymbolKind.Variable; case 'alias': return vscode_languageserver_1.SymbolKind.Variable; case 'let': return vscode_languageserver_1.SymbolKind.Variable; case 'const': return vscode_languageserver_1.SymbolKind.Constant; case 'JSX attribute': return vscode_languageserver_1.SymbolKind.Property; default: return vscode_languageserver_1.SymbolKind.Variable; } } function scriptElementKindToCompletionItemKind(kind) { switch (kind) { case typescript_1.default.ScriptElementKind.primitiveType: case typescript_1.default.ScriptElementKind.keyword: return vscode_languageserver_1.CompletionItemKind.Keyword; case typescript_1.default.ScriptElementKind.constElement: return vscode_languageserver_1.CompletionItemKind.Constant; case typescript_1.default.ScriptElementKind.letElement: case typescript_1.default.ScriptElementKind.variableElement: case typescript_1.default.ScriptElementKind.localVariableElement: case typescript_1.default.ScriptElementKind.alias: return vscode_languageserver_1.CompletionItemKind.Variable; case typescript_1.default.ScriptElementKind.memberVariableElement: case typescript_1.default.ScriptElementKind.memberGetAccessorElement: case typescript_1.default.ScriptElementKind.memberSetAccessorElement: return vscode_languageserver_1.CompletionItemKind.Field; case typescript_1.default.ScriptElementKind.functionElement: return vscode_languageserver_1.CompletionItemKind.Function; case typescript_1.default.ScriptElementKind.memberFunctionElement: case typescript_1.default.ScriptElementKind.constructSignatureElement: case typescript_1.default.ScriptElementKind.callSignatureElement: case typescript_1.default.ScriptElementKind.indexSignatureElement: return vscode_languageserver_1.CompletionItemKind.Method; case typescript_1.default.ScriptElementKind.enumElement: return vscode_languageserver_1.CompletionItemKind.Enum; case typescript_1.default.ScriptElementKind.moduleElement: case typescript_1.default.ScriptElementKind.externalModuleName: return vscode_languageserver_1.CompletionItemKind.Module; case typescript_1.default.ScriptElementKind.classElement: case typescript_1.default.ScriptElementKind.typeElement: return vscode_languageserver_1.CompletionItemKind.Class; case typescript_1.default.ScriptElementKind.interfaceElement: return vscode_languageserver_1.CompletionItemKind.Interface; case typescript_1.default.ScriptElementKind.warning: case typescript_1.default.ScriptElementKind.scriptElement: return vscode_languageserver_1.CompletionItemKind.File; case typescript_1.default.ScriptElementKind.directory: return vscode_languageserver_1.CompletionItemKind.Folder; case typescript_1.default.ScriptElementKind.string: return vscode_languageserver_1.CompletionItemKind.Constant; } return vscode_languageserver_1.CompletionItemKind.Property; } function mapSeverity(category) { switch (category) { case typescript_1.default.DiagnosticCategory.Error: return vscode_languageserver_1.DiagnosticSeverity.Error; case typescript_1.default.DiagnosticCategory.Warning: return vscode_languageserver_1.DiagnosticSeverity.Warning; case typescript_1.default.DiagnosticCategory.Suggestion: return vscode_languageserver_1.DiagnosticSeverity.Hint; case typescript_1.default.DiagnosticCategory.Message: return vscode_languageserver_1.DiagnosticSeverity.Information; } return vscode_languageserver_1.DiagnosticSeverity.Error; } // Matches comments that come before any non-comment content const commentsRegex = /^(\s*\/\/.*\s*)*/; // The following regex matches @ts-check or @ts-nocheck if: // - must be @ts-(no)check // - the comment which has @ts-(no)check can have any type of whitespace before it, but not other characters // - what's coming after @ts-(no)check is irrelevant as long there is any kind of whitespace or line break, so this would be picked up, too: // @ts-check asdasd // [ \t\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff] // is just \s (a.k.a any whitespace character) without linebreak and vertical tab const tsCheckRegex = /\/\/[ \t\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]*(@ts-(no)?check)($|\s)/; /** * Returns `// @ts-check` or `// @ts-nocheck` if content starts with comments and has one of these * in its comments. */ function getTsCheckComment(str = '') { const comments = str.match(commentsRegex)?.[0]; if (comments) { const tsCheck = comments.match(tsCheckRegex); if (tsCheck) { // second-last entry is the capturing group with the exact ts-check wording return `// ${tsCheck[tsCheck.length - 3]}${typescript_1.default.sys.newLine}`; } } } function convertToTextSpan(range, snapshot) { const start = snapshot.offsetAt(snapshot.getGeneratedPosition(range.start)); const end = snapshot.offsetAt(snapshot.getGeneratedPosition(range.end)); return { start, length: end - start }; } function isInScript(position, snapshot) { return (0, documents_1.isInTag)(position, snapshot.scriptInfo) || (0, documents_1.isInTag)(position, snapshot.moduleScriptInfo); } function getDiagnosticTag(diagnostic) { const tags = []; if (diagnostic.reportsUnnecessary) { tags.push(vscode_languageserver_1.DiagnosticTag.Unnecessary); } if (diagnostic.reportsDeprecated) { tags.push(vscode_languageserver_1.DiagnosticTag.Deprecated); } return tags; } function changeSvelteComponentName(name) { return name.replace(/(\w+)__SvelteComponent_/, '$1'); } const COMPONENT_SUFFIX = '__SvelteComponent_'; function isGeneratedSvelteComponentName(className) { return className.endsWith(COMPONENT_SUFFIX); } function offsetOfGeneratedComponentExport(snapshot) { return snapshot.getFullText().lastIndexOf(COMPONENT_SUFFIX); } function toGeneratedSvelteComponentName(className) { return className + COMPONENT_SUFFIX; } function hasTsExtensions(fileName) { return (fileName.endsWith(typescript_1.default.Extension.Dts) || fileName.endsWith(typescript_1.default.Extension.Tsx) || fileName.endsWith(typescript_1.default.Extension.Ts)); } function isSvelte2tsxShimFile(fileName) { return fileName?.endsWith('svelte-shims.d.ts') || fileName?.endsWith('svelte-shims-v4.d.ts'); } //# sourceMappingURL=utils.js.map