@lionweb/class-core 0.7.0-beta.13 → 0.7.0-beta.15

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 (51) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/dist/base-types.d.ts +0 -4
  3. package/dist/base-types.d.ts.map +1 -1
  4. package/dist/base-types.js +0 -25
  5. package/dist/base-types.js.map +1 -1
  6. package/dist/deltas/appliers.d.ts.map +1 -1
  7. package/dist/deltas/appliers.js +2 -1
  8. package/dist/deltas/appliers.js.map +1 -1
  9. package/dist/deltas/inverters.d.ts.map +1 -1
  10. package/dist/deltas/inverters.js +33 -9
  11. package/dist/deltas/inverters.js.map +1 -1
  12. package/dist/deltas/receivers.d.ts.map +1 -1
  13. package/dist/deltas/receivers.js +2 -1
  14. package/dist/deltas/receivers.js.map +1 -1
  15. package/dist/deltas/serialization/deserializer.g.d.ts.map +1 -1
  16. package/dist/deltas/serialization/deserializer.g.js +16 -4
  17. package/dist/deltas/serialization/deserializer.g.js.map +1 -1
  18. package/dist/deserializer.d.ts.map +1 -1
  19. package/dist/deserializer.js +3 -14
  20. package/dist/deserializer.js.map +1 -1
  21. package/dist/factory.d.ts +8 -0
  22. package/dist/factory.d.ts.map +1 -1
  23. package/dist/factory.js +25 -16
  24. package/dist/factory.js.map +1 -1
  25. package/dist/id-mapping.d.ts +21 -3
  26. package/dist/id-mapping.d.ts.map +1 -1
  27. package/dist/id-mapping.js +37 -17
  28. package/dist/id-mapping.js.map +1 -1
  29. package/dist/textualizer.js +1 -1
  30. package/dist/textualizer.js.map +1 -1
  31. package/dist/value-managers/annotations.d.ts.map +1 -1
  32. package/dist/value-managers/annotations.js +1 -2
  33. package/dist/value-managers/annotations.js.map +1 -1
  34. package/dist/value-managers/containments.d.ts +2 -2
  35. package/dist/value-managers/containments.d.ts.map +1 -1
  36. package/dist/value-managers/containments.js +89 -27
  37. package/dist/value-managers/containments.js.map +1 -1
  38. package/dist/value-managers/references.js +2 -2
  39. package/package.json +34 -34
  40. package/src/base-types.ts +0 -25
  41. package/src/deltas/appliers.ts +2 -1
  42. package/src/deltas/inverters.ts +33 -9
  43. package/src/deltas/receivers.ts +2 -1
  44. package/src/deltas/serialization/deserializer.g.ts +19 -7
  45. package/src/deserializer.ts +3 -19
  46. package/src/factory.ts +30 -16
  47. package/src/id-mapping.ts +26 -5
  48. package/src/textualizer.ts +1 -1
  49. package/src/value-managers/annotations.ts +2 -2
  50. package/src/value-managers/containments.ts +87 -27
  51. package/src/value-managers/references.ts +2 -2
@@ -18,12 +18,15 @@
18
18
  import { Containment } from "@lionweb/core"
19
19
  import { action, observable } from "mobx"
20
20
 
21
- import { INodeBase, removeFromParent } from "../base-types.js"
21
+ import { INodeBase } from "../base-types.js"
22
22
  import {
23
23
  ChildAddedDelta,
24
24
  ChildDeletedDelta,
25
- ChildMovedAndReplacedFromOtherContainmentInSameParentDelta, ChildMovedAndReplacedInSameContainmentDelta,
25
+ ChildMovedAndReplacedFromOtherContainmentDelta,
26
+ ChildMovedAndReplacedFromOtherContainmentInSameParentDelta,
27
+ ChildMovedAndReplacedInSameContainmentDelta,
26
28
  ChildMovedFromOtherContainmentDelta,
29
+ ChildMovedFromOtherContainmentInSameParentDelta,
27
30
  ChildMovedInSameContainmentDelta,
28
31
  ChildReplacedDelta
29
32
  } from "../deltas/index.js"
@@ -80,24 +83,38 @@ export abstract class SingleContainmentValueManager<T extends INodeBase> extends
80
83
  this.child.set(newChild);
81
84
  }
82
85
 
83
- @action replaceWith(newChild: T) {
84
- const oldChild = this.getDirectly();
85
- if (oldChild === undefined) {
86
+ @action replaceWith(movedChild: T) {
87
+ const replacedChild = this.getDirectly();
88
+ if (replacedChild === undefined) {
86
89
  // not a proper replace, but an add-set => delegate to regular setter (— unfortunately, through necessarily “unfolding the hierarchy”):
87
90
  if (this instanceof OptionalSingleContainmentValueManager) {
88
- this.set(newChild);
91
+ this.set(movedChild);
89
92
  }
90
93
  if (this instanceof RequiredSingleContainmentValueManager) {
91
- this.set(newChild);
94
+ this.set(movedChild);
92
95
  }
93
96
  } else {
94
- if (oldChild === newChild) {
97
+ if (replacedChild === movedChild) {
95
98
  // do nothing: nothing's changed
96
99
  } else {
97
- oldChild.detach();
98
- this.setDirectly(newChild);
99
- newChild.attachTo(this.container, this.feature);
100
- this.emitDelta(() => new ChildReplacedDelta(this.container, this.feature, 0, oldChild, newChild));
100
+ if (movedChild.parent === undefined) {
101
+ this.emitDelta(() => new ChildReplacedDelta(this.container, this.feature, 0, replacedChild, movedChild));
102
+ } else {
103
+ if (movedChild.parent === this.container) {
104
+ if (movedChild.containment === this.containment) {
105
+ this.emitDelta(() => new ChildMovedAndReplacedInSameContainmentDelta(this.container, this.containment, 0, 0, movedChild, replacedChild));
106
+ } else {
107
+ const oldIndex = removeFromContainment(replacedChild);
108
+ this.emitDelta(() => new ChildMovedAndReplacedFromOtherContainmentInSameParentDelta(this.container, movedChild.containment!, oldIndex, this.containment, 0, movedChild, replacedChild));
109
+ }
110
+ } else {
111
+ const oldIndex = removeFromContainment(replacedChild);
112
+ this.emitDelta(() => new ChildMovedAndReplacedFromOtherContainmentDelta(this.container, this.containment, 0, movedChild, movedChild.parent!, movedChild.containment!, oldIndex, replacedChild));
113
+ }
114
+ }
115
+ this.setDirectly(movedChild);
116
+ movedChild.attachTo(this.container, this.containment);
117
+ replacedChild.detach();
101
118
  }
102
119
  }
103
120
  }
@@ -124,7 +141,7 @@ export class OptionalSingleContainmentValueManager<T extends INodeBase> extends
124
141
  } else {
125
142
  if (newChild.parent && newChild.containment) {
126
143
  const oldParent = newChild.parent;
127
- removeFromParent(oldParent, newChild);
144
+ removeFromContainment(newChild);
128
145
  this.emitDelta(() => new ChildMovedFromOtherContainmentDelta(oldParent, newChild.containment!, 0, this.container, this.feature, 0, newChild));
129
146
  } else {
130
147
  this.emitDelta(() => new ChildAddedDelta(this.container, this.feature, 0, newChild));
@@ -141,13 +158,14 @@ export class OptionalSingleContainmentValueManager<T extends INodeBase> extends
141
158
  if (oldChild === newChild) {
142
159
  // do nothing: nothing's changed
143
160
  } else {
161
+ // FIXME this could emit 2 deltas where it should be a single ChildReplaced-delta
144
162
  if (oldChild.parent && oldChild.containment && oldChild.parent === this.container && oldChild.containment === this.feature) {
145
163
  // FIXME oldChild.parent COULD be this.container
146
164
  this.emitDelta(() => new ChildDeletedDelta(this.container, this.feature, 0, oldChild));
147
165
  }
148
166
  oldChild.detach();
149
167
  if (newChild.parent && newChild.containment) {
150
- removeFromParent(newChild.parent, newChild);
168
+ removeFromContainment(newChild);
151
169
  }
152
170
  this.setDirectly(newChild);
153
171
  newChild.attachTo(this.container, this.feature);
@@ -183,7 +201,7 @@ export class RequiredSingleContainmentValueManager<T extends INodeBase> extends
183
201
  } else {
184
202
  if (newChild.parent && newChild.containment) {
185
203
  const oldParent = newChild.parent;
186
- removeFromParent(oldParent, newChild);
204
+ removeFromContainment(newChild);
187
205
  this.emitDelta(() => new ChildMovedFromOtherContainmentDelta(oldParent, newChild.containment!, 0, this.container, this.feature, 0, newChild));
188
206
  } else {
189
207
  this.emitDelta(() => new ChildAddedDelta(this.container, this.feature, 0, newChild));
@@ -204,7 +222,7 @@ export class RequiredSingleContainmentValueManager<T extends INodeBase> extends
204
222
  }
205
223
  oldChild.detach();
206
224
  if (newChild.parent && newChild.containment) {
207
- removeFromParent(newChild.parent, newChild);
225
+ removeFromContainment(newChild);
208
226
  }
209
227
  this.setDirectly(newChild);
210
228
  newChild.attachTo(this.container, this.feature);
@@ -251,16 +269,31 @@ export abstract class MultiContainmentValueManager<T extends INodeBase> extends
251
269
  this.children.splice(index, 0, newChild);
252
270
  }
253
271
 
254
- @action insertAtIndex(newChild: T, index: number) {
255
- this.insertAtIndexDirectly(newChild, index);
256
- if (newChild.parent === undefined && newChild.containment === undefined) {
257
- this.emitDelta(() => new ChildAddedDelta(this.container, this.containment, index, newChild));
272
+ @action insertAtIndex(newChild: T, newIndex: number) {
273
+ if (newChild.parent === undefined) {
274
+ this.insertAtIndexDirectly(newChild, newIndex);
275
+ newChild.attachTo(this.container, this.containment);
276
+ this.emitDelta(() => new ChildAddedDelta(this.container, this.containment, newIndex, newChild));
258
277
  } else {
259
- const oldIndex = removeFromParent(newChild.parent, newChild);
260
- this.emitDelta(() => new ChildMovedFromOtherContainmentDelta(newChild.parent!, newChild.containment!, oldIndex, this.container, this.containment, index, newChild));
261
- newChild.detach();
278
+ if (newChild.parent === this.container) {
279
+ if (newChild.containment === this.containment) {
280
+ const oldIndex = this.children.indexOf(newChild);
281
+ this.moveDirectly(oldIndex, newIndex);
282
+ this.emitDelta(() => new ChildMovedInSameContainmentDelta(this.container, this.containment, oldIndex, newIndex, newChild));
283
+ } else {
284
+ const oldIndex = removeFromContainment(newChild);
285
+ checkIndex(newIndex, this.children.length, true);
286
+ this.insertAtIndexDirectly(newChild, newIndex);
287
+ this.emitDelta(() => new ChildMovedFromOtherContainmentInSameParentDelta(this.container, newChild.containment!, oldIndex, newChild, this.containment, newIndex));
288
+ newChild.attachTo(this.container, this.containment);
289
+ }
290
+ } else {
291
+ const oldIndex = removeFromContainment(newChild);
292
+ this.insertAtIndexDirectly(newChild, newIndex);
293
+ this.emitDelta(() => new ChildMovedFromOtherContainmentDelta(newChild.parent!, newChild.containment!, oldIndex, this.container, this.containment, newIndex, newChild));
294
+ newChild.attachTo(this.container, this.containment);
295
+ }
262
296
  }
263
- newChild.attachTo(this.container, this.containment);
264
297
  }
265
298
 
266
299
  @action removeDirectly(childToRemove: T): number {
@@ -298,18 +331,20 @@ export abstract class MultiContainmentValueManager<T extends INodeBase> extends
298
331
 
299
332
  @action replaceAtIndex(movedChild: T, newIndex: number) {
300
333
  checkIndex(newIndex, this.children.length, false);
334
+ if (movedChild.parent === undefined) {
335
+ throw new Error(`a child-to-move (id=${movedChild.id}) must already be contained`);
336
+ }
301
337
  const replacedChild = this.children[newIndex];
302
338
  if (replacedChild === movedChild) {
303
339
  // do nothing: nothing's changed
304
340
  } else {
305
341
  this.children.splice(newIndex, 1, movedChild);
306
- if (replacedChild.parent) {
342
+ if (replacedChild.parent !== undefined) {
307
343
  const oldValueManager = replacedChild.parent.getContainmentValueManager(replacedChild.containment!);
308
344
  const oldIndex = oldValueManager instanceof SingleContainmentValueManager
309
345
  ? 0
310
346
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
311
347
  : (oldValueManager as MultiContainmentValueManager<any>).children.indexOf(replacedChild);
312
- replacedChild.detach();
313
348
  if (replacedChild.parent === movedChild.parent) {
314
349
  if (replacedChild.containment === movedChild.containment) {
315
350
  this.emitDelta(() => new ChildMovedAndReplacedInSameContainmentDelta(this.container, this.containment, oldIndex, newIndex, movedChild, replacedChild));
@@ -317,8 +352,9 @@ export abstract class MultiContainmentValueManager<T extends INodeBase> extends
317
352
  this.emitDelta(() => new ChildMovedAndReplacedFromOtherContainmentInSameParentDelta(this.container, replacedChild.containment!, oldIndex, this.containment, newIndex, movedChild, replacedChild));
318
353
  }
319
354
  } else {
320
- this.emitDelta(() => new ChildMovedFromOtherContainmentDelta(replacedChild.parent!, replacedChild.containment!, oldIndex, this.container, this.containment, newIndex, movedChild));
355
+ this.emitDelta(() => new ChildMovedAndReplacedFromOtherContainmentDelta(this.container, this.containment, newIndex, movedChild, movedChild.parent!, movedChild.containment!, oldIndex, replacedChild));
321
356
  }
357
+ replacedChild.detach();
322
358
  } else {
323
359
  // not a move+replace, but a regular replace instead:
324
360
  this.emitDelta(() => new ChildReplacedDelta(this.container, this.containment, newIndex, replacedChild, movedChild));
@@ -380,3 +416,27 @@ export class RequiredMultiContainmentValueManager<T extends INodeBase> extends M
380
416
 
381
417
  }
382
418
 
419
+ /**
420
+ * Removes the given child node from its containment, and returns the containment index it had before removal.
421
+ */
422
+ const removeFromContainment = (child: INodeBase): number => {
423
+ if (child.parent === undefined) {
424
+ throw new Error(`can't remove an orphan from its parent`)
425
+ }
426
+ if (child.containment === undefined) {
427
+ throw new Error(`can't remove an orphan from its containing feature`)
428
+ }
429
+ if (child.containment === null) {
430
+ throw new Error(`can't remove an annotation`)
431
+ }
432
+ const valueManager = child.parent.getContainmentValueManager(child.containment)
433
+ if (valueManager instanceof SingleContainmentValueManager) {
434
+ valueManager.setDirectly(undefined)
435
+ return 0
436
+ } else if (valueManager instanceof MultiContainmentValueManager) {
437
+ return valueManager.removeDirectly(child)
438
+ } else {
439
+ throw new Error(`don't know how to remove a child that's contained through a value manager of type ${valueManager.constructor.name}`)
440
+ }
441
+ }
442
+
@@ -106,7 +106,7 @@ export class OptionalSingleReferenceValueManager<T extends INodeBase> extends Si
106
106
  if (oldTarget === undefined) {
107
107
  this.emitDelta(() => new ReferenceAddedDelta(this.container, this.reference, 0, newTarget));
108
108
  } else {
109
- this.emitDelta(() => new ReferenceChangedDelta(this.container, this.reference, 0, oldTarget, newTarget));
109
+ this.emitDelta(() => new ReferenceChangedDelta(this.container, this.reference, 0, newTarget, oldTarget));
110
110
  }
111
111
  }
112
112
  }
@@ -142,7 +142,7 @@ export class RequiredSingleReferenceValueManager<T extends INodeBase> extends Si
142
142
  if (oldTarget === undefined) {
143
143
  this.emitDelta(() => new ReferenceAddedDelta(this.container, this.reference, 0, newTarget));
144
144
  } else {
145
- this.emitDelta(() => new ReferenceChangedDelta(this.container, this.reference, 0, oldTarget, newTarget));
145
+ this.emitDelta(() => new ReferenceChangedDelta(this.container, this.reference, 0, newTarget, oldTarget));
146
146
  }
147
147
  }
148
148
  }