@hydranium/glsp-server 1.0.0-next.317 → 1.0.0-next.319

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/lib/command/hydranium-glsp-command-stack.d.ts +13 -2
  2. package/lib/command/hydranium-glsp-command-stack.d.ts.map +1 -1
  3. package/lib/command/hydranium-glsp-command-stack.js +49 -2
  4. package/lib/command/hydranium-glsp-command-stack.js.map +1 -1
  5. package/lib/command/hydranium-glsp-operation-command.d.ts +21 -2
  6. package/lib/command/hydranium-glsp-operation-command.d.ts.map +1 -1
  7. package/lib/command/hydranium-glsp-operation-command.js +29 -3
  8. package/lib/command/hydranium-glsp-operation-command.js.map +1 -1
  9. package/lib/command/hydranium-glsp-recording-command.d.ts +7 -0
  10. package/lib/command/hydranium-glsp-recording-command.d.ts.map +1 -1
  11. package/lib/command/hydranium-glsp-recording-command.js +12 -1
  12. package/lib/command/hydranium-glsp-recording-command.js.map +1 -1
  13. package/lib/command/hydranium-glsp-undo-redo-action-handler.d.ts +58 -1
  14. package/lib/command/hydranium-glsp-undo-redo-action-handler.d.ts.map +1 -1
  15. package/lib/command/hydranium-glsp-undo-redo-action-handler.js +116 -1
  16. package/lib/command/hydranium-glsp-undo-redo-action-handler.js.map +1 -1
  17. package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.d.ts +11 -1
  18. package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.d.ts.map +1 -1
  19. package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.js +22 -3
  20. package/lib/computed-bounds/hydranium-glsp-computed-bounds-action-handler.js.map +1 -1
  21. package/lib/messages/index.d.ts +3 -0
  22. package/lib/messages/index.d.ts.map +1 -1
  23. package/lib/messages/index.js +3 -0
  24. package/lib/messages/index.js.map +1 -1
  25. package/lib/state/abstract-hydranium-glsp-state.d.ts +12 -1
  26. package/lib/state/abstract-hydranium-glsp-state.d.ts.map +1 -1
  27. package/lib/state/abstract-hydranium-glsp-state.js +17 -1
  28. package/lib/state/abstract-hydranium-glsp-state.js.map +1 -1
  29. package/lib/status/diagram-status-reporter.d.ts +23 -3
  30. package/lib/status/diagram-status-reporter.d.ts.map +1 -1
  31. package/lib/status/diagram-status-reporter.js +28 -2
  32. package/lib/status/diagram-status-reporter.js.map +1 -1
  33. package/lib/submission/hydranium-glsp-submission-handler.d.ts +12 -1
  34. package/lib/submission/hydranium-glsp-submission-handler.d.ts.map +1 -1
  35. package/lib/submission/hydranium-glsp-submission-handler.js +30 -4
  36. package/lib/submission/hydranium-glsp-submission-handler.js.map +1 -1
  37. package/package.json +7 -7
  38. package/src/command/hydranium-glsp-command-stack.ts +52 -2
  39. package/src/command/hydranium-glsp-operation-command.ts +42 -3
  40. package/src/command/hydranium-glsp-recording-command.ts +14 -1
  41. package/src/command/hydranium-glsp-undo-redo-action-handler.ts +146 -1
  42. package/src/computed-bounds/hydranium-glsp-computed-bounds-action-handler.ts +21 -3
  43. package/src/messages/index.ts +12 -0
  44. package/src/state/abstract-hydranium-glsp-state.ts +19 -1
  45. package/src/status/diagram-status-reporter.ts +37 -4
  46. package/src/submission/hydranium-glsp-submission-handler.ts +26 -5
@@ -1 +1 @@
1
- {"version":3,"file":"hydranium-glsp-submission-handler.js","sourceRoot":"","sources":["../../src/submission/hydranium-glsp-submission-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hydranium-glsp-submission-handler.js","sourceRoot":"","sources":["../../src/submission/hydranium-glsp-submission-handler.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydranium/glsp-server",
3
- "version": "1.0.0-next.317",
3
+ "version": "1.0.0-next.319",
4
4
  "description": "GLSP protocol head for the hydranium framework. Peer of @hydranium/core/lsp and @hydranium/data-server; built on @hydranium/core.",
5
5
  "keywords": [
6
6
  "diagram",
@@ -70,9 +70,9 @@
70
70
  },
71
71
  "devDependencies": {
72
72
  "@eclipse-glsp/server": "2.7.0",
73
- "@hydranium/core": "1.0.0-next.317",
74
- "@hydranium/langium": "1.0.0-next.317",
75
- "@hydranium/protocol": "1.0.0-next.317",
73
+ "@hydranium/core": "1.0.0-next.319",
74
+ "@hydranium/langium": "1.0.0-next.319",
75
+ "@hydranium/protocol": "1.0.0-next.319",
76
76
  "inversify": "6.2.2",
77
77
  "reflect-metadata": "0.2.2",
78
78
  "rimraf": "^5.0.0",
@@ -82,9 +82,9 @@
82
82
  },
83
83
  "peerDependencies": {
84
84
  "@eclipse-glsp/server": "^2.6.0",
85
- "@hydranium/core": "1.0.0-next.317",
86
- "@hydranium/langium": "1.0.0-next.317",
87
- "@hydranium/protocol": "1.0.0-next.317",
85
+ "@hydranium/core": "1.0.0-next.319",
86
+ "@hydranium/langium": "1.0.0-next.319",
87
+ "@hydranium/protocol": "1.0.0-next.319",
88
88
  "inversify": "^6.0.0",
89
89
  "reflect-metadata": "^0.2.2",
90
90
  "vscode-jsonrpc": "^9.0.0",
@@ -7,15 +7,18 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
 
10
- import { DefaultCommandStack, ModelState } from '@eclipse-glsp/server';
10
+ import { type Command, CompoundCommand, DefaultCommandStack, ModelState } from '@eclipse-glsp/server';
11
11
  import { type ServerSharedServices } from '@hydranium/core';
12
12
  import { inject, injectable } from 'inversify';
13
13
  import { HydraniumTypes } from '../state/hydranium-shared-core-services.js';
14
+ import { isCommandArray } from './hydranium-glsp-operation-command.js';
15
+ import { HydraniumGlspRecordingCommand } from './hydranium-glsp-recording-command.js';
14
16
 
15
17
  /**
16
18
  * GLSP's command stack with the diagram's dirty state read from the text store:
17
19
  * dirty while any document the diagram's client session has open differs from
18
- * its file, as the store last knew the file. Undo and redo are GLSP's.
20
+ * its file, as the store last knew the file. Undo and redo are GLSP's; a
21
+ * command whose every write was dropped is not pushed.
19
22
  *
20
23
  * GLSP's own answer counts the diagram's commands since its last save, so it
21
24
  * misses every change the diagram did not make: another client's unsaved edit
@@ -34,6 +37,43 @@ export class HydraniumGlspCommandStack extends DefaultCommandStack {
34
37
  return textDocuments.openDocuments().some(open => open.clients.includes(clientId) && textDocuments.isDirty(open.uri));
35
38
  }
36
39
 
40
+ /**
41
+ * Lifted from `@eclipse-glsp/server` 2.7.0's `DefaultCommandStack.execute`,
42
+ * pushing no entry for a recording command executed outside an operation
43
+ * whose write was dropped, or a `CompoundCommand` of only such commands at
44
+ * any depth: its undo would do nothing, and the user's next undo would be
45
+ * spent on it. A compound that also changed something is pushed, warning
46
+ * that its undo step leaves out what was dropped. The accompanying test
47
+ * pins upstream's source.
48
+ */
49
+ override async execute(command: Command): Promise<void> {
50
+ try {
51
+ await command.execute();
52
+ } catch (error: unknown) {
53
+ this.handleError(error);
54
+ }
55
+ const leaves = leavesOf(command);
56
+ const dropped = leaves.filter(leaf => leaf instanceof HydraniumGlspRecordingCommand && leaf.dropped).length;
57
+ if (dropped > 0 && dropped === leaves.length) {
58
+ return;
59
+ }
60
+ if (dropped > 0) {
61
+ this.logger.warn(
62
+ `${dropped} of ${leaves.length} commands of a compound executed outside an operation had their write dropped, ` +
63
+ 'so its undo step leaves them out; execute them in one operation to write and undo them as one'
64
+ );
65
+ }
66
+ // Clear the command list past the top (i.e. the old redo list)
67
+ this.commands = this.commands.slice(0, this.top + 1);
68
+ this.commands.push(command);
69
+ ++this.top;
70
+ // if the saveIndex points to the old redo list we can never reach a state again
71
+ // where save is not necessary. => ensure that `isDirty` always returns true
72
+ if (this.saveIndex >= this.top) {
73
+ this.saveIndex = -2;
74
+ }
75
+ }
76
+
37
77
  /**
38
78
  * Lifted from `@eclipse-glsp/server` 2.7.0's `DefaultCommandStack.handleError`
39
79
  * without its `error` line: the failure is rethrown, and whoever ends it
@@ -45,3 +85,13 @@ export class HydraniumGlspCommandStack extends DefaultCommandStack {
45
85
  throw error;
46
86
  }
47
87
  }
88
+
89
+ /**
90
+ * The commands `command` executes: itself, or a `CompoundCommand`'s children
91
+ * at any depth, read from GLSP's protected `CompoundCommand.commands`, as the
92
+ * operation reads them.
93
+ */
94
+ function leavesOf(command: Command): Command[] {
95
+ const children: unknown = command instanceof CompoundCommand ? Reflect.get(command, 'commands') : undefined;
96
+ return isCommandArray(children) ? children.flatMap(leavesOf) : [command];
97
+ }
@@ -61,6 +61,7 @@ export interface OperationInternals {
61
61
  recordWrittenRoot(root: AstNode): void;
62
62
  recordDropped(current: AstNode | undefined): void;
63
63
  recordExecuted(step: OperationSideEffect): void;
64
+ isUndoingOrRedoing(): boolean;
64
65
  assertNotDuringUndoRedo(label: string): void;
65
66
  amendBefore(update: (before: AnyObject) => AnyObject): void;
66
67
  }
@@ -84,6 +85,39 @@ export function openOperationOf(state: object): OperationInternals | undefined {
84
85
  return openOperations.get(state);
85
86
  }
86
87
 
88
+ /**
89
+ * How many operations an undo or redo skipped and applied, as one command-stack
90
+ * entry, a compound executed outside an operation, can undo several.
91
+ */
92
+ export interface UndoRedoTally {
93
+ skipped: number;
94
+ applied: number;
95
+ }
96
+
97
+ /** The tally of each state's undo or redo, until {@link takeUndoRedoTally} reads it. */
98
+ const undoRedoTallies = new WeakMap<object, UndoRedoTally>();
99
+
100
+ function tallyOf(state: object): UndoRedoTally {
101
+ let tally = undoRedoTallies.get(state);
102
+ if (!tally) {
103
+ tally = { skipped: 0, applied: 0 };
104
+ undoRedoTallies.set(state, tally);
105
+ }
106
+ return tally;
107
+ }
108
+
109
+ /**
110
+ * The operations undone or redone on `state` since the last call, skipped and
111
+ * applied, for the handler that ran the undo or redo to tell the client: GLSP's
112
+ * command stack takes no answer from an undo, and moves past a skipped one as
113
+ * past any other.
114
+ */
115
+ export function takeUndoRedoTally(state: object): UndoRedoTally {
116
+ const tally = undoRedoTallies.get(state) ?? { skipped: 0, applied: 0 };
117
+ undoRedoTallies.delete(state);
118
+ return tally;
119
+ }
120
+
87
121
  /** Run `operation` as {@link HydraniumGlspOperationCommand} describes. */
88
122
  export function runOperation<TSourceModel extends AnyObject>(
89
123
  operation: HydraniumGlspOperationCommand<TSourceModel>,
@@ -172,6 +206,7 @@ export class HydraniumGlspOperationCommand<TSourceModel extends AnyObject = AnyO
172
206
  this.before = update(this.before) as TSourceModel;
173
207
  }
174
208
  },
209
+ isUndoingOrRedoing: () => this.undoingOrRedoing,
175
210
  assertNotDuringUndoRedo: label => {
176
211
  if (this.undoingOrRedoing) {
177
212
  throw new Error(
@@ -411,8 +446,9 @@ export class HydraniumGlspOperationCommand<TSourceModel extends AnyObject = AnyO
411
446
  /**
412
447
  * Resolve the transition onto the current model, run the commands' side
413
448
  * effects, then write once, gated on the versions the model was read at. A
414
- * collision does nothing but warn; a transition with nothing left to apply,
415
- * or one the model already holds, still runs the side effects.
449
+ * collision does nothing but warn; a transition with nothing left to
450
+ * apply, or one the model already holds, still runs the side effects. Either
451
+ * way the outcome is counted for {@link takeUndoRedoTally}.
416
452
  *
417
453
  * The caller holds `runExclusive`, which nothing here takes again.
418
454
  */
@@ -438,10 +474,12 @@ export class HydraniumGlspOperationCommand<TSourceModel extends AnyObject = AnyO
438
474
  this.modelState.logger.warn(
439
475
  `${direction === 'undo' ? 'Undo' : 'Redo'} of an operation skipped (${outcome.status}); a foreign edit changed a shared field`
440
476
  );
477
+ tallyOf(this.modelState).skipped++;
441
478
  return;
442
479
  }
443
480
  }
444
481
  await this.undoOrRedoSideEffects(direction, merged);
482
+ tallyOf(this.modelState).applied++;
445
483
  }
446
484
 
447
485
  /**
@@ -597,6 +635,7 @@ export class HydraniumGlspOperationCommand<TSourceModel extends AnyObject = AnyO
597
635
  }
598
636
  }
599
637
 
600
- function isCommandArray(value: unknown): value is Command[] {
638
+ /** Whether `value` is a list of commands, as a `CompoundCommand` holds its children. */
639
+ export function isCommandArray(value: unknown): value is Command[] {
601
640
  return Array.isArray(value) && value.every(element => typeof element === 'object' && element !== null && 'execute' in element);
602
641
  }
@@ -48,6 +48,17 @@ export class HydraniumGlspRecordingCommand<TSourceModel extends AnyObject> exten
48
48
  /** The operation this command opened, when it executed outside one. */
49
49
  protected ownOperation?: HydraniumGlspOperationCommand<TSourceModel>;
50
50
 
51
+ /** Backing field for {@link dropped}. */
52
+ protected _dropped = false;
53
+
54
+ /**
55
+ * Whether the operation this command opened, executing outside one, had its
56
+ * write dropped: the command changed nothing, and its undo does nothing.
57
+ */
58
+ get dropped(): boolean {
59
+ return this._dropped;
60
+ }
61
+
51
62
  constructor(
52
63
  modelState: HydraniumGlspRecordingState<TSourceModel>,
53
64
  /** Human-readable label for the operation; appears in the timing-pair log line. */
@@ -66,7 +77,9 @@ export class HydraniumGlspRecordingCommand<TSourceModel extends AnyObject> exten
66
77
  const open = openOperationOf(this.modelState);
67
78
  if (!open) {
68
79
  const operation = new HydraniumGlspOperationCommand<TSourceModel>(this.modelState);
69
- if ((await this.modelState.runExclusive(() => runOperation(operation, () => this))) === 'executed') {
80
+ const outcome = await this.modelState.runExclusive(() => runOperation(operation, () => this));
81
+ this._dropped = outcome === 'dropped';
82
+ if (outcome === 'executed') {
70
83
  this.ownOperation = operation;
71
84
  }
72
85
  return;
@@ -7,10 +7,75 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
 
10
- import { type Action, ModelState, UndoRedoActionHandler } from '@eclipse-glsp/server';
10
+ import { type Action, Logger, MessageAction, ModelState, RedoAction, UndoAction, UndoRedoActionHandler } from '@eclipse-glsp/server';
11
+ import { type ServerSharedServices } from '@hydranium/core';
11
12
  import { type AstNode } from '@hydranium/langium';
13
+ import { type MessageDefinition, defineMessage, describeError, isConflictError } from '@hydranium/protocol';
12
14
  import { inject, injectable } from 'inversify';
13
15
  import { type AbstractHydraniumGlspState } from '../state/abstract-hydranium-glsp-state.js';
16
+ import { HydraniumTypes } from '../state/hydranium-shared-core-services.js';
17
+ import { isDiagramEditDroppedError, logActionFailure } from './diagram-edit-dropped-error.js';
18
+ import { type UndoRedoDirection, takeUndoRedoTally } from './hydranium-glsp-operation-command.js';
19
+
20
+ /** An undo did nothing: another editor has since changed a field it would restore. */
21
+ export const DIAGRAM_UNDO_SKIPPED = defineMessage(
22
+ 'hydranium/glsp-server/diagram-undo-skipped',
23
+ 'Nothing was undone: another editor has since changed what this undo would restore.'
24
+ );
25
+
26
+ /** A redo did nothing: another editor has since changed a field it would reapply. */
27
+ export const DIAGRAM_REDO_SKIPPED = defineMessage(
28
+ 'hydranium/glsp-server/diagram-redo-skipped',
29
+ 'Nothing was redone: another editor has since changed what this redo would reapply.'
30
+ );
31
+
32
+ /**
33
+ * Part of an undo did nothing: of the operations one undo step undoes, as a
34
+ * compound executed outside an operation does, another editor has since
35
+ * changed a field some would restore, and the rest were undone.
36
+ */
37
+ export const DIAGRAM_UNDO_PARTLY_SKIPPED = defineMessage(
38
+ 'hydranium/glsp-server/diagram-undo-partly-skipped',
39
+ 'Part of this undo was not applied: another editor has since changed some of what it would restore.'
40
+ );
41
+
42
+ /** Part of a redo did nothing, as {@link DIAGRAM_UNDO_PARTLY_SKIPPED} describes for an undo. */
43
+ export const DIAGRAM_REDO_PARTLY_SKIPPED = defineMessage(
44
+ 'hydranium/glsp-server/diagram-redo-partly-skipped',
45
+ 'Part of this redo was not applied: another editor has since changed some of what it would reapply.'
46
+ );
47
+
48
+ /**
49
+ * An undo failed because another editor changed a field it writes while it
50
+ * ran. GLSP clears the undo history on every failed undo or redo, so the
51
+ * message says so: the next undo otherwise does nothing, unexplained.
52
+ */
53
+ export const DIAGRAM_UNDO_FAILED = defineMessage(
54
+ 'hydranium/glsp-server/diagram-undo-failed',
55
+ 'Could not undo: another editor changed the same element meanwhile. The undo and redo history of this diagram was cleared.'
56
+ );
57
+
58
+ /** A redo failed as {@link DIAGRAM_UNDO_FAILED} describes for an undo. */
59
+ export const DIAGRAM_REDO_FAILED = defineMessage(
60
+ 'hydranium/glsp-server/diagram-redo-failed',
61
+ 'Could not redo: another editor changed the same element meanwhile. The undo and redo history of this diagram was cleared.'
62
+ );
63
+
64
+ /**
65
+ * An undo failed for a reason of its own, a side effect that threw, say, and
66
+ * GLSP cleared the history as it does on every failed undo or redo. The
67
+ * reason goes in the message's details; the log has it in full.
68
+ */
69
+ export const DIAGRAM_UNDO_ERROR = defineMessage(
70
+ 'hydranium/glsp-server/diagram-undo-error',
71
+ 'Could not undo: an error occurred. The undo and redo history of this diagram was cleared.'
72
+ );
73
+
74
+ /** A redo failed as {@link DIAGRAM_UNDO_ERROR} describes for an undo. */
75
+ export const DIAGRAM_REDO_ERROR = defineMessage(
76
+ 'hydranium/glsp-server/diagram-redo-error',
77
+ 'Could not redo: an error occurred. The undo and redo history of this diagram was cleared.'
78
+ );
14
79
 
15
80
  /**
16
81
  * GLSP's undo and redo handler inside the state's `runExclusive`. GLSP's
@@ -18,12 +83,92 @@ import { type AbstractHydraniumGlspState } from '../state/abstract-hydranium-gls
18
83
  * the boundary covers the whole action: taken around the undo or redo alone,
19
84
  * an undo arriving while an operation runs would move the position past an
20
85
  * entry it then cannot undo.
86
+ *
87
+ * An undo or redo a foreign edit skipped, whole or in part, tells the client,
88
+ * which otherwise sees nothing happen. One that fails ends here, as a message saying the
89
+ * history was cleared in place of GLSP's generic notice for a failed action:
90
+ * a dropped or conflicting one says another editor changed the element, and
91
+ * any but a dropped one, which its reconcile has logged, is logged here.
21
92
  */
22
93
  @injectable()
23
94
  export class HydraniumGlspUndoRedoActionHandler extends UndoRedoActionHandler {
24
95
  @inject(ModelState) protected readonly modelState!: AbstractHydraniumGlspState<AstNode, unknown>;
96
+ @inject(HydraniumTypes.SharedCoreServices) protected readonly sharedServices!: ServerSharedServices;
97
+ @inject(Logger) protected readonly logger!: Logger;
25
98
 
26
99
  override execute(action: Action): Promise<Action[]> {
27
100
  return this.modelState.runExclusive(() => super.execute(action));
28
101
  }
102
+
103
+ protected override undo(): Promise<Action[]> {
104
+ return this.undoOrRedo('undo');
105
+ }
106
+
107
+ protected override redo(): Promise<Action[]> {
108
+ return this.undoOrRedo('redo');
109
+ }
110
+
111
+ /**
112
+ * Lifted from `@eclipse-glsp/server` 2.7.0's `UndoRedoActionHandler.undo`
113
+ * and `redo`, telling the client of a skip and ending a failure of the
114
+ * command stack's undo or redo, which flushes the history on any failure.
115
+ * A failed submit after it leaves the history whole and fails as upstream.
116
+ * The accompanying test pins upstream's source.
117
+ */
118
+ protected async undoOrRedo(direction: UndoRedoDirection): Promise<Action[]> {
119
+ const undo = direction === 'undo';
120
+ if (!(undo ? this.commandStack.canUndo() : this.commandStack.canRedo())) {
121
+ return [];
122
+ }
123
+ // A tally no handler read, as of an undo whose submit failed or that ran outside this handler, is not this one's.
124
+ takeUndoRedoTally(this.modelState);
125
+ try {
126
+ await (undo ? this.commandStack.undo() : this.commandStack.redo());
127
+ } catch (error: unknown) {
128
+ return [this.failure(direction, error)];
129
+ }
130
+ const actions = await this.modelSubmissionHandler.submitModel(direction);
131
+ const { skipped, applied } = takeUndoRedoTally(this.modelState);
132
+ if (skipped === 0) {
133
+ return actions;
134
+ }
135
+ const message =
136
+ applied === 0
137
+ ? undo
138
+ ? DIAGRAM_UNDO_SKIPPED
139
+ : DIAGRAM_REDO_SKIPPED
140
+ : undo
141
+ ? DIAGRAM_UNDO_PARTLY_SKIPPED
142
+ : DIAGRAM_REDO_PARTLY_SKIPPED;
143
+ return [MessageAction.create(this.render(message), { severity: 'WARNING' }), ...actions];
144
+ }
145
+
146
+ /**
147
+ * The message for an undo or redo that failed, logging a failure its
148
+ * reconcile has not. A conflict thrown rather than dropped, by a state that
149
+ * does not reconcile or a reconcile that could not read the text, is the
150
+ * same foreign edit as a dropped write and is told as one.
151
+ */
152
+ protected failure(direction: UndoRedoDirection, error: unknown): MessageAction {
153
+ const undo = direction === 'undo';
154
+ if (isDiagramEditDroppedError(error)) {
155
+ return MessageAction.create(this.render(undo ? DIAGRAM_UNDO_FAILED : DIAGRAM_REDO_FAILED), { severity: 'ERROR' });
156
+ }
157
+ logActionFailure(this.logger, undo ? UndoAction.create() : RedoAction.create(), error);
158
+ if (isConflictError(error)) {
159
+ // The conflict's own message names the document, which the details carry.
160
+ return MessageAction.create(this.render(undo ? DIAGRAM_UNDO_FAILED : DIAGRAM_REDO_FAILED), {
161
+ severity: 'ERROR',
162
+ details: describeError(error)
163
+ });
164
+ }
165
+ return MessageAction.create(this.render(undo ? DIAGRAM_UNDO_ERROR : DIAGRAM_REDO_ERROR), {
166
+ severity: 'ERROR',
167
+ details: describeError(error)
168
+ });
169
+ }
170
+
171
+ protected render(message: MessageDefinition<string>): string {
172
+ return this.sharedServices.MessageRenderer.renderMessage(message);
173
+ }
29
174
  }
@@ -12,13 +12,28 @@ import {
12
12
  type ComputedBoundsAction,
13
13
  ComputedBoundsActionHandler,
14
14
  type GModelRoot,
15
- type MaybePromise
15
+ type MaybePromise,
16
+ MessageAction
16
17
  } from '@eclipse-glsp/server';
17
18
  import { type AstNode } from '@hydranium/langium';
18
- import { injectable } from 'inversify';
19
+ import { type ServerSharedServices } from '@hydranium/core';
20
+ import { defineMessage } from '@hydranium/protocol';
21
+ import { inject, injectable } from 'inversify';
19
22
  import { type AbstractHydraniumGlspState } from '../state/abstract-hydranium-glsp-state.js';
23
+ import { HydraniumTypes } from '../state/hydranium-shared-core-services.js';
20
24
  import { type HydraniumGlspSubmissionHandler } from '../submission/hydranium-glsp-submission-handler.js';
21
25
 
26
+ /**
27
+ * The first layout of a diagram arrived for a model the server has since
28
+ * replaced, so the diagram stays empty. Rendered at the raise site, since
29
+ * GLSP's message action has no slot for its identity. It names the recovery:
30
+ * a reopened diagram requests its model again.
31
+ */
32
+ export const DIAGRAM_LAYOUT_STALE = defineMessage(
33
+ 'hydranium/glsp-server/diagram-layout-stale',
34
+ 'Could not show this diagram: the document changed while it was opening. Close the diagram and open it again.'
35
+ );
36
+
22
37
  /**
23
38
  * GLSP {@link ComputedBoundsActionHandler} base shared by all hydranium
24
39
  * adopters. Adds handshake-aware revision-mismatch logging on top of the
@@ -32,7 +47,8 @@ import { type HydraniumGlspSubmissionHandler } from '../submission/hydranium-gls
32
47
  * very first `computedBounds` arrives with a revision the server has already
33
48
  * bumped, the subsequent `SetModelAction` response never fires and the diagram
34
49
  * stays stuck at "model loading…". Adopters need this initial-handshake case
35
- * logged as an error: the diagram stays empty, so the requested load failed.
50
+ * logged as an error, and the client told with {@link DIAGRAM_LAYOUT_STALE}:
51
+ * the diagram stays empty, so the requested load failed.
36
52
  *
37
53
  * **Handshake detection** uses
38
54
  * {@link HydraniumGlspSubmissionHandler.hasPendingInitialRequest} — true
@@ -49,6 +65,7 @@ import { type HydraniumGlspSubmissionHandler } from '../submission/hydranium-gls
49
65
  export class HydraniumGlspComputedBoundsActionHandler extends ComputedBoundsActionHandler {
50
66
  declare protected readonly modelState: AbstractHydraniumGlspState<AstNode, unknown>;
51
67
  declare protected readonly submissionHandler: HydraniumGlspSubmissionHandler<AstNode, unknown>;
68
+ @inject(HydraniumTypes.SharedCoreServices) protected readonly sharedServices!: ServerSharedServices;
52
69
 
53
70
  override execute(action: ComputedBoundsAction): MaybePromise<Action[]> {
54
71
  this.modelState.logger.debug(`ComputedBoundsActionHandler.execute entered: action.revision=${action.revision}`);
@@ -59,6 +76,7 @@ export class HydraniumGlspComputedBoundsActionHandler extends ComputedBoundsActi
59
76
  `ComputedBounds rejected (initial handshake): action.revision=${action.revision} model.revision=${model.revision} — ` +
60
77
  'initial SetModelAction will not fire (empty diagram)'
61
78
  );
79
+ return [MessageAction.create(this.sharedServices.MessageRenderer.renderMessage(DIAGRAM_LAYOUT_STALE), { severity: 'ERROR' })];
62
80
  } else {
63
81
  this.modelState.logger.debug(
64
82
  `ComputedBounds dropped (stale): action.revision=${action.revision} model.revision=${model.revision} — ` +
@@ -22,6 +22,18 @@
22
22
  * discovers the codes exist.
23
23
  */
24
24
 
25
+ export {
26
+ DIAGRAM_REDO_ERROR,
27
+ DIAGRAM_REDO_FAILED,
28
+ DIAGRAM_REDO_PARTLY_SKIPPED,
29
+ DIAGRAM_REDO_SKIPPED,
30
+ DIAGRAM_UNDO_ERROR,
31
+ DIAGRAM_UNDO_FAILED,
32
+ DIAGRAM_UNDO_PARTLY_SKIPPED,
33
+ DIAGRAM_UNDO_SKIPPED
34
+ } from '../command/hydranium-glsp-undo-redo-action-handler.js';
35
+ export { DIAGRAM_LAYOUT_STALE } from '../computed-bounds/hydranium-glsp-computed-bounds-action-handler.js';
36
+ export { DIAGRAM_EDIT_DROPPED } from '../status/diagram-status-reporter.js';
25
37
  export {
26
38
  DIAGRAM_READONLY_PARSE_ERROR,
27
39
  DIAGRAM_SESSION_REFUSED,
@@ -409,7 +409,9 @@ export abstract class AbstractHydraniumGlspState<TRoot extends AstNode, TSourceM
409
409
  /**
410
410
  * Resync after a write whose reconcile dropped the edit: during an
411
411
  * operation the operation undoes its side effects, pushes nothing, and
412
- * captures the document's current root when it ends.
412
+ * captures the document's current root when it ends. Announced on
413
+ * {@link onEditDropped}, except during an undo or redo, which fails and
414
+ * reports that itself.
413
415
  */
414
416
  protected writeDropped(): void {
415
417
  const operation = openOperationOf(this);
@@ -418,6 +420,22 @@ export abstract class AbstractHydraniumGlspState<TRoot extends AstNode, TSourceM
418
420
  } else {
419
421
  this.refreshSourceRoot();
420
422
  }
423
+ if (!operation?.isUndoingOrRedoing()) {
424
+ this.editDroppedEmitter.fire();
425
+ }
426
+ }
427
+
428
+ /** Backing emitter for {@link onEditDropped}. */
429
+ protected readonly editDroppedEmitter = new Emitter<void>();
430
+
431
+ /**
432
+ * Fires when a write's reconcile dropped a diagram edit, whether an
433
+ * operation or code outside one wrote it, so that one listener tells the
434
+ * client: the diagram returning to the document's state otherwise reads as
435
+ * the edit never having been made.
436
+ */
437
+ get onEditDropped(): Event<void> {
438
+ return this.editDroppedEmitter.event;
421
439
  }
422
440
 
423
441
  /**
@@ -15,23 +15,41 @@ import {
15
15
  type ClientSessionListener,
16
16
  ClientSessionManager,
17
17
  EditMode,
18
+ MessageAction,
18
19
  ModelState,
19
20
  SetEditModeAction,
20
21
  StatusAction
21
22
  } from '@eclipse-glsp/server';
23
+ import { type ServerSharedServices } from '@hydranium/core';
22
24
  import { type AstNode } from '@hydranium/langium';
23
- import { DisposableCollection, describeErrorWithStack } from '@hydranium/protocol';
25
+ import { DisposableCollection, defineMessage, describeErrorWithStack } from '@hydranium/protocol';
24
26
  import { inject, injectable } from 'inversify';
25
27
  import { type AbstractHydraniumGlspState } from '../state/abstract-hydranium-glsp-state.js';
26
28
  import { type DiagramStatusEntry } from '../state/diagram-status.js';
29
+ import { HydraniumTypes } from '../state/hydranium-shared-core-services.js';
30
+
31
+ /**
32
+ * A diagram edit was dropped because another editor changed the same field
33
+ * first. The diagram returns to the document's state, which without this reads
34
+ * as the edit never having been made. It names the recovery: the edit made
35
+ * again applies to the other editor's change.
36
+ */
37
+ export const DIAGRAM_EDIT_DROPPED = defineMessage(
38
+ 'hydranium/glsp-server/diagram-edit-dropped',
39
+ 'Your diagram change was not applied: another editor changed the same element first. Make the change again if you still want it.'
40
+ );
27
41
 
28
42
  /**
29
43
  * Sends the client what {@link AbstractHydraniumGlspState.onStatusChanged}
30
- * announces: the current status for its status overlay and the edit mode.
44
+ * announces: the current status for its status overlay and the edit mode; and
45
+ * a warning for each edit {@link AbstractHydraniumGlspState.onEditDropped}
46
+ * announces.
31
47
  *
32
- * The only sender of either action. A status or edit mode dispatched from
48
+ * The only sender of the status and the edit mode. Either dispatched from
33
49
  * anywhere else is overwritten by the next change, and the state's account of
34
- * why the diagram is read-only no longer matches the client's.
50
+ * why the diagram is read-only no longer matches the client's. An
51
+ * implementation bound in place of {@link DefaultDiagramStatusReporter} takes
52
+ * over the dropped-edit warning too, or the client no longer hears of one.
35
53
  */
36
54
  export interface DiagramStatusReporter extends ClientSessionInitializer {
37
55
  /**
@@ -47,6 +65,7 @@ export class DefaultDiagramStatusReporter implements DiagramStatusReporter, Clie
47
65
  @inject(ModelState) protected readonly state!: AbstractHydraniumGlspState<AstNode, unknown>;
48
66
  @inject(ActionDispatcher) protected readonly actionDispatcher!: ActionDispatcher;
49
67
  @inject(ClientSessionManager) protected readonly sessionManager!: ClientSessionManager;
68
+ @inject(HydraniumTypes.SharedCoreServices) protected readonly sharedServices!: ServerSharedServices;
50
69
 
51
70
  protected readonly toDispose = new DisposableCollection();
52
71
  /** What the client shows; it starts editable with an empty overlay. */
@@ -56,6 +75,7 @@ export class DefaultDiagramStatusReporter implements DiagramStatusReporter, Clie
56
75
  initialize(): void {
57
76
  this.sessionManager.addListener(this, this.state.clientId);
58
77
  this.toDispose.push(this.state.onStatusChanged(() => this.send()));
78
+ this.toDispose.push(this.state.onEditDropped(() => this.sendEditDropped()));
59
79
  }
60
80
 
61
81
  clientEditModeChanged(editMode: EditMode): void {
@@ -69,6 +89,19 @@ export class DefaultDiagramStatusReporter implements DiagramStatusReporter, Clie
69
89
  .catch((error: unknown) => this.state.logger.warn(`Could not send the diagram status: ${describeErrorWithStack(error)}`));
70
90
  }
71
91
 
92
+ /**
93
+ * Warn the client of a dropped edit. Not awaited: the drop is announced
94
+ * inside the diagram's exclusive section, and a dispatch from outside any
95
+ * action queues behind the action being processed, which may be waiting
96
+ * for that section.
97
+ */
98
+ protected sendEditDropped(): void {
99
+ const message = this.sharedServices.MessageRenderer.renderMessage(DIAGRAM_EDIT_DROPPED);
100
+ this.actionDispatcher
101
+ .dispatch(MessageAction.create(message, { severity: 'WARNING' }))
102
+ .catch((error: unknown) => this.state.logger.warn(`Could not warn of a dropped edit: ${describeErrorWithStack(error)}`));
103
+ }
104
+
72
105
  /** The actions that bring the client up to date, recording them as sent. */
73
106
  protected changedActions(): Action[] {
74
107
  const actions: Action[] = [];