UNPKG

svelte-language-server

Version:
334 lines 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.not = not; exports.or = or; exports.and = and; exports.unique = unique; exports.clamp = clamp; exports.urlToPath = urlToPath; exports.pathToUrl = pathToUrl; exports.normalizePath = normalizePath; exports.normalizeUri = normalizeUri; exports.getLastPartOfPath = getLastPartOfPath; exports.flatten = flatten; exports.passMap = passMap; exports.isInRange = isInRange; exports.isZeroLengthRange = isZeroLengthRange; exports.isRangeStartAfterEnd = isRangeStartAfterEnd; exports.swapRangeStartEndIfNecessary = swapRangeStartEndIfNecessary; exports.moveRangeStartToEndIfNecessary = moveRangeStartToEndIfNecessary; exports.isBeforeOrEqualToPosition = isBeforeOrEqualToPosition; exports.isPositionEqual = isPositionEqual; exports.isNotNullOrUndefined = isNotNullOrUndefined; exports.debounceSameArg = debounceSameArg; exports.debounceThrottle = debounceThrottle; exports.regexLastIndexOf = regexLastIndexOf; exports.regexIndexOf = regexIndexOf; exports.getRegExpMatches = getRegExpMatches; exports.modifyLines = modifyLines; exports.isSamePosition = isSamePosition; exports.filterAsync = filterAsync; exports.getIndent = getIndent; exports.possiblyComponent = possiblyComponent; exports.returnObjectIfHasKeys = returnObjectIfHasKeys; exports.toFileNameLowerCase = toFileNameLowerCase; exports.createGetCanonicalFileName = createGetCanonicalFileName; exports.memoize = memoize; exports.removeLineWithString = removeLineWithString; exports.traverseTypeString = traverseTypeString; const lodash_1 = require("lodash"); const vscode_uri_1 = require("vscode-uri"); function not(predicate) { return (x) => !predicate(x); } function or(...predicates) { return (x) => predicates.some((predicate) => predicate(x)); } function and(...predicates) { return (x) => predicates.every((predicate) => predicate(x)); } function unique(array) { return (0, lodash_1.uniqWith)(array, lodash_1.isEqual); } function clamp(num, min, max) { return Math.max(min, Math.min(max, num)); } function urlToPath(stringUrl) { const url = vscode_uri_1.URI.parse(stringUrl); if (url.scheme !== 'file') { return null; } return url.fsPath.replace(/\\/g, '/'); } function pathToUrl(path) { return vscode_uri_1.URI.file(path).toString(); } /** * Some paths (on windows) start with a upper case driver letter, some don't. * This is normalized here. */ function normalizePath(path) { return vscode_uri_1.URI.file(path).fsPath.replace(/\\/g, '/'); } /** * URIs coming from the client could be encoded in a different * way than expected / than the internal services create them. * This normalizes them to be the same as the internally generated ones. */ function normalizeUri(uri) { return vscode_uri_1.URI.parse(uri).toString(); } /** * Given a path like foo/bar or foo/bar.svelte , returns its last path * (bar or bar.svelte in this example). */ function getLastPartOfPath(path) { return path.replace(/\\/g, '/').split('/').pop() || ''; } function flatten(arr) { return arr.reduce((all, item) => (Array.isArray(item) ? [...all, ...item] : [...all, item]), []); } /** * Map or keep original (passthrough) if the mapper returns undefined. */ function passMap(array, mapper) { return array.map((x) => { const mapped = mapper(x); return mapped === undefined ? x : mapped; }); } function isInRange(range, positionToTest) { return (isBeforeOrEqualToPosition(range.end, positionToTest) && isBeforeOrEqualToPosition(positionToTest, range.start)); } function isZeroLengthRange(range) { return isPositionEqual(range.start, range.end); } function isRangeStartAfterEnd(range) { return (range.end.line < range.start.line || (range.end.line === range.start.line && range.end.character < range.start.character)); } function swapRangeStartEndIfNecessary(range) { if (isRangeStartAfterEnd(range)) { const start = range.start; range.start = range.end; range.end = start; } return range; } function moveRangeStartToEndIfNecessary(range) { if (isRangeStartAfterEnd(range)) { range.start = range.end; } return range; } function isBeforeOrEqualToPosition(position, positionToTest) { return (positionToTest.line < position.line || (positionToTest.line === position.line && positionToTest.character <= position.character)); } function isPositionEqual(position1, position2) { return position1.line === position2.line && position1.character === position2.character; } function isNotNullOrUndefined(val) { return val !== undefined && val !== null; } /** * Debounces a function but cancels previous invocation only if * a second function determines it should. * * @param fn The function with it's argument * @param determineIfSame The function which determines if the previous invocation should be canceld or not * @param miliseconds Number of miliseconds to debounce */ function debounceSameArg(fn, shouldCancelPrevious, miliseconds) { let timeout; let prevArg; return (arg) => { if (shouldCancelPrevious(arg, prevArg)) { clearTimeout(timeout); } prevArg = arg; timeout = setTimeout(() => { fn(arg); prevArg = undefined; }, miliseconds); }; } /** * Debounces a function but also waits at minimum the specified number of miliseconds until * the next invocation. This avoids needless calls when a synchronous call (like diagnostics) * took too long and the whole timeout of the next call was eaten up already. * * @param fn The function * @param miliseconds Number of miliseconds to debounce/throttle */ function debounceThrottle(fn, miliseconds) { let timeout; let lastInvocation = Date.now() - miliseconds; function maybeCall() { clearTimeout(timeout); timeout = setTimeout(() => { if (Date.now() - lastInvocation < miliseconds) { maybeCall(); return; } fn(); lastInvocation = Date.now(); }, miliseconds); } return maybeCall; } /** * Like str.lastIndexOf, but for regular expressions. Note that you need to provide the g-flag to your RegExp! */ function regexLastIndexOf(text, regex, endPos) { if (endPos === undefined) { endPos = text.length; } else if (endPos < 0) { endPos = 0; } const stringToWorkWith = text.substring(0, endPos + 1); let lastIndexOf = -1; let result = null; while ((result = regex.exec(stringToWorkWith)) !== null) { lastIndexOf = result.index; } return lastIndexOf; } /** * Like str.indexOf, but for regular expressions. */ function regexIndexOf(text, regex, startPos) { if (startPos === undefined || startPos < 0) { startPos = 0; } const stringToWorkWith = text.substring(startPos); const result = regex.exec(stringToWorkWith); return result?.index ?? -1; } /** * Get all matches of a regexp. */ function getRegExpMatches(regex, str) { const matches = []; let match; while ((match = regex.exec(str))) { matches.push(match); } return matches; } /** * Function to modify each line of a text, preserving the line break style (`\n` or `\r\n`) */ function modifyLines(text, replacementFn) { let idx = 0; return text .split('\r\n') .map((l1) => l1 .split('\n') .map((line) => replacementFn(line, idx++)) .join('\n')) .join('\r\n'); } function isSamePosition(position, another) { return position.line === another.line && position.character === another.character; } /** * Like array.filter, but asynchronous */ async function filterAsync(array, predicate) { const fail = Symbol(); return (await Promise.all(array.map(async (item, idx) => ((await predicate(item, idx)) ? item : fail)))).filter((i) => i !== fail); } function getIndent(text) { return /^[ |\t]+/.exec(text)?.[0] ?? ''; } function possiblyComponent(nodeOrTagName) { return !!(typeof nodeOrTagName === 'object' ? nodeOrTagName.tag : nodeOrTagName)?.[0].match(/[A-Z]/); } /** * If the object if it has entries, else undefined */ function returnObjectIfHasKeys(obj) { if (Object.keys(obj || {}).length > 0) { return obj; } } const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_\. ]+/g; /** * adopted from https://github.com/microsoft/TypeScript/blob/8192d550496d884263e292488e325ae96893dc78/src/compiler/core.ts#L1769-L1807 * see the comment there about why we can't just use String.prototype.toLowerCase() here */ function toFileNameLowerCase(x) { return fileNameLowerCaseRegExp.test(x) ? x.replace(fileNameLowerCaseRegExp, toLowerCase) : x; } function toLowerCase(x) { return x.toLowerCase(); } /** * adopted from https://github.com/microsoft/TypeScript/blob/8192d550496d884263e292488e325ae96893dc78/src/compiler/core.ts#L2312 */ function createGetCanonicalFileName(useCaseSensitiveFileNames) { return useCaseSensitiveFileNames ? identity : toFileNameLowerCase; } function identity(x) { return x; } function memoize(callback) { let value; let callbackInner = callback; return () => { if (callbackInner) { value = callback(); callbackInner = undefined; } return value; }; } function removeLineWithString(str, keyword) { const lines = str.split('\n'); const filteredLines = lines.filter((line) => !line.includes(keyword)); return filteredLines.join('\n'); } /** * Traverses a string and returns the index of the end character, taking into account quotes, curlies and generic tags. */ function traverseTypeString(str, start, endChar) { let singleQuoteOpen = false; let doubleQuoteOpen = false; let countCurlyBrace = 0; let countAngleBracket = 0; for (let i = start; i < str.length; i++) { const char = str[i]; if (!doubleQuoteOpen && char === "'") { singleQuoteOpen = !singleQuoteOpen; } else if (!singleQuoteOpen && char === '"') { doubleQuoteOpen = !doubleQuoteOpen; } else if (!doubleQuoteOpen && !singleQuoteOpen) { if (char === '{') { countCurlyBrace++; } else if (char === '}') { countCurlyBrace--; } else if (char === '<') { countAngleBracket++; } else if (char === '>') { countAngleBracket--; } } if (!singleQuoteOpen && !doubleQuoteOpen && countCurlyBrace === 0 && countAngleBracket === 0 && char === endChar) { return i; } } return -1; } //# sourceMappingURL=utils.js.map