Skip to content

Commit 4e5da34

Browse files
Align Node server validation with Java server (async live validation) (#99)
Fixes eclipse-glsp/glsp#1408
1 parent a9ed9ad commit 4e5da34

File tree

3 files changed

+40
-3
lines changed

3 files changed

+40
-3
lines changed

packages/server/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,13 @@
6363
"@types/uuid": "8.3.1",
6464
"commander": "^8.3.0",
6565
"fast-json-patch": "^3.1.0",
66+
"lodash": "4.17.21",
6667
"vscode-jsonrpc": "8.2.0",
6768
"winston": "^3.3.3",
6869
"ws": "^8.12.1"
6970
},
7071
"devDependencies": {
72+
"@types/lodash": "4.14.191",
7173
"@types/ws": "^8.5.4"
7274
},
7375
"peerDependencies": {

packages/server/src/common/features/model/model-submission-handler.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ import {
2424
SetDirtyStateAction,
2525
SetMarkersAction,
2626
SetModelAction,
27+
StatusAction,
2728
UpdateModelAction
2829
} from '@eclipse-glsp/protocol';
30+
import { DebouncedFunc, debounce } from 'lodash';
2931

3032
import { inject, injectable, optional } from 'inversify';
33+
import { ActionDispatcher } from '../../actions/action-dispatcher';
3134
import { CommandStack } from '../../command/command-stack';
3235
import { DiagramConfiguration, ServerLayoutKind } from '../../diagram/diagram-configuration';
3336
import { LayoutEngine } from '../layout/layout-engine';
@@ -70,8 +73,14 @@ export class ModelSubmissionHandler {
7073
@optional()
7174
protected validator?: ModelValidator;
7275

76+
@inject(ActionDispatcher)
77+
protected actionDispatcher: ActionDispatcher;
78+
7379
protected requestModelAction?: RequestModelAction;
7480

81+
liveValidationDelay = 100;
82+
protected debouncedLiveValidation?: DebouncedFunc<(validator: ModelValidator) => void>;
83+
7584
/**
7685
* Returns a list of actions to submit the initial revision of the client-side model, based on the injected
7786
* {@link ModelState}. Typically this method is invoked by the {@link RequestModelActionHandler} when the diagram
@@ -149,12 +158,33 @@ export class ModelSubmissionHandler {
149158
result.push(SetDirtyStateAction.create(this.commandStack.isDirty, { reason }));
150159
}
151160
if (this.validator) {
152-
const markers = await this.validator.validate([this.modelState.root], MarkersReason.LIVE);
153-
result.push(SetMarkersAction.create(markers, { reason: MarkersReason.LIVE }));
161+
const validationActions = await this.validateModel(this.validator);
162+
result.push(...validationActions);
154163
}
155164
return result;
156165
}
157166

167+
protected validateModel(validator: ModelValidator): MaybePromise<Action[]> {
168+
this.scheduleLiveValidation(validator);
169+
// we are using async, debounced live validation so there are no actions to return for the model submission
170+
return [];
171+
}
172+
173+
protected scheduleLiveValidation(validator: ModelValidator): void {
174+
this.debouncedLiveValidation?.cancel();
175+
this.debouncedLiveValidation = debounce(validator => this.performLiveValidation(validator), this.liveValidationDelay);
176+
this.debouncedLiveValidation(validator);
177+
}
178+
179+
protected async performLiveValidation(validator: ModelValidator): Promise<void> {
180+
this.actionDispatcher.dispatch(StatusAction.create('Validate Model...'));
181+
const markers = await validator.validate([this.modelState.root], MarkersReason.LIVE);
182+
return this.actionDispatcher.dispatchAll(
183+
SetMarkersAction.create(markers, { reason: MarkersReason.LIVE }),
184+
StatusAction.create('', { severity: 'NONE' })
185+
);
186+
}
187+
158188
protected createSetModeAction(newRoot: GModelRootSchema): SetModelAction {
159189
const responseId = this.requestModelAction?.requestId ?? '';
160190
const response = SetModelAction.create(newRoot, { responseId });

yarn.lock

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,11 @@
10341034
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
10351035
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
10361036

1037+
1038+
version "4.14.191"
1039+
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.191.tgz#09511e7f7cba275acd8b419ddac8da9a6a79e2fa"
1040+
integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==
1041+
10371042
"@types/minimatch@^3.0.3":
10381043
version "3.0.5"
10391044
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
@@ -4739,7 +4744,7 @@ lodash.merge@^4.6.2:
47394744
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
47404745
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
47414746

4742-
lodash@^4.17.21:
4747+
lodash@4.17.21, lodash@^4.17.21:
47434748
version "4.17.21"
47444749
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
47454750
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

0 commit comments

Comments
 (0)