"use strict"; /* -------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.TextDocuments = void 0; const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol"); /** * A manager for simple text documents. The manager requires at a minimum that * the server registered for the following text document sync events in the * initialize handler or via dynamic registration: * * - open and close events. * - change events. * * Registering for save and will save events is optional. */ class TextDocuments { /** * Create a new text document manager. */ constructor(configuration) { this._configuration = configuration; this._syncedDocuments = new Map(); this._onDidChangeContent = new vscode_languageserver_protocol_1.Emitter(); this._onDidOpen = new vscode_languageserver_protocol_1.Emitter(); this._onDidClose = new vscode_languageserver_protocol_1.Emitter(); this._onDidSave = new vscode_languageserver_protocol_1.Emitter(); this._onWillSave = new vscode_languageserver_protocol_1.Emitter(); } /** * An event that fires when a text document managed by this manager * has been opened. */ get onDidOpen() { return this._onDidOpen.event; } /** * An event that fires when a text document managed by this manager * has been opened or the content changes. */ get onDidChangeContent() { return this._onDidChangeContent.event; } /** * An event that fires when a text document managed by this manager * will be saved. */ get onWillSave() { return this._onWillSave.event; } /** * Sets a handler that will be called if a participant wants to provide * edits during a text document save. */ onWillSaveWaitUntil(handler) { this._willSaveWaitUntil = handler; } /** * An event that fires when a text document managed by this manager * has been saved. */ get onDidSave() { return this._onDidSave.event; } /** * An event that fires when a text document managed by this manager * has been closed. */ get onDidClose() { return this._onDidClose.event; } /** * Returns the document for the given URI. Returns undefined if * the document is not managed by this instance. * * @param uri The text document's URI to retrieve. * @return the text document or `undefined`. */ get(uri) { return this._syncedDocuments.get(uri); } /** * Returns all text documents managed by this instance. * * @return all text documents. */ all() { return Array.from(this._syncedDocuments.values()); } /** * Returns the URIs of all text documents managed by this instance. * * @return the URI's of all text documents. */ keys() { return Array.from(this._syncedDocuments.keys()); } /** * Listens for `low level` notification on the given connection to * update the text documents managed by this instance. * * Please note that the connection only provides handlers not an event model. Therefore * listening on a connection will overwrite the following handlers on a connection: * `onDidOpenTextDocument`, `onDidChangeTextDocument`, `onDidCloseTextDocument`, * `onWillSaveTextDocument`, `onWillSaveTextDocumentWaitUntil` and `onDidSaveTextDocument`. * * Use the corresponding events on the TextDocuments instance instead. * * @param connection The connection to listen on. */ listen(connection) { connection.__textDocumentSync = vscode_languageserver_protocol_1.TextDocumentSyncKind.Incremental; const disposables = []; disposables.push(connection.onDidOpenTextDocument((event) => { const td = event.textDocument; const document = this._configuration.create(td.uri, td.languageId, td.version, td.text); this._syncedDocuments.set(td.uri, document); const toFire = Object.freeze({ document }); this._onDidOpen.fire(toFire); this._onDidChangeContent.fire(toFire); })); disposables.push(connection.onDidChangeTextDocument((event) => { const td = event.textDocument; const changes = event.contentChanges; if (changes.length === 0) { return; } const { version } = td; if (version === null || version === undefined) { throw new Error(`Received document change event for ${td.uri} without valid version identifier`); } let syncedDocument = this._syncedDocuments.get(td.uri); if (syncedDocument !== undefined) { syncedDocument = this._configuration.update(syncedDocument, changes, version); this._syncedDocuments.set(td.uri, syncedDocument); this._onDidChangeContent.fire(Object.freeze({ document: syncedDocument })); } })); disposables.push(connection.onDidCloseTextDocument((event) => { let syncedDocument = this._syncedDocuments.get(event.textDocument.uri); if (syncedDocument !== undefined) { this._syncedDocuments.delete(event.textDocument.uri); this._onDidClose.fire(Object.freeze({ document: syncedDocument })); } })); disposables.push(connection.onWillSaveTextDocument((event) => { let syncedDocument = this._syncedDocuments.get(event.textDocument.uri); if (syncedDocument !== undefined) { this._onWillSave.fire(Object.freeze({ document: syncedDocument, reason: event.reason })); } })); disposables.push(connection.onWillSaveTextDocumentWaitUntil((event, token) => { let syncedDocument = this._syncedDocuments.get(event.textDocument.uri); if (syncedDocument !== undefined && this._willSaveWaitUntil) { return this._willSaveWaitUntil(Object.freeze({ document: syncedDocument, reason: event.reason }), token); } else { return []; } })); disposables.push(connection.onDidSaveTextDocument((event) => { let syncedDocument = this._syncedDocuments.get(event.textDocument.uri); if (syncedDocument !== undefined) { this._onDidSave.fire(Object.freeze({ document: syncedDocument })); } })); return vscode_languageserver_protocol_1.Disposable.create(() => { disposables.forEach(disposable => disposable.dispose()); }); } } exports.TextDocuments = TextDocuments;