172 lines
7 KiB
JavaScript
172 lines
7 KiB
JavaScript
"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;
|