Files
infocom-systems-design/node_modules/langium/lib/lsp/normalized-text-documents.js
2025-10-03 22:27:28 +03:00

138 lines
6.2 KiB
JavaScript

/******************************************************************************
* Copyright 2024 TypeFox GmbH
* This program and the accompanying materials are made available under the
* terms of the MIT License, which is available in the project root.
******************************************************************************/
import { TextDocumentSyncKind, Disposable, Emitter } from 'vscode-languageserver';
import { UriUtils } from '../utils/uri-utils.js';
// Adapted from:
// https://github.com/microsoft/vscode-languageserver-node/blob/8f5fa710d3a9f60ff5e7583a9e61b19f86e39da3/server/src/common/textDocuments.ts
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
/**
* Normalizing text document manager. Normalizes all incoming URIs to the same format used by VS Code.
*/
export class NormalizedTextDocuments {
constructor(configuration) {
this._configuration = configuration;
this._syncedDocuments = new Map();
this._onDidChangeContent = new Emitter();
this._onDidOpen = new Emitter();
this._onDidClose = new Emitter();
this._onDidSave = new Emitter();
this._onWillSave = new Emitter();
}
get onDidOpen() {
return this._onDidOpen.event;
}
get onDidChangeContent() {
return this._onDidChangeContent.event;
}
get onWillSave() {
return this._onWillSave.event;
}
onWillSaveWaitUntil(handler) {
this._willSaveWaitUntil = handler;
}
get onDidSave() {
return this._onDidSave.event;
}
get onDidClose() {
return this._onDidClose.event;
}
get(uri) {
return this._syncedDocuments.get(UriUtils.normalize(uri));
}
set(document) {
const uri = UriUtils.normalize(document.uri);
let result = true;
if (this._syncedDocuments.has(uri)) {
result = false;
}
this._syncedDocuments.set(uri, document);
const toFire = Object.freeze({ document });
this._onDidOpen.fire(toFire);
this._onDidChangeContent.fire(toFire);
return result;
}
delete(uri) {
const uriString = UriUtils.normalize(typeof uri === 'object' && 'uri' in uri ? uri.uri : uri);
const syncedDocument = this._syncedDocuments.get(uriString);
if (syncedDocument !== undefined) {
this._syncedDocuments.delete(uriString);
this._onDidClose.fire(Object.freeze({ document: syncedDocument }));
}
}
all() {
return Array.from(this._syncedDocuments.values());
}
keys() {
return Array.from(this._syncedDocuments.keys());
}
listen(connection) {
// Required for interoperability with the the vscode-languageserver package
// eslint-disable-next-line @typescript-eslint/no-explicit-any
connection.__textDocumentSync = TextDocumentSyncKind.Incremental;
const disposables = [];
disposables.push(connection.onDidOpenTextDocument((event) => {
const td = event.textDocument;
const uri = UriUtils.normalize(td.uri);
const document = this._configuration.create(uri, td.languageId, td.version, td.text);
this._syncedDocuments.set(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`);
}
const uri = UriUtils.normalize(td.uri);
let syncedDocument = this._syncedDocuments.get(uri);
if (syncedDocument !== undefined) {
syncedDocument = this._configuration.update(syncedDocument, changes, version);
this._syncedDocuments.set(uri, syncedDocument);
this._onDidChangeContent.fire(Object.freeze({ document: syncedDocument }));
}
}));
disposables.push(connection.onDidCloseTextDocument((event) => {
const uri = UriUtils.normalize(event.textDocument.uri);
const syncedDocument = this._syncedDocuments.get(uri);
if (syncedDocument !== undefined) {
this._syncedDocuments.delete(uri);
this._onDidClose.fire(Object.freeze({ document: syncedDocument }));
}
}));
disposables.push(connection.onWillSaveTextDocument((event) => {
const syncedDocument = this._syncedDocuments.get(UriUtils.normalize(event.textDocument.uri));
if (syncedDocument !== undefined) {
this._onWillSave.fire(Object.freeze({ document: syncedDocument, reason: event.reason }));
}
}));
disposables.push(connection.onWillSaveTextDocumentWaitUntil((event, token) => {
const syncedDocument = this._syncedDocuments.get(UriUtils.normalize(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) => {
const syncedDocument = this._syncedDocuments.get(UriUtils.normalize(event.textDocument.uri));
if (syncedDocument !== undefined) {
this._onDidSave.fire(Object.freeze({ document: syncedDocument }));
}
}));
return Disposable.create(() => { disposables.forEach(disposable => disposable.dispose()); });
}
}
//# sourceMappingURL=normalized-text-documents.js.map