forked from eclipse-glsp/glsp-client
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GLSP-1116 Revise model loading (eclipse-glsp#287)
* GLSP-1116 Revise model loading - Refactor diagram loader - Remove dispatching of temporary empty set model action and instead call `actionDispatcher.initialize()` earlier which also dispatches an empty set model action under the hood - Add additional `postModelInitalization` hook for startup services that want execute logic after the model is fully initialized - Rework `ModelInitializationConstraint` - Provide `onInitialized` override that allows sync registration of listener callbacks - Refactor `setCompleted` method and remove the possiblity to set the initialized state to false. Model initialization is a one-time action. Once initialized there should be no way to "uninitialize" the constraint - Provide test cases - Add `dispatchOnceModelInitialized` utility function to action dispatcher - Ensure that type hints are requested after the model has been initialized Part-of: eclipse-glsp/glsp#1116 Part-of: eclipse-glsp/glsp#606 * GLSP-1117: Remove need for explicit definition of client actions -Extend `initializeClientSession` request to also specific the set of client action kinds. This way the server knows which actions should be sent to the client -Adapt `GLSPModelSource´ to retrieve the client actions before sending the `initializeClientSession` request - Add customized `GLSPActionHandlerRegistry` which provides a query method to retrieve all handled action kinds Part of eclipse-glsp/glsp/issues/1117 * GLSP-1071: Rename ServerStatus/ServerMessage action Part of eclipse-glsp/glsp#1071
- Loading branch information
1 parent
d96a09c
commit c0e6a7d
Showing
28 changed files
with
371 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2023 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 | ||
********************************************************************************/ | ||
|
||
import { injectable } from 'inversify'; | ||
import { ActionHandlerRegistry } from '~glsp-sprotty'; | ||
|
||
@injectable() | ||
export class GLSPActionHandlerRegistry extends ActionHandlerRegistry { | ||
/** | ||
* Retrieve a set of all action kinds for which (at least) one | ||
* handler is registered | ||
* @returns the set of handled action kinds | ||
*/ | ||
getHandledActionKinds(): string[] { | ||
return Array.from(this.elements.keys()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
packages/client/src/base/model/model-initialization-constraint.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2023 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 | ||
********************************************************************************/ | ||
import { expect } from 'chai'; | ||
import { Container } from 'inversify'; | ||
import 'reflect-metadata'; | ||
import * as sinon from 'sinon'; | ||
import { Deferred, EMPTY_ROOT, InitializeCanvasBoundsAction, SetModelAction, UpdateModelAction } from '~glsp-sprotty'; | ||
import { DefaultModelInitializationConstraint, ModelInitializationConstraint } from './model-initialization-constraint'; | ||
const sandbox = sinon.createSandbox(); | ||
const container = new Container(); | ||
let constraint: ModelInitializationConstraint; | ||
// eslint-disable-next-line @typescript-eslint/no-empty-function | ||
const listener = sandbox.spy((): void => {}); | ||
|
||
describe('DefaultModelInitializationConstraint', () => { | ||
beforeEach(() => { | ||
constraint = container.resolve(DefaultModelInitializationConstraint); | ||
sandbox.reset(); | ||
}); | ||
it('should complete after dispatching non empty SetModelAction and `InitializeCanvasBoundsAction`', () => { | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched(SetModelAction.create({ id: 'model', type: 'graph' })); | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND }); | ||
expect(constraint.isCompleted).to.be.true; | ||
}); | ||
it('should complete after dispatching non empty UpdateModelAction and `InitializeCanvasBoundsAction`', () => { | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched(UpdateModelAction.create({ id: 'model', type: 'graph' })); | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND }); | ||
expect(constraint.isCompleted).to.be.true; | ||
}); | ||
it('should note complete after dispatching empty SetModelAction and `InitializeCanvasBoundsAction` ', () => { | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched(SetModelAction.create(EMPTY_ROOT)); | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND }); | ||
expect(constraint.isCompleted).to.be.false; | ||
}); | ||
it('should note complete after dispatching empty UpdateModelAction and `InitializeCanvasBoundsAction ', () => { | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched(UpdateModelAction.create(EMPTY_ROOT)); | ||
expect(constraint.isCompleted).to.be.false; | ||
constraint.notifyDispatched({ kind: InitializeCanvasBoundsAction.KIND }); | ||
expect(constraint.isCompleted).to.be.false; | ||
}); | ||
describe('onInitialized', () => { | ||
it('returned promise should resolve once the constraint is initialized', async () => { | ||
const initializeDeferred = new Deferred<void>(); | ||
const initializePromise = constraint.onInitialized(); | ||
initializePromise.then(() => initializeDeferred.resolve()); | ||
expect(initializeDeferred.state).to.be.equal('unresolved'); | ||
// Directly trigger the completion method simplify test logic | ||
constraint['setCompleted'](); | ||
// Short delay of test execution to ensure that the deferred state is updated. | ||
await new Promise(resolve => setTimeout(resolve, 5)); | ||
expect(initializeDeferred.state).to.be.equal('resolved'); | ||
}); | ||
it('registered listener should be invoked once the constraint is initialized', () => { | ||
constraint.onInitialized(listener); | ||
expect(listener.called).to.be.false; | ||
// Directly trigger the completion method simplify test logic | ||
constraint['setCompleted'](); | ||
expect(listener.called).to.be.true; | ||
}); | ||
it('registered listener should be invoked directly on registration if the constraint is already initialized', () => { | ||
// Directly trigger the completion method simplify test logic | ||
constraint['setCompleted'](); | ||
constraint.onInitialized(listener); | ||
expect(listener.called).to.be.true; | ||
}); | ||
it('Disposed listener should not be invoked once the constraint is initialized', () => { | ||
const toDispose = constraint.onInitialized(listener); | ||
expect(listener.called).to.be.false; | ||
toDispose.dispose(); | ||
// Directly trigger the completion method simplify test logic | ||
constraint['setCompleted'](); | ||
expect(listener.called).to.be.false; | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.