UNPKG

@eclipse-glsp/client

Version:

A sprotty-based client for GLSP

186 lines 8.79 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GLSPActionDispatcher = void 0; /******************************************************************************** * Copyright (c) 2019-2024 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * This Source Code may also be made available under the following Secondary * Licenses when the conditions for such availability set forth in the Eclipse * Public License v. 2.0 are satisfied: GNU General Public License, version 2 * with the GNU Classpath Exception which is available at * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ const sprotty_1 = require("@eclipse-glsp/sprotty"); const inversify_1 = require("inversify"); const action_handler_registry_1 = require("./action-handler-registry"); const glsp_model_source_1 = require("./model/glsp-model-source"); const model_initialization_constraint_1 = require("./model/model-initialization-constraint"); let GLSPActionDispatcher = class GLSPActionDispatcher extends sprotty_1.ActionDispatcher { constructor() { super(...arguments); this.timeouts = new Map(); this.initializedConstraint = false; this.postUpdateQueue = []; this.initializeDeferred = new sprotty_1.Deferred(); } initialize() { if (!this.initialized) { this.initialized = this.initializeDeferred.promise; this.doInitialize(); } return this.initialized; } async doInitialize() { try { if (this.actionHandlerRegistry instanceof action_handler_registry_1.GLSPActionHandlerRegistry) { this.actionHandlerRegistry.initialize(); } this.handleAction(sprotty_1.SetModelAction.create(sprotty_1.EMPTY_ROOT)).catch(() => { /* Logged in handleAction method */ }); this.startModelInitialization(); this.initializeDeferred.resolve(); } catch (error) { this.initializeDeferred.reject(error); } } startModelInitialization() { if (!this.initializedConstraint) { this.logger.log(this, 'Starting model initialization mode'); this.initializationConstraint.onInitialized(() => this.logger.log(this, 'Model initialization completed')); this.initializedConstraint = true; } } onceModelInitialized() { return this.initializationConstraint.onInitialized(); } hasHandler(action) { return this.actionHandlerRegistry.get(action.kind).length > 0; } /** * Processes all given actions, by dispatching them to the corresponding handlers, after the model initialization is completed. * * @param actions The actions that should be dispatched after the model initialization */ dispatchOnceModelInitialized(...actions) { this.initializationConstraint.onInitialized(() => this.dispatchAll(actions)); } /** * Processes all given actions, by dispatching them to the corresponding handlers, after the next model update. * The given actions are queued until the next model update cycle has been completed i.e. * the `EditorContextService.onModelRootChanged` event is triggered. * * @param actions The actions that should be dispatched after the next model update */ dispatchAfterNextUpdate(...actions) { this.postUpdateQueue.push(...actions); } modelRootChanged(_root) { if (this.postUpdateQueue.length === 0) { return; } const toDispatch = [...this.postUpdateQueue]; this.postUpdateQueue = []; this.dispatchAll(toDispatch); } async dispatch(action) { const result = await super.dispatch(action); this.initializationConstraint.notifyDispatched(action); return result; } handleAction(action) { if (sprotty_1.ResponseAction.hasValidResponseId(action)) { // clear timeout const timeout = this.timeouts.get(action.responseId); if (timeout !== undefined) { clearTimeout(timeout); this.timeouts.delete(action.responseId); } // Check if we have a pending request for the response. // If not the we clear the responseId => action will be dispatched normally const deferred = this.requests.get(action.responseId); if (deferred === undefined) { action.responseId = ''; } } if (!this.hasHandler(action) && glsp_model_source_1.OptionalAction.is(action)) { return Promise.resolve(); } return super.handleAction(action); } request(action) { if (!action.requestId && action.requestId === '') { // No request id has been specified. So we use a generated one. action.requestId = sprotty_1.RequestAction.generateRequestId(); } return super.request(action); } /** * Dispatch a request and waits for a response until the timeout given in `timeoutMs` has * been reached. The returned promise is resolved when a response with matching identifier * is dispatched or when the timeout has been reached. That response is _not_ passed to the * registered action handlers. Instead, it is the responsibility of the caller of this method * to handle the response properly. For example, it can be sent to the registered handlers by * passing it again to the `dispatch` method. * If `rejectOnTimeout` is set to false (default) the returned promise will be resolved with * no value, otherwise it will be rejected. */ requestUntil(action, timeoutMs = 2000, rejectOnTimeout = false) { if (!action.requestId && action.requestId === '') { // No request id has been specified. So we use a generated one. action.requestId = sprotty_1.RequestAction.generateRequestId(); } const requestId = action.requestId; const timeout = setTimeout(() => { const deferred = this.requests.get(requestId); if (deferred !== undefined) { // cleanup clearTimeout(timeout); this.requests.delete(requestId); const notification = 'Request ' + requestId + ' (' + action + ') time out after ' + timeoutMs + 'ms.'; if (rejectOnTimeout) { deferred.reject(notification); } else { this.logger.info(this, notification); deferred.resolve(); } } }, timeoutMs); this.timeouts.set(requestId, timeout); return super.request(action); } }; exports.GLSPActionDispatcher = GLSPActionDispatcher; __decorate([ (0, inversify_1.inject)(model_initialization_constraint_1.ModelInitializationConstraint), __metadata("design:type", model_initialization_constraint_1.ModelInitializationConstraint) ], GLSPActionDispatcher.prototype, "initializationConstraint", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.ActionHandlerRegistry), __metadata("design:type", sprotty_1.ActionHandlerRegistry) ], GLSPActionDispatcher.prototype, "actionHandlerRegistry", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.ActionHandlerRegistryProvider), __metadata("design:type", Function) ], GLSPActionDispatcher.prototype, "actionHandlerRegistryProvider", void 0); exports.GLSPActionDispatcher = GLSPActionDispatcher = __decorate([ (0, inversify_1.injectable)() ], GLSPActionDispatcher); //# sourceMappingURL=action-dispatcher.js.map