@hydranium/core 1.0.0-next.357 → 1.0.0-next.359
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.
- package/lib/langium/keys/containment.d.ts +3 -2
- package/lib/langium/keys/containment.d.ts.map +1 -1
- package/lib/langium/keys/containment.js.map +1 -1
- package/lib/langium/keys/name-based-key-provider.d.ts +17 -10
- package/lib/langium/keys/name-based-key-provider.d.ts.map +1 -1
- package/lib/langium/keys/name-based-key-provider.js +24 -12
- package/lib/langium/keys/name-based-key-provider.js.map +1 -1
- package/package.json +5 -5
- package/src/langium/keys/containment.ts +3 -2
- package/src/langium/keys/name-based-key-provider.ts +24 -12
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
*
|
|
13
13
|
* **These live beside the key provider because the constraint is the key
|
|
14
14
|
* provider's.** `NameBasedKeyProvider` keys a node the `NameProvider` gives no
|
|
15
|
-
* name from its position, as `` `${$containerProperty}@${$containerIndex}`
|
|
16
|
-
*
|
|
15
|
+
* name from its position, as `` `${$containerProperty}@${$containerIndex}` ``
|
|
16
|
+
* (`` `${$containerProperty}@` `` in a single-valued property), so a node
|
|
17
|
+
* appended with a bare `array.push` carries neither and
|
|
17
18
|
* `getElementKey` answers `undefined` — the element has no key at all, and the
|
|
18
19
|
* GLSP index cannot address it. Deleting from the middle of such a list must
|
|
19
20
|
* renumber the survivors, or an id derived later in the same command names the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containment.d.ts","sourceRoot":"","sources":["../../../src/langium/keys/containment.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF
|
|
1
|
+
{"version":3,"file":"containment.d.ts","sourceRoot":"","sources":["../../../src/langium/keys/containment.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGlD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,MAAM,SAAS,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnI;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,MAAM,SAAS,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,CAYhH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containment.js","sourceRoot":"","sources":["../../../src/langium/keys/containment.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;
|
|
1
|
+
{"version":3,"file":"containment.js","sourceRoot":"","sources":["../../../src/langium/keys/containment.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAoClF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAyB,SAAkB,EAAE,QAAgB,EAAE,QAAkB,EAAE,KAAa;IACxH,MAAM,OAAO,GAAG,KAAwB,CAAC;IACzC,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAC/B,OAAO,CAAC,kBAAkB,GAAG,QAAQ,CAAC;IACtC,OAAO,CAAC,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC;AAChB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAyB,QAAkB,EAAE,QAA6B;IACrG,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,CAAC;IACZ,CAAC;IACD,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;IACnD,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/C,KAAyB,CAAC,eAAe,GAAG,KAAK,CAAC;QACnD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,OAAO,CAAC;AAClB,CAAC"}
|
|
@@ -42,20 +42,25 @@ import { type NameProvider } from '../naming/name-provider.js';
|
|
|
42
42
|
* `NameProvider` gives no name. For grammars with unnamed element types the
|
|
43
43
|
* reorder / insert / delete stability above does NOT apply to those nodes:
|
|
44
44
|
* their keys move when their index moves, so a mid-array insert or delete
|
|
45
|
-
* renumbers every later sibling.
|
|
45
|
+
* renumbers every later sibling. A node held in a single-valued property has
|
|
46
|
+
* no `$containerIndex` and falls back to `` `${$containerProperty}@` ``; the
|
|
47
|
+
* trailing `@` keeps its key apart from a sibling named after the property.
|
|
46
48
|
*
|
|
47
49
|
* Two consequences for a caller creating such nodes programmatically
|
|
48
50
|
* (a GLSP operation handler is the usual case):
|
|
49
51
|
*
|
|
50
|
-
* - A node appended with a bare `array.push
|
|
51
|
-
* `$
|
|
52
|
-
* has no key at all. The
|
|
52
|
+
* - A node appended with a bare `array.push`, or assigned to a single-valued
|
|
53
|
+
* property without its `$containerProperty`, has no container position, so
|
|
54
|
+
* `getElementKey` returns `undefined` and the node has no key at all. The
|
|
55
|
+
* containment plumbing has to be stamped.
|
|
53
56
|
* - After a removal, surviving siblings need their `$containerIndex`
|
|
54
57
|
* renumbered, or a key derived afterwards addresses the wrong node.
|
|
55
58
|
*
|
|
56
|
-
* {@link appendChild} and {@link removeChildren} discharge both
|
|
57
|
-
* beside this provider because the constraint is this provider's
|
|
58
|
-
* any caller's.
|
|
59
|
+
* {@link appendChild} and {@link removeChildren} discharge both for arrays,
|
|
60
|
+
* and ship beside this provider because the constraint is this provider's
|
|
61
|
+
* rather than any caller's. A single-valued property needs no helper: build
|
|
62
|
+
* the node with its `$container` and `$containerProperty`, which
|
|
63
|
+
* `buildAstNode` accepts.
|
|
59
64
|
*
|
|
60
65
|
* Adopters that need insert / delete stability for unnamed types should
|
|
61
66
|
* give those types a name in the grammar, or bind a key provider whose
|
|
@@ -94,9 +99,11 @@ export declare class NameBasedKeyProvider implements ElementKeyProvider {
|
|
|
94
99
|
*/
|
|
95
100
|
protected isSemanticRoot(node: AstNode): boolean;
|
|
96
101
|
/**
|
|
97
|
-
*
|
|
98
|
-
* `containerProperty@containerIndex
|
|
99
|
-
*
|
|
102
|
+
* Segment for a node the `NameProvider` gives no name —
|
|
103
|
+
* `containerProperty@containerIndex`, or `containerProperty@` when the
|
|
104
|
+
* container holds no array in that property, attached or not. Returns
|
|
105
|
+
* `undefined` when the node has no container position: the node itself
|
|
106
|
+
* then has no key, and an ancestor's level is left out of the key.
|
|
100
107
|
*/
|
|
101
108
|
protected unidentifiedSegment(node: AstNode): string | undefined;
|
|
102
109
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"name-based-key-provider.d.ts","sourceRoot":"","sources":["../../../src/langium/keys/name-based-key-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,KAAK,kBAAkB,EAAwB,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D
|
|
1
|
+
{"version":3,"file":"name-based-key-provider.d.ts","sourceRoot":"","sources":["../../../src/langium/keys/name-based-key-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,KAAK,kBAAkB,EAAwB,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,qBAAa,oBAAqB,YAAW,kBAAkB;IAKzD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,sBAAsB;IAJtD,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IAC9C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAElC,YACsB,QAAQ,EAAE,sBAAsB,EACnD,OAAO,GAAE,cAAmB,EAI9B;IAED,aAAa,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAqBhD;IAED;;;;;;;OAOG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAEjE;IAED;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAQ/C;IAED;;;;;;OAMG;IACH,SAAS,CAAC,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAU/D;CACH"}
|
|
@@ -37,20 +37,25 @@ import { resolveElementByScan } from './element-key-provider.js';
|
|
|
37
37
|
* `NameProvider` gives no name. For grammars with unnamed element types the
|
|
38
38
|
* reorder / insert / delete stability above does NOT apply to those nodes:
|
|
39
39
|
* their keys move when their index moves, so a mid-array insert or delete
|
|
40
|
-
* renumbers every later sibling.
|
|
40
|
+
* renumbers every later sibling. A node held in a single-valued property has
|
|
41
|
+
* no `$containerIndex` and falls back to `` `${$containerProperty}@` ``; the
|
|
42
|
+
* trailing `@` keeps its key apart from a sibling named after the property.
|
|
41
43
|
*
|
|
42
44
|
* Two consequences for a caller creating such nodes programmatically
|
|
43
45
|
* (a GLSP operation handler is the usual case):
|
|
44
46
|
*
|
|
45
|
-
* - A node appended with a bare `array.push
|
|
46
|
-
* `$
|
|
47
|
-
* has no key at all. The
|
|
47
|
+
* - A node appended with a bare `array.push`, or assigned to a single-valued
|
|
48
|
+
* property without its `$containerProperty`, has no container position, so
|
|
49
|
+
* `getElementKey` returns `undefined` and the node has no key at all. The
|
|
50
|
+
* containment plumbing has to be stamped.
|
|
48
51
|
* - After a removal, surviving siblings need their `$containerIndex`
|
|
49
52
|
* renumbered, or a key derived afterwards addresses the wrong node.
|
|
50
53
|
*
|
|
51
|
-
* {@link appendChild} and {@link removeChildren} discharge both
|
|
52
|
-
* beside this provider because the constraint is this provider's
|
|
53
|
-
* any caller's.
|
|
54
|
+
* {@link appendChild} and {@link removeChildren} discharge both for arrays,
|
|
55
|
+
* and ship beside this provider because the constraint is this provider's
|
|
56
|
+
* rather than any caller's. A single-valued property needs no helper: build
|
|
57
|
+
* the node with its `$container` and `$containerProperty`, which
|
|
58
|
+
* `buildAstNode` accepts.
|
|
54
59
|
*
|
|
55
60
|
* Adopters that need insert / delete stability for unnamed types should
|
|
56
61
|
* give those types a name in the grammar, or bind a key provider whose
|
|
@@ -124,15 +129,22 @@ export class NameBasedKeyProvider {
|
|
|
124
129
|
return false;
|
|
125
130
|
}
|
|
126
131
|
/**
|
|
127
|
-
*
|
|
128
|
-
* `containerProperty@containerIndex
|
|
129
|
-
*
|
|
132
|
+
* Segment for a node the `NameProvider` gives no name —
|
|
133
|
+
* `containerProperty@containerIndex`, or `containerProperty@` when the
|
|
134
|
+
* container holds no array in that property, attached or not. Returns
|
|
135
|
+
* `undefined` when the node has no container position: the node itself
|
|
136
|
+
* then has no key, and an ancestor's level is left out of the key.
|
|
130
137
|
*/
|
|
131
138
|
unidentifiedSegment(node) {
|
|
132
|
-
|
|
139
|
+
const property = node.$containerProperty;
|
|
140
|
+
if (property === undefined) {
|
|
133
141
|
return undefined;
|
|
134
142
|
}
|
|
135
|
-
|
|
143
|
+
if (node.$containerIndex !== undefined) {
|
|
144
|
+
return `${property}@${node.$containerIndex}`;
|
|
145
|
+
}
|
|
146
|
+
// An array member without its index stays keyless rather than share `property@` with its siblings.
|
|
147
|
+
return Array.isArray(node.$container?.[property]) ? undefined : `${property}@`;
|
|
136
148
|
}
|
|
137
149
|
}
|
|
138
150
|
//# sourceMappingURL=name-based-key-provider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"name-based-key-provider.js","sourceRoot":"","sources":["../../../src/langium/keys/name-based-key-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAMlF,OAAO,EAA2B,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAG1F
|
|
1
|
+
{"version":3,"file":"name-based-key-provider.js","sourceRoot":"","sources":["../../../src/langium/keys/name-based-key-provider.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hydranium/core",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.359",
|
|
4
4
|
"description": "Foundational runtime of the hydranium framework: AST coordination layer (services, integrity, AST extension, serialization, multi-client documents) plus the LSP textual head at the /lsp subpath. Consumed by protocol-head packages (@hydranium/data-server, @hydranium/glsp-server).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ast",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"diff": "^5.2.0"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
|
-
"@hydranium/langium": "1.0.0-next.
|
|
91
|
-
"@hydranium/protocol": "1.0.0-next.
|
|
90
|
+
"@hydranium/langium": "1.0.0-next.359",
|
|
91
|
+
"@hydranium/protocol": "1.0.0-next.359",
|
|
92
92
|
"@playwright/test": "^1.55.0",
|
|
93
93
|
"@types/diff": "^5.2.0",
|
|
94
94
|
"fake-indexeddb": "^6.2.5",
|
|
@@ -101,8 +101,8 @@
|
|
|
101
101
|
"vscode-languageserver-types": "3.18.0"
|
|
102
102
|
},
|
|
103
103
|
"peerDependencies": {
|
|
104
|
-
"@hydranium/langium": "1.0.0-next.
|
|
105
|
-
"@hydranium/protocol": "1.0.0-next.
|
|
104
|
+
"@hydranium/langium": "1.0.0-next.359",
|
|
105
|
+
"@hydranium/protocol": "1.0.0-next.359",
|
|
106
106
|
"@playwright/test": "^1.40.0",
|
|
107
107
|
"vscode-jsonrpc": "^9.0.0",
|
|
108
108
|
"vscode-languageserver": "~10.0.1",
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
*
|
|
14
14
|
* **These live beside the key provider because the constraint is the key
|
|
15
15
|
* provider's.** `NameBasedKeyProvider` keys a node the `NameProvider` gives no
|
|
16
|
-
* name from its position, as `` `${$containerProperty}@${$containerIndex}`
|
|
17
|
-
*
|
|
16
|
+
* name from its position, as `` `${$containerProperty}@${$containerIndex}` ``
|
|
17
|
+
* (`` `${$containerProperty}@` `` in a single-valued property), so a node
|
|
18
|
+
* appended with a bare `array.push` carries neither and
|
|
18
19
|
* `getElementKey` answers `undefined` — the element has no key at all, and the
|
|
19
20
|
* GLSP index cannot address it. Deleting from the middle of such a list must
|
|
20
21
|
* renumber the survivors, or an id derived later in the same command names the
|
|
@@ -44,20 +44,25 @@ import { type NameProvider } from '../naming/name-provider.js';
|
|
|
44
44
|
* `NameProvider` gives no name. For grammars with unnamed element types the
|
|
45
45
|
* reorder / insert / delete stability above does NOT apply to those nodes:
|
|
46
46
|
* their keys move when their index moves, so a mid-array insert or delete
|
|
47
|
-
* renumbers every later sibling.
|
|
47
|
+
* renumbers every later sibling. A node held in a single-valued property has
|
|
48
|
+
* no `$containerIndex` and falls back to `` `${$containerProperty}@` ``; the
|
|
49
|
+
* trailing `@` keeps its key apart from a sibling named after the property.
|
|
48
50
|
*
|
|
49
51
|
* Two consequences for a caller creating such nodes programmatically
|
|
50
52
|
* (a GLSP operation handler is the usual case):
|
|
51
53
|
*
|
|
52
|
-
* - A node appended with a bare `array.push
|
|
53
|
-
* `$
|
|
54
|
-
* has no key at all. The
|
|
54
|
+
* - A node appended with a bare `array.push`, or assigned to a single-valued
|
|
55
|
+
* property without its `$containerProperty`, has no container position, so
|
|
56
|
+
* `getElementKey` returns `undefined` and the node has no key at all. The
|
|
57
|
+
* containment plumbing has to be stamped.
|
|
55
58
|
* - After a removal, surviving siblings need their `$containerIndex`
|
|
56
59
|
* renumbered, or a key derived afterwards addresses the wrong node.
|
|
57
60
|
*
|
|
58
|
-
* {@link appendChild} and {@link removeChildren} discharge both
|
|
59
|
-
* beside this provider because the constraint is this provider's
|
|
60
|
-
* any caller's.
|
|
61
|
+
* {@link appendChild} and {@link removeChildren} discharge both for arrays,
|
|
62
|
+
* and ship beside this provider because the constraint is this provider's
|
|
63
|
+
* rather than any caller's. A single-valued property needs no helper: build
|
|
64
|
+
* the node with its `$container` and `$containerProperty`, which
|
|
65
|
+
* `buildAstNode` accepts.
|
|
61
66
|
*
|
|
62
67
|
* Adopters that need insert / delete stability for unnamed types should
|
|
63
68
|
* give those types a name in the grammar, or bind a key provider whose
|
|
@@ -137,14 +142,21 @@ export class NameBasedKeyProvider implements ElementKeyProvider {
|
|
|
137
142
|
}
|
|
138
143
|
|
|
139
144
|
/**
|
|
140
|
-
*
|
|
141
|
-
* `containerProperty@containerIndex
|
|
142
|
-
*
|
|
145
|
+
* Segment for a node the `NameProvider` gives no name —
|
|
146
|
+
* `containerProperty@containerIndex`, or `containerProperty@` when the
|
|
147
|
+
* container holds no array in that property, attached or not. Returns
|
|
148
|
+
* `undefined` when the node has no container position: the node itself
|
|
149
|
+
* then has no key, and an ancestor's level is left out of the key.
|
|
143
150
|
*/
|
|
144
151
|
protected unidentifiedSegment(node: AstNode): string | undefined {
|
|
145
|
-
|
|
152
|
+
const property = node.$containerProperty;
|
|
153
|
+
if (property === undefined) {
|
|
146
154
|
return undefined;
|
|
147
155
|
}
|
|
148
|
-
|
|
156
|
+
if (node.$containerIndex !== undefined) {
|
|
157
|
+
return `${property}@${node.$containerIndex}`;
|
|
158
|
+
}
|
|
159
|
+
// An array member without its index stays keyless rather than share `property@` with its siblings.
|
|
160
|
+
return Array.isArray((node.$container as Record<string, unknown> | undefined)?.[property]) ? undefined : `${property}@`;
|
|
149
161
|
}
|
|
150
162
|
}
|