UNPKG

vscode-languageclient

Version:
703 lines (702 loc) 31.8 kB
"use strict"; /* -------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.DidSaveTextDocumentFeature = exports.WillSaveWaitUntilFeature = exports.WillSaveFeature = exports.DidChangeTextDocumentFeature = exports.DidCloseTextDocumentFeature = exports.DidOpenTextDocumentFeature = void 0; const vscode_1 = require("vscode"); const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol"); const features_1 = require("./features"); const UUID = __importStar(require("./utils/uuid")); const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument"); class DidOpenTextDocumentFeature extends features_1.TextDocumentEventFeature { _syncedDocuments; _pendingOpenNotifications; _delayOpen; _pendingOpenListeners; constructor(client, syncedDocuments) { super(client, vscode_1.workspace.onDidOpenTextDocument, vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type, () => client.middleware.didOpen, (textDocument) => client.code2ProtocolConverter.asOpenTextDocumentParams(textDocument), (data) => data, features_1.TextDocumentEventFeature.textDocumentFilter); this._syncedDocuments = syncedDocuments; this._pendingOpenNotifications = new Map(); this._delayOpen = client.clientOptions.textSynchronization?.delayOpenNotifications ?? false; } async callback(document) { if (!this._delayOpen) { return super.callback(document); } else { if (!this.matches(document)) { return; } const visibleDocuments = this._client.visibleDocuments; if (visibleDocuments.isVisible(document)) { return super.callback(document); } else { // Snapshot the text document so that when we send the delayed // notification it is based on the content/version at the time // it would've been sent, and not the updated version. // // See https://github.com/microsoft/vscode-languageserver-node/issues/1695 const snapshot = new TextDocumentSnapshot(document); this._pendingOpenNotifications.set(snapshot.uri.toString(), snapshot); } } } get openDocuments() { return this._syncedDocuments.values(); } fillClientCapabilities(capabilities) { (0, features_1.ensure)((0, features_1.ensure)(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true; } initialize(capabilities, documentSelector) { const textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.openClose) { this.register({ id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } }); } } get registrationType() { return vscode_languageserver_protocol_1.DidOpenTextDocumentNotification.type; } register(data) { super.register(data); if (!data.registerOptions.documentSelector) { return; } const documentSelector = this._client.protocol2CodeConverter.asDocumentSelector(data.registerOptions.documentSelector); vscode_1.workspace.textDocuments.forEach((textDocument) => { const uri = textDocument.uri.toString(); if (this._syncedDocuments.has(uri)) { return; } if (vscode_1.languages.match(documentSelector, textDocument) > 0 && !this._client.hasDedicatedTextSynchronizationFeature(textDocument)) { const visibleDocuments = this._client.visibleDocuments; if (visibleDocuments.isVisible(textDocument)) { const middleware = this._client.middleware; const didOpen = (textDocument) => { return this._client.sendNotification(this._type, this._createParams(textDocument)); }; (middleware.didOpen ? middleware.didOpen(textDocument, didOpen) : didOpen(textDocument)).catch((error) => { this._client.error(`Sending document notification ${this._type.method} failed`, error); }); this._syncedDocuments.set(uri, textDocument); } else { this._pendingOpenNotifications.set(uri, textDocument); } } }); if (this._delayOpen && this._pendingOpenListeners === undefined) { this._pendingOpenListeners = []; const visibleDocuments = this._client.visibleDocuments; this._pendingOpenListeners.push(visibleDocuments.onClose((closed) => { for (const uri of closed) { this._pendingOpenNotifications.delete(uri.toString()); } })); this._pendingOpenListeners.push(visibleDocuments.onOpen((opened) => { for (const uri of opened) { const document = this._pendingOpenNotifications.get(uri.toString()); if (document !== undefined) { super.callback(document).catch(((error) => { this._client.error(`Sending document notification ${this._type.method} failed`, error); })); this._pendingOpenNotifications.delete(uri.toString()); } } })); this._pendingOpenListeners.push(vscode_1.workspace.onDidCloseTextDocument((document) => { this._pendingOpenNotifications.delete(document.uri.toString()); })); } } /** * Sends any pending open notifications unless they are for the document * being closed. * * @param closingDocument The document being closed. * @returns Whether a pending open notification was dropped because it was * for the closing document. */ async sendPendingOpenNotifications(closingDocument) { const notifications = Array.from(this._pendingOpenNotifications.values()); this._pendingOpenNotifications.clear(); let didDropOpenNotification = false; for (const notification of notifications) { if (closingDocument !== undefined && notification.uri.toString() === closingDocument) { didDropOpenNotification = true; continue; } await super.callback(notification); } return didDropOpenNotification; } getTextDocument(data) { return data; } notificationSent(textDocument, type, params) { this._syncedDocuments.set(textDocument.uri.toString(), textDocument); super.notificationSent(textDocument, type, params); } clear() { this._pendingOpenNotifications.clear(); if (this._pendingOpenListeners !== undefined) { for (const listener of this._pendingOpenListeners) { listener.dispose(); } this._pendingOpenListeners = undefined; } super.clear(); } } exports.DidOpenTextDocumentFeature = DidOpenTextDocumentFeature; class DidCloseTextDocumentFeature extends features_1.TextDocumentEventFeature { _syncedDocuments; _pendingTextDocumentChanges; constructor(client, syncedDocuments, pendingTextDocumentChanges) { super(client, vscode_1.workspace.onDidCloseTextDocument, vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type, () => client.middleware.didClose, (textDocument) => client.code2ProtocolConverter.asCloseTextDocumentParams(textDocument), (data) => data, features_1.TextDocumentEventFeature.textDocumentFilter); this._syncedDocuments = syncedDocuments; this._pendingTextDocumentChanges = pendingTextDocumentChanges; } get registrationType() { return vscode_languageserver_protocol_1.DidCloseTextDocumentNotification.type; } fillClientCapabilities(capabilities) { (0, features_1.ensure)((0, features_1.ensure)(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true; } initialize(capabilities, documentSelector) { const textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.openClose) { this.register({ id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } }); } } async callback(data) { await super.callback(data); this._pendingTextDocumentChanges.delete(data.uri.toString()); } getTextDocument(data) { return data; } notificationSent(textDocument, type, params) { this._syncedDocuments.delete(textDocument.uri.toString()); super.notificationSent(textDocument, type, params); } unregister(id) { const selector = this._selectors.get(id); if (selector === undefined) { return; } // The super call removed the selector from the map // of selectors. super.unregister(id); const selectors = this._selectors.values(); this._syncedDocuments.forEach((textDocument) => { if (vscode_1.languages.match(selector, textDocument) > 0 && !this._selectorFilter(selectors, textDocument) && !this._client.hasDedicatedTextSynchronizationFeature(textDocument)) { const middleware = this._client.middleware; const didClose = (textDocument) => { return this._client.sendNotification(this._type, this._createParams(textDocument)); }; this._syncedDocuments.delete(textDocument.uri.toString()); (middleware.didClose ? middleware.didClose(textDocument, didClose) : didClose(textDocument)).catch((error) => { this._client.error(`Sending document notification ${this._type.method} failed`, error); }); } }); } } exports.DidCloseTextDocumentFeature = DidCloseTextDocumentFeature; class DidChangeTextDocumentFeature extends features_1.DynamicDocumentFeature { _listener; _changeData; _onAboutToSendNotification; _onNotificationSent; _onPendingChangeAdded; _pendingTextDocumentChanges; _syncKind; constructor(client, pendingTextDocumentChanges) { super(client); this._changeData = new Map(); this._onAboutToSendNotification = new vscode_1.EventEmitter(); this._onNotificationSent = new vscode_1.EventEmitter(); this._onPendingChangeAdded = new vscode_1.EventEmitter(); this._pendingTextDocumentChanges = pendingTextDocumentChanges; this._syncKind = vscode_languageserver_protocol_1.TextDocumentSyncKind.None; } get onAboutToSendNotification() { return this._onAboutToSendNotification.event; } get onNotificationSent() { return this._onNotificationSent.event; } get onPendingChangeAdded() { return this._onPendingChangeAdded.event; } get syncKind() { return this._syncKind; } get registrationType() { return vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type; } fillClientCapabilities(capabilities) { (0, features_1.ensure)((0, features_1.ensure)(capabilities, 'textDocument'), 'synchronization').dynamicRegistration = true; } initialize(capabilities, documentSelector) { const textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.change !== undefined && textDocumentSyncOptions.change !== vscode_languageserver_protocol_1.TextDocumentSyncKind.None) { this.register({ id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }, { syncKind: textDocumentSyncOptions.change }) }); } } register(data) { if (!data.registerOptions.documentSelector) { return; } if (!this._listener) { this._listener = vscode_1.workspace.onDidChangeTextDocument(this.callback, this); } this._changeData.set(data.id, { syncKind: data.registerOptions.syncKind, documentSelector: this._client.protocol2CodeConverter.asDocumentSelector(data.registerOptions.documentSelector), }); this.updateSyncKind(data.registerOptions.syncKind); } *getDocumentSelectors() { for (const data of this._changeData.values()) { yield data.documentSelector; } } async callback(event) { // Text document changes are send for dirty changes as well. We don't // have dirty / un-dirty events in the LSP so we ignore content changes // with length zero. if (event.contentChanges.length === 0) { return; } // We need to capture the URI and version here since they might change on the text document // until we reach did `didChange` call since the middleware support async execution. const uri = event.document.uri; const version = event.document.version; const promises = []; for (const changeData of this._changeData.values()) { if (vscode_1.languages.match(changeData.documentSelector, event.document) > 0 && !this._client.hasDedicatedTextSynchronizationFeature(event.document)) { const middleware = this._client.middleware; if (changeData.syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Incremental) { const didChange = async (event) => { const params = this._client.code2ProtocolConverter.asChangeTextDocumentParams(event, uri, version); this.aboutToSendNotification(event.document, vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, params); await this._client.sendNotification(vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, params); this.notificationSent(event.document, vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type, params); }; promises.push(middleware.didChange ? middleware.didChange(event, event => didChange(event)) : didChange(event)); } else if (changeData.syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Full) { const didChange = async (event) => { const eventUri = event.document.uri.toString(); this._pendingTextDocumentChanges.set(eventUri, event.document); this._onPendingChangeAdded.fire(); }; promises.push(middleware.didChange ? middleware.didChange(event, event => didChange(event)) : didChange(event)); } } } return Promise.all(promises).then(undefined, (error) => { this._client.error(`Sending document notification ${vscode_languageserver_protocol_1.DidChangeTextDocumentNotification.type.method} failed`, error); throw error; }); } aboutToSendNotification(textDocument, type, params) { this._onAboutToSendNotification.fire({ textDocument, type, params }); } notificationSent(textDocument, type, params) { this._onNotificationSent.fire({ textDocument, type, params }); } unregister(id) { this._changeData.delete(id); if (this._changeData.size === 0) { if (this._listener) { this._listener.dispose(); this._listener = undefined; } this._syncKind = vscode_languageserver_protocol_1.TextDocumentSyncKind.None; } else { this._syncKind = vscode_languageserver_protocol_1.TextDocumentSyncKind.None; for (const changeData of this._changeData.values()) { this.updateSyncKind(changeData.syncKind); if (this._syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Full) { break; } } } } clear() { this._pendingTextDocumentChanges.clear(); this._changeData.clear(); this._syncKind = vscode_languageserver_protocol_1.TextDocumentSyncKind.None; if (this._listener) { this._listener.dispose(); this._listener = undefined; } } getPendingDocumentChanges(excludes) { if (this._pendingTextDocumentChanges.size === 0) { return []; } let result; if (excludes.size === 0) { result = Array.from(this._pendingTextDocumentChanges.values()); this._pendingTextDocumentChanges.clear(); } else { result = []; for (const entry of this._pendingTextDocumentChanges) { if (!excludes.has(entry[0])) { result.push(entry[1]); this._pendingTextDocumentChanges.delete(entry[0]); } } } return result; } getProvider(document) { for (const changeData of this._changeData.values()) { if (vscode_1.languages.match(changeData.documentSelector, document) > 0) { return { send: (event) => { return this.callback(event); } }; } } return undefined; } updateSyncKind(syncKind) { if (this._syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.Full) { return; } switch (syncKind) { case vscode_languageserver_protocol_1.TextDocumentSyncKind.Full: this._syncKind = syncKind; break; case vscode_languageserver_protocol_1.TextDocumentSyncKind.Incremental: if (this._syncKind === vscode_languageserver_protocol_1.TextDocumentSyncKind.None) { this._syncKind = vscode_languageserver_protocol_1.TextDocumentSyncKind.Incremental; } break; } } } exports.DidChangeTextDocumentFeature = DidChangeTextDocumentFeature; class WillSaveFeature extends features_1.TextDocumentEventFeature { constructor(client) { super(client, vscode_1.workspace.onWillSaveTextDocument, vscode_languageserver_protocol_1.WillSaveTextDocumentNotification.type, () => client.middleware.willSave, (willSaveEvent) => client.code2ProtocolConverter.asWillSaveTextDocumentParams(willSaveEvent), (event) => event.document, (selectors, willSaveEvent) => features_1.TextDocumentEventFeature.textDocumentFilter(selectors, willSaveEvent.document)); } get registrationType() { return vscode_languageserver_protocol_1.WillSaveTextDocumentNotification.type; } fillClientCapabilities(capabilities) { const value = (0, features_1.ensure)((0, features_1.ensure)(capabilities, 'textDocument'), 'synchronization'); value.willSave = true; } initialize(capabilities, documentSelector) { const textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.willSave) { this.register({ id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } }); } } getTextDocument(data) { return data.document; } } exports.WillSaveFeature = WillSaveFeature; class WillSaveWaitUntilFeature extends features_1.DynamicDocumentFeature { _listener; _selectors; constructor(client) { super(client); this._selectors = new Map(); } getDocumentSelectors() { return this._selectors.values(); } get registrationType() { return vscode_languageserver_protocol_1.WillSaveTextDocumentWaitUntilRequest.type; } fillClientCapabilities(capabilities) { const value = (0, features_1.ensure)((0, features_1.ensure)(capabilities, 'textDocument'), 'synchronization'); value.willSaveWaitUntil = true; } initialize(capabilities, documentSelector) { const textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.willSaveWaitUntil) { this.register({ id: UUID.generateUuid(), registerOptions: { documentSelector: documentSelector } }); } } register(data) { if (!data.registerOptions.documentSelector) { return; } if (!this._listener) { this._listener = vscode_1.workspace.onWillSaveTextDocument(this.callback, this); } this._selectors.set(data.id, this._client.protocol2CodeConverter.asDocumentSelector(data.registerOptions.documentSelector)); } callback(event) { if (features_1.TextDocumentEventFeature.textDocumentFilter(this._selectors.values(), event.document) && !this._client.hasDedicatedTextSynchronizationFeature(event.document)) { const middleware = this._client.middleware; const willSaveWaitUntil = (event) => { return this._client.sendRequest(vscode_languageserver_protocol_1.WillSaveTextDocumentWaitUntilRequest.type, this._client.code2ProtocolConverter.asWillSaveTextDocumentParams(event)).then(async (edits) => { const vEdits = await this._client.protocol2CodeConverter.asTextEdits(edits); return vEdits === undefined ? [] : vEdits; }); }; event.waitUntil(middleware.willSaveWaitUntil ? middleware.willSaveWaitUntil(event, willSaveWaitUntil) : willSaveWaitUntil(event)); } } unregister(id) { this._selectors.delete(id); if (this._selectors.size === 0 && this._listener) { this._listener.dispose(); this._listener = undefined; } } clear() { this._selectors.clear(); if (this._listener) { this._listener.dispose(); this._listener = undefined; } } } exports.WillSaveWaitUntilFeature = WillSaveWaitUntilFeature; class DidSaveTextDocumentFeature extends features_1.TextDocumentEventFeature { _includeText; constructor(client) { super(client, vscode_1.workspace.onDidSaveTextDocument, vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type, () => client.middleware.didSave, (textDocument) => client.code2ProtocolConverter.asSaveTextDocumentParams(textDocument, this._includeText), (data) => data, features_1.TextDocumentEventFeature.textDocumentFilter); this._includeText = false; } get registrationType() { return vscode_languageserver_protocol_1.DidSaveTextDocumentNotification.type; } fillClientCapabilities(capabilities) { (0, features_1.ensure)((0, features_1.ensure)(capabilities, 'textDocument'), 'synchronization').didSave = true; } initialize(capabilities, documentSelector) { const textDocumentSyncOptions = capabilities.resolvedTextDocumentSync; if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.save) { const saveOptions = typeof textDocumentSyncOptions.save === 'boolean' ? { includeText: false } : { includeText: !!textDocumentSyncOptions.save.includeText }; this.register({ id: UUID.generateUuid(), registerOptions: Object.assign({}, { documentSelector: documentSelector }, saveOptions) }); } } register(data) { this._includeText = !!data.registerOptions.includeText; super.register(data); } getTextDocument(data) { return data; } } exports.DidSaveTextDocumentFeature = DidSaveTextDocumentFeature; // Copied from https://github.com/microsoft/vscode/src/vs/editor/common/core/wordHelper.ts const USUAL_WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\|;:\'",.<>/?'; /** * Create a word definition regular expression based on default word separators. * Optionally provide allowed separators that should be included in words. * * The default would look like this: * /(-?\d*\.\d\w*)|([^\`\~\!\@\#\$\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g */ function createWordRegExp(allowInWords = '') { let source = '(-?\\d*\\.\\d\\w*)|([^'; for (const sep of USUAL_WORD_SEPARATORS) { if (allowInWords.indexOf(sep) >= 0) { continue; } source += '\\' + sep; } source += '\\s]+)'; return new RegExp(source, 'g'); } // catches numbers (including floating numbers) in the first group, and alphanum in the second const DEFAULT_WORD_REGEXP = createWordRegExp(); class TextDocumentSnapshot { _extTextDocument; _capturedTextDocument; _content; _uri; _fileName; _languageId; _version; _eol; _isUntitled; _encoding; _isDirty; _isClosed; constructor(textDocument) { this._extTextDocument = textDocument; this._content = textDocument.getText(); this._uri = textDocument.uri; this._fileName = textDocument.fileName; this._languageId = textDocument.languageId; this._version = textDocument.version; this._eol = textDocument.eol; this._isUntitled = textDocument.isUntitled; this._encoding = textDocument.encoding; this._isDirty = textDocument.isDirty; this._isClosed = textDocument.isClosed; this._capturedTextDocument = vscode_languageserver_textdocument_1.TextDocument.create(this._uri.toString(), this._languageId, this._version, this._content); } get uri() { return this._uri; } get languageId() { return this._languageId; } get version() { return this._version; } get eol() { return this._eol; } get isUntitled() { return this._isUntitled; } get encoding() { return this._encoding; } get fileName() { return this._fileName; } get isDirty() { return this._isDirty; } get isClosed() { return this._isClosed; } save() { return this.version === this._extTextDocument.version ? this._extTextDocument.save() : Promise.resolve(false); } get lineCount() { return this._capturedTextDocument.lineCount; } offsetAt(position) { return this._capturedTextDocument.offsetAt(position); } positionAt(offset) { const position = this._capturedTextDocument.positionAt(offset); return new vscode_1.Position(position.line, position.character); } getText(range) { return this._capturedTextDocument.getText(range); } lineAt(lineOrPosition) { const line = typeof lineOrPosition === 'number' ? lineOrPosition : this.validatePosition(lineOrPosition).line; if (line < 0 || line >= this.lineCount) { throw new RangeError(`Illegal value for line: ${line}`); } const lineRange = this._capturedTextDocument.getLineRange(line); const text = this._capturedTextDocument.getText(lineRange); const firstNonWhitespaceCharacterIndex = text.search(/\S/); const range = new vscode_1.Range(lineRange.start.line, lineRange.start.character, lineRange.end.line, lineRange.end.character); const rangeIncludingLineBreak = line + 1 < this.lineCount ? new vscode_1.Range(range.start.line, range.start.character, line + 1, 0) : range; return { lineNumber: line, text, range, rangeIncludingLineBreak, firstNonWhitespaceCharacterIndex: firstNonWhitespaceCharacterIndex === -1 ? text.length : firstNonWhitespaceCharacterIndex, isEmptyOrWhitespace: firstNonWhitespaceCharacterIndex === -1 }; } getWordRangeAtPosition(position, regex) { const lineNumber = this.validatePosition(position).line; const lineText = this.lineAt(lineNumber).text; const wordRegex = TextDocumentSnapshot.getWordRegExp(regex); let match; wordRegex.lastIndex = 0; while ((match = wordRegex.exec(lineText)) !== null) { if (match.index <= position.character && wordRegex.lastIndex >= position.character) { return new vscode_1.Range(lineNumber, match.index, lineNumber, wordRegex.lastIndex); } } return undefined; } validateRange(range) { const start = this.validatePosition(range.start); const end = this.validatePosition(range.end); if (start === range.start && end === range.end) { return range; } return new vscode_1.Range(start.line, start.character, end.line, end.character); } validatePosition(position) { const line = Math.min(Math.max(position.line, 0), this.lineCount - 1); const lineRange = this._capturedTextDocument.getLineRange(line); const character = Math.min(Math.max(position.character, 0), lineRange.end.character); if (line === position.line && character === position.character) { return position; } return new vscode_1.Position(line, character); } static getWordRegExp(regex) { const result = regex ?? DEFAULT_WORD_REGEXP; if (result.flags.includes('g')) { return result; } const flags = `${result.flags}g`; return new RegExp(result.source, flags); } }