UNPKG

atom-languageclient

Version:
119 lines 15.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getExePath = exports.exeExtentionDefault = exports.rootPathDefault = exports.promiseWithTimeout = exports.assertUnreachable = exports.doWithCancellationToken = exports.cancelAndRefreshCancellationToken = exports.escapeRegExp = exports.getWordAtPosition = void 0; const path_1 = require("path"); const fs_1 = require("fs"); const atom_1 = require("atom"); const vscode_jsonrpc_1 = require("vscode-jsonrpc"); /** Obtain the range of the word at the given editor position. Uses the non-word characters from the position's grammar scope. */ function getWordAtPosition(editor, position) { const nonWordCharacters = escapeRegExp(editor.getNonWordCharacters(position)); const range = _getRegexpRangeAtPosition(editor.getBuffer(), position, new RegExp(`^[\t ]*$|[^\\s${nonWordCharacters}]+`, "g")); if (range == null) { return new atom_1.Range(position, position); } return range; } exports.getWordAtPosition = getWordAtPosition; function escapeRegExp(string) { // From atom/underscore-plus. return string.replace(/[$()*+./?[\\\]^{|}-]/g, "\\$&"); } exports.escapeRegExp = escapeRegExp; function _getRegexpRangeAtPosition(buffer, position, wordRegex) { const { row, column } = position; const rowRange = buffer.rangeForRow(row, false); let matchData; // Extract the expression from the row text. buffer.scanInRange(wordRegex, rowRange, (data) => { const { range } = data; if (position.isGreaterThanOrEqual(range.start) && // Range endpoints are exclusive. position.isLessThan(range.end)) { matchData = data; data.stop(); return; } // Stop the scan if the scanner has passed our position. if (range.end.column > column) { data.stop(); } }); return matchData == null ? null : matchData.range; } /** * For the given connection and cancellationTokens map, cancel the existing CancellationToken for that connection then * create and store a new CancellationToken to be used for the current request. */ function cancelAndRefreshCancellationToken(key, cancellationTokens) { let cancellationToken = cancellationTokens.get(key); if (cancellationToken !== undefined && !cancellationToken.token.isCancellationRequested) { cancellationToken.cancel(); } cancellationToken = new vscode_jsonrpc_1.CancellationTokenSource(); cancellationTokens.set(key, cancellationToken); return cancellationToken.token; } exports.cancelAndRefreshCancellationToken = cancelAndRefreshCancellationToken; function doWithCancellationToken(key, cancellationTokens, work) { return __awaiter(this, void 0, void 0, function* () { const token = cancelAndRefreshCancellationToken(key, cancellationTokens); const result = yield work(token); cancellationTokens.delete(key); return result; }); } exports.doWithCancellationToken = doWithCancellationToken; function assertUnreachable(_) { return _; } exports.assertUnreachable = assertUnreachable; function promiseWithTimeout(ms, promise) { return new Promise((resolve, reject) => { // create a timeout to reject promise if not resolved const timer = setTimeout(() => { reject(new Error(`Timeout after ${ms}ms`)); }, ms); promise .then((res) => { clearTimeout(timer); resolve(res); }) .catch((err) => { clearTimeout(timer); reject(err); }); }); } exports.promiseWithTimeout = promiseWithTimeout; exports.rootPathDefault = path_1.join("bin", `${process.platform}-${process.arch}`); exports.exeExtentionDefault = process.platform === "win32" ? ".exe" : ""; /** * Finds an exe file in the package assuming it is placed under `rootPath/platform-arch/exe`. If the exe file did not * exist, the given name is returned. For example on Windows x64, if the `exeName` is `serve-d`, it returns the absolute * path to `./bin/win32-x64/exeName.exe`, and if the file did not exist, `serve-d` is returned. * * @param exeName Name of the exe file * @param rootPath The path of the folder of the exe file. Defaults to 'join("bin", `${process.platform}-${process.arch}`)' * @param exeExtention The extention of the exe file. Defaults to `process.platform === "win32" ? ".exe" : ""` */ function getExePath(exeName, rootPath = exports.rootPathDefault, exeExtention = exports.exeExtentionDefault) { const exePath = path_1.resolve(path_1.join(rootPath, `${exeName}${exeExtention}`)); if (fs_1.existsSync(exePath)) { return exePath; } else { return exeName; } } exports.getExePath = getExePath; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUEsK0JBQW9DO0FBQ3BDLDJCQUErQjtBQUMvQiwrQkFBNkU7QUFDN0UsbURBQTJFO0FBSTNFLGlJQUFpSTtBQUNqSSxTQUFnQixpQkFBaUIsQ0FBQyxNQUFrQixFQUFFLFFBQWU7SUFDbkUsTUFBTSxpQkFBaUIsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUE7SUFDN0UsTUFBTSxLQUFLLEdBQUcseUJBQXlCLENBQ3JDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsRUFDbEIsUUFBUSxFQUNSLElBQUksTUFBTSxDQUFDLGlCQUFpQixpQkFBaUIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUN4RCxDQUFBO0lBQ0QsSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFO1FBQ2pCLE9BQU8sSUFBSSxZQUFLLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFBO0tBQ3JDO0lBQ0QsT0FBTyxLQUFLLENBQUE7QUFDZCxDQUFDO0FBWEQsOENBV0M7QUFFRCxTQUFnQixZQUFZLENBQUMsTUFBYztJQUN6Qyw2QkFBNkI7SUFDN0IsT0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDLHVCQUF1QixFQUFFLE1BQU0sQ0FBQyxDQUFBO0FBQ3hELENBQUM7QUFIRCxvQ0FHQztBQUVELFNBQVMseUJBQXlCLENBQUMsTUFBa0IsRUFBRSxRQUFlLEVBQUUsU0FBaUI7SUFDdkYsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUE7SUFDaEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFDL0MsSUFBSSxTQUE4QyxDQUFBO0lBQ2xELDRDQUE0QztJQUM1QyxNQUFNLENBQUMsV0FBVyxDQUFDLFNB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UUFBQSxtQkFBbUIsR0FBRyxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUE7QUFFN0U7Ozs7Ozs7O0dBUUc7QUFDSCxTQUFnQixVQUFVLENBQUMsT0FBZSxFQUFFLFFBQVEsR0FBRyx1QkFBZSxFQUFFLFlBQVksR0FBRywyQkFBbUI7SUFDeEcsTUFBTSxPQUFPLEdBQUcsY0FBTyxDQUFDLFdBQUksQ0FBQyxRQUFRLEVBQUUsR0FBRyxPQUFPLEdBQUcsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3BFLElBQUksZUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ3ZCLE9BQU8sT0FBTyxDQUFBO0tBQ2Y7U0FBTTtRQUNMLE9BQU8sT0FBTyxDQUFBO0tBQ2Y7QUFDSCxDQUFDO0FBUEQsZ0NBT0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBqb2luLCByZXNvbHZlIH0gZnJvbSBcInBhdGhcIlxuaW1wb3J0IHsgZXhpc3RzU3luYyB9IGZyb20gXCJmc1wiXG5pbXBvcnQgeyBQb2ludCwgVGV4dEJ1ZmZlciwgVGV4dEVkaXRvciwgUmFuZ2UsIEJ1ZmZlclNjYW5SZXN1bHQgfSBmcm9tIFwiYXRvbVwiXG5pbXBvcnQgeyBDYW5jZWxsYXRpb25Ub2tlbiwgQ2FuY2VsbGF0aW9uVG9rZW5Tb3VyY2UgfSBmcm9tIFwidnNjb2RlLWpzb25ycGNcIlxuXG5leHBvcnQgdHlwZSBSZXBvcnRCdXN5V2hpbGUgPSA8VD4odGl0bGU6IHN0cmluZywgZjogKCkgPT4gUHJvbWlzZTxUPikgPT4gUHJvbWlzZTxUPlxuXG4vKiogT2J0YWluIHRoZSByYW5nZSBvZiB0aGUgd29yZCBhdCB0aGUgZ2l2ZW4gZWRpdG9yIHBvc2l0aW9uLiBVc2VzIHRoZSBub24td29yZCBjaGFyYWN0ZXJzIGZyb20gdGhlIHBvc2l0aW9uJ3MgZ3JhbW1hciBzY29wZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRXb3JkQXRQb3NpdGlvbihlZGl0b3I6IFRleHRFZGl0b3IsIHBvc2l0aW9uOiBQb2ludCk6IFJhbmdlIHtcbiAgY29uc3Qgbm9uV29yZENoYXJhY3RlcnMgPSBlc2NhcGVSZWdFeHAoZWRpdG9yLmdldE5vbldvcmRDaGFyYWN0ZXJzKHBvc2l0aW9uKSlcbiAgY29uc3QgcmFuZ2UgPSBfZ2V0UmVnZXhwUmFuZ2VBdFBvc2l0aW9uKFxuICAgIGVkaXRvci5nZXRCdWZmZXIoKSxcbiAgICBwb3NpdGlvbixcbiAgICBuZXcgUmVnRXhwKGBeW1xcdCBdKiR8W15cXFxccyR7bm9uV29yZENoYXJhY3RlcnN9XStgLCBcImdcIilcbiAgKVxuICBpZiAocmFuZ2UgPT0gbnVsbCkge1xuICAgIHJldHVybiBuZXcgUmFuZ2UocG9zaXRpb24sIHBvc2l0aW9uKVxuICB9XG4gIHJldHVybiByYW5nZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZXNjYXBlUmVnRXhwKHN0cmluZzogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gRnJvbSBhdG9tL3VuZGVyc2NvcmUtcGx1cy5cbiAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9bJCgpKisuLz9bXFxcXFxcXV57fH0tXS9nLCBcIlxcXFwkJlwiKVxufVxuXG5mdW5jdGlvbiBfZ2V0UmVnZXhwUmFuZ2VBdFBvc2l0aW9uKGJ1ZmZlcjogVGV4dEJ1ZmZlciwgcG9zaXRpb246IFBvaW50LCB3b3JkUmVnZXg6IFJlZ0V4cCk6IFJhbmdlIHwgbnVsbCB7XG4gIGNvbnN0IHsgcm93LCBjb2x1bW4gfSA9IHBvc2l0aW9uXG4gIGNvbnN0IHJvd1JhbmdlID0gYnVmZmVyLnJhbmdlRm9yUm93KHJvdywgZmFsc2UpXG4gIGxldCBtYXRjaERhdGE6IEJ1ZmZlclNjYW5SZXN1bHQgfCB1bmRlZmluZWQgfCBudWxsXG4gIC8vIEV4dHJhY3QgdGhlIGV4cHJlc3Npb24gZnJvbSB0aGUgcm93IHRleHQuXG4gIGJ1ZmZlci5zY2FuSW5SYW5nZSh3b3JkUmVnZXgsIHJvd1JhbmdlLCAoZGF0YSkgPT4ge1xuICAgIGNvbnN0IHsgcmFuZ2UgfSA9IGRhdGFcbiAgICBpZiAoXG4gICAgICBwb3NpdGlvbi5pc0dyZWF0ZXJUaGFuT3JFcXVhbChyYW5nZS5zdGFydCkgJiZcbiAgICAgIC8vIFJhbmdlIGVuZHBvaW50cyBhcmUgZXhjbHVzaXZlLlxuICAgICAgcG9zaXRpb24uaXNMZXNzVGhhbihyYW5nZS5lbmQpXG4gICAgKSB7XG4gICAgICBtYXRjaERhdGEgPSBkYXRhXG4gICAgICBkYXRhLnN0b3AoKVxuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIC8vIFN0b3AgdGhlIHNjYW4gaWYgdGhlIHNjYW5uZXIgaGFzIHBhc3NlZCBvdXIgcG9zaXRpb24uXG4gICAgaWYgKHJhbmdlLmVuZC5jb2x1bW4gPiBjb2x1bW4pIHtcbiAgICAgIGRhdGEuc3RvcCgpXG4gICAgfVxuICB9KVxuICByZXR1cm4gbWF0Y2hEYXRhID09IG51bGwgPyBudWxsIDogbWF0Y2hEYXRhLnJhbmdlXG59XG5cbi8qKlxuICogRm9yIHRoZSBnaXZlbiBjb25uZWN0aW9uIGFuZCBjYW5jZWxsYXRpb25Ub2tlbnMgbWFwLCBjYW5jZWwgdGhlIGV4aXN0aW5nIENhbmNlbGxhdGlvblRva2VuIGZvciB0aGF0IGNvbm5lY3Rpb24gdGhlblxuICogY3JlYXRlIGFuZCBzdG9yZSBhIG5ldyBDYW5jZWxsYXRpb25Ub2tlbiB0byBiZSB1c2VkIGZvciB0aGUgY3VycmVudCByZXF1ZXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FuY2VsQW5kUmVmcmVzaENhbmNlbGxhdGlvblRva2VuPFQgZXh0ZW5kcyBvYmplY3Q+KFxuICBrZXk6IFQsXG4gIGNhbmNlbGxhdGlvblRva2VuczogV2Vha01hcDxULCBDYW5jZWxsYXRpb25Ub2tlblNvdXJjZT5cbik6IENhbmNlbGxhdGlvblRva2VuIHtcbiAgbGV0IGNhbmNlbGxhdGlvblRva2VuID0gY2FuY2VsbGF0aW9uVG9rZW5zLmdldChrZXkpXG4gIGlmIChjYW5jZWxsYXRpb25Ub2tlbiAhPT0gdW5kZWZpbmVkICYmICFjYW5jZWxsYXRpb25Ub2tlbi50b2tlbi5pc0NhbmNlbGxhdGlvblJlcXVlc3RlZCkge1xuICAgIGNhbmNlbGxhdGlvblRva2VuLmNhbmNlbCgpXG4gIH1cblxuICBjYW5jZWxsYXRpb25Ub2tlbiA9IG5ldyBDYW5jZWxsYXRpb25Ub2tlblNvdXJjZSgpXG4gIGNhbmNlbGxhdGlvblRva2Vucy5zZXQoa2V5LCBjYW5jZWxsYXRpb25Ub2tlbilcbiAgcmV0dXJuIGNhbmNlbGxhdGlvblRva2VuLnRva2VuXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb1dpdGhDYW5jZWxsYXRpb25Ub2tlbjxUMSBleHRlbmRzIG9iamVjdCwgVDI+KFxuICBrZXk6IFQxLFxuICBjYW5jZWxsYXRpb25Ub2tlbnM6IFdlYWtNYXA8VDEsIENhbmNlbGxhdGlvblRva2VuU291cmNlPixcbiAgd29yazogKHRva2VuOiBDYW5jZWxsYXRpb25Ub2tlbikgPT4gUHJvbWlzZTxUMj5cbik6IFByb21pc2U8VDI+IHtcbiAgY29uc3QgdG9rZW4gPSBjYW5jZWxBbmRSZWZyZXNoQ2FuY2VsbGF0aW9uVG9rZW4oa2V5LCBjYW5jZWxsYXRpb25Ub2tlbnMpXG4gIGNvbnN0IHJlc3VsdDogVDIgPSBhd2FpdCB3b3JrKHRva2VuKVxuICBjYW5jZWxsYXRpb25Ub2tlbnMuZGVsZXRlKGtleSlcbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0VW5yZWFjaGFibGUoXzogbmV2ZXIpOiBuZXZlciB7XG4gIHJldHVybiBfXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcm9taXNlV2l0aFRpbWVvdXQ8VD4obXM6IG51bWJlciwgcHJvbWlzZTogUHJvbWlzZTxUPik6IFByb21pc2U8VD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIC8vIGNyZWF0ZSBhIHRpbWVvdXQgdG8gcmVqZWN0IHByb21pc2UgaWYgbm90IHJlc29sdmVkXG4gICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHJlamVjdChuZXcgRXJyb3IoYFRpbWVvdXQgYWZ0ZXIgJHttc31tc2ApKVxuICAgIH0sIG1zKVxuXG4gICAgcHJvbWlzZVxuICAgICAgLnRoZW4oKHJlcykgPT4ge1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpXG4gICAgICAgIHJlc29sdmUocmVzKVxuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lcilcbiAgICAgICAgcmVqZWN0KGVycilcbiAgICAgIH0pXG4gIH0pXG59XG5cbmV4cG9ydCBjb25zdCByb290UGF0aERlZmF1bHQgPSBqb2luKFwiYmluXCIsIGAke3Byb2Nlc3MucGxhdGZvcm19LSR7cHJvY2Vzcy5hcmNofWApXG5leHBvcnQgY29uc3QgZXhlRXh0ZW50aW9uRGVmYXVsdCA9IHByb2Nlc3MucGxhdGZvcm0gPT09IFwid2luMzJcIiA/IFwiLmV4ZVwiIDogXCJcIlxuXG4vKipcbiAqIEZpbmRzIGFuIGV4ZSBmaWxlIGluIHRoZSBwYWNrYWdlIGFzc3VtaW5nIGl0IGlzIHBsYWNlZCB1bmRlciBgcm9vdFBhdGgvcGxhdGZvcm0tYXJjaC9leGVgLiBJZiB0aGUgZXhlIGZpbGUgZGlkIG5vdFxuICogZXhpc3QsIHRoZSBnaXZlbiBuYW1lIGlzIHJldHVybmVkLiBGb3IgZXhhbXBsZSBvbiBXaW5kb3dzIHg2NCwgaWYgdGhlIGBleGVOYW1lYCBpcyBgc2VydmUtZGAsIGl0IHJldHVybnMgdGhlIGFic29sdXRlXG4gKiBwYXRoIHRvIGAuL2Jpbi93aW4zMi14NjQvZXhlTmFtZS5leGVgLCBhbmQgaWYgdGhlIGZpbGUgZGlkIG5vdCBleGlzdCwgYHNlcnZlLWRgIGlzIHJldHVybmVkLlxuICpcbiAqIEBwYXJhbSBleGVOYW1lIE5hbWUgb2YgdGhlIGV4ZSBmaWxlXG4gKiBAcGFyYW0gcm9vdFBhdGggVGhlIHBhdGggb2YgdGhlIGZvbGRlciBvZiB0aGUgZXhlIGZpbGUuIERlZmF1bHRzIHRvICdqb2luKFwiYmluXCIsIGAke3Byb2Nlc3MucGxhdGZvcm19LSR7cHJvY2Vzcy5hcmNofWApJ1xuICogQHBhcmFtIGV4ZUV4dGVudGlvbiBUaGUgZXh0ZW50aW9uIG9mIHRoZSBleGUgZmlsZS4gRGVmYXVsdHMgdG8gYHByb2Nlc3MucGxhdGZvcm0gPT09IFwid2luMzJcIiA/IFwiLmV4ZVwiIDogXCJcImBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEV4ZVBhdGgoZXhlTmFtZTogc3RyaW5nLCByb290UGF0aCA9IHJvb3RQYXRoRGVmYXVsdCwgZXhlRXh0ZW50aW9uID0gZXhlRXh0ZW50aW9uRGVmYXVsdCk6IHN0cmluZyB7XG4gIGNvbnN0IGV4ZVBhdGggPSByZXNvbHZlKGpvaW4ocm9vdFBhdGgsIGAke2V4ZU5hbWV9JHtleGVFeHRlbnRpb259YCkpXG4gIGlmIChleGlzdHNTeW5jKGV4ZVBhdGgpKSB7XG4gICAgcmV0dXJuIGV4ZVBhdGhcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZXhlTmFtZVxuICB9XG59XG4iXX0=