@bablr/agast-helpers 0.7.1 → 0.9.0
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/builders.js +110 -49
- package/lib/object.js +86 -0
- package/lib/path-facade.js +44 -0
- package/lib/path.js +780 -556
- package/lib/print.js +75 -97
- package/lib/shorthand.js +26 -1
- package/lib/stream.js +55 -163
- package/lib/symbols.js +6 -2
- package/lib/tags.js +236 -0
- package/lib/template.js +28 -37
- package/lib/tree.js +391 -213
- package/package.json +11 -6
- package/lib/sumtree.js +0 -62
package/lib/path.js
CHANGED
|
@@ -1,72 +1,154 @@
|
|
|
1
1
|
import { WeakStackFrame } from '@bablr/weak-stack';
|
|
2
|
-
import * as
|
|
3
|
-
import * as
|
|
2
|
+
import * as BTree from '@bablr/agast-helpers/btree';
|
|
3
|
+
import * as Tags from './tags.js';
|
|
4
4
|
import {
|
|
5
5
|
ReferenceTag,
|
|
6
6
|
InitializerTag,
|
|
7
|
-
EmbeddedNode,
|
|
8
7
|
DoctypeTag,
|
|
9
|
-
OpenNodeTag,
|
|
10
8
|
CloseNodeTag,
|
|
11
9
|
GapTag,
|
|
12
10
|
NullTag,
|
|
13
11
|
ShiftTag,
|
|
12
|
+
BindingTag,
|
|
13
|
+
PropertyWrapper,
|
|
14
|
+
Property,
|
|
14
15
|
} from './symbols.js';
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
buildGapTag,
|
|
19
|
-
buildReferenceTag,
|
|
20
|
-
buildShiftTag,
|
|
21
|
-
} from './builders.js';
|
|
16
|
+
import { isPlainObject, isString } from './object.js';
|
|
17
|
+
import { buildBinding, buildChild, buildProperty, buildPropertyWrapper } from './builders.js';
|
|
18
|
+
import { buildReferenceTag, finalizeNode } from './tree.js';
|
|
22
19
|
|
|
23
|
-
export const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
export const wrapperIsFull = (wrapper) => {
|
|
21
|
+
let { tags } = wrapper.value;
|
|
22
|
+
|
|
23
|
+
if (tags[1]?.type === InitializerTag) {
|
|
24
|
+
return true;
|
|
25
|
+
} else {
|
|
26
|
+
return tags.length === 3;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const offsetForTag = (tag) => {
|
|
31
|
+
switch (tag.type) {
|
|
32
|
+
case ReferenceTag:
|
|
33
|
+
case ShiftTag:
|
|
34
|
+
return 0;
|
|
35
|
+
case BindingTag:
|
|
36
|
+
case InitializerTag:
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const buildPathSegment = (name, index = null, shiftIndex = null) => {
|
|
42
|
+
if (!name) throw new Error();
|
|
43
|
+
return { type: null, name, index, shiftIndex };
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const buildTypePathSegment = (type, index = null, shiftIndex = null) => {
|
|
47
|
+
if (!type) throw new Error();
|
|
48
|
+
return { type, name: null, index, shiftIndex };
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const buildFullPathSegment = (type, name, index = null, shiftIndex = null) => {
|
|
52
|
+
return { type, name, index, shiftIndex };
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const getRootProperty = (node, index = 0) => {
|
|
56
|
+
if (node == null || !isFragmentNode(node)) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
let idx = getPropertyTagsIndex(node, '.', null, index);
|
|
60
|
+
|
|
61
|
+
if (idx == null) return null;
|
|
62
|
+
|
|
63
|
+
let tag = Tags.getAt(idx, node.tags);
|
|
64
|
+
|
|
65
|
+
if (tag.type !== PropertyWrapper) throw new Error();
|
|
66
|
+
return tag.value.property;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const getRoot = (node, index = 0) => {
|
|
70
|
+
if (!isFragmentNode(node)) {
|
|
71
|
+
return node;
|
|
29
72
|
}
|
|
30
|
-
|
|
31
|
-
return
|
|
73
|
+
|
|
74
|
+
return getRootProperty(node, index)?.node;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const getRootArray = (node) => {
|
|
78
|
+
let arr = [];
|
|
79
|
+
for (let i = 0; ; i++) {
|
|
80
|
+
let root = getRoot(node, i);
|
|
81
|
+
if (root) {
|
|
82
|
+
arr.push(root);
|
|
83
|
+
} else {
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return arr;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const getOpenTag = (node) => {
|
|
91
|
+
return Tags.getValues(node.tags)[0];
|
|
32
92
|
};
|
|
33
93
|
|
|
34
94
|
export const getCloseTag = (node) => {
|
|
35
|
-
|
|
36
|
-
const tag = sumtree.getAt(-1, children);
|
|
37
|
-
if (tag.type !== CloseNodeTag) return null;
|
|
38
|
-
return tag;
|
|
95
|
+
return Tags.getValues(node.tags)[2];
|
|
39
96
|
};
|
|
40
97
|
|
|
41
98
|
export const isNullNode = (node) => {
|
|
42
|
-
return node && node.type === null &&
|
|
99
|
+
return node && node.type === null && Tags.getAt(0, node.tags).type === NullTag;
|
|
43
100
|
};
|
|
44
101
|
|
|
45
102
|
export const isFragmentNode = (node) => {
|
|
46
|
-
return node && node.type === null && getOpenTag(node)?.value
|
|
103
|
+
return node && node.type === null && getOpenTag(node)?.value?.type === null;
|
|
47
104
|
};
|
|
48
105
|
|
|
49
106
|
export const isGapNode = (node) => {
|
|
50
|
-
return node && node.type === null &&
|
|
107
|
+
return node && node.type === null && Tags.getAt(0, node.tags).type === GapTag;
|
|
51
108
|
};
|
|
52
109
|
|
|
53
|
-
export const
|
|
54
|
-
|
|
110
|
+
export const isStubNode = (node) => {
|
|
111
|
+
return node && node.type === null && [GapTag, NullTag].includes(Tags.getAt(0, node.tags).type);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const isStubTag = (tag) => {
|
|
115
|
+
return [GapTag, NullTag].includes(tag.type);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const getChildPropertyIndex = (agAstNode, tagsIndex) => {
|
|
119
|
+
let child = Tags.getAt(tagsIndex, agAstNode.tags);
|
|
120
|
+
|
|
121
|
+
if (child.type !== PropertyWrapper) return null;
|
|
122
|
+
|
|
123
|
+
let tag = child.value.tags[0];
|
|
124
|
+
|
|
125
|
+
let refIndex = tag.type === ShiftTag ? tagsIndex - tag.value.index : tagsIndex;
|
|
126
|
+
|
|
127
|
+
let stack = Tags.findPath(refIndex, agAstNode.tags);
|
|
55
128
|
let { node, index: leafIdx } = stack.value;
|
|
56
|
-
let leaf =
|
|
129
|
+
let leaf = Tags.getAt(leafIdx, node);
|
|
57
130
|
|
|
58
|
-
if (leaf.type !==
|
|
131
|
+
if (leaf.type !== PropertyWrapper) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let leafRefTag = leaf.value.tags[0];
|
|
136
|
+
|
|
137
|
+
if (leafRefTag.type !== ReferenceTag) return null;
|
|
59
138
|
|
|
60
|
-
let { name, isArray } =
|
|
139
|
+
let { name, isArray } = leafRefTag.value;
|
|
61
140
|
let count = -1;
|
|
62
141
|
|
|
63
142
|
if (!isArray) return null;
|
|
64
143
|
|
|
65
144
|
for (let i = leafIdx; i >= 0; i--) {
|
|
66
|
-
let value =
|
|
145
|
+
let value = Tags.getAt(i, node);
|
|
146
|
+
if (value.type === PropertyWrapper) {
|
|
147
|
+
let firstTag = value.value.tags[0];
|
|
67
148
|
|
|
68
|
-
|
|
69
|
-
|
|
149
|
+
if (firstTag.type === ReferenceTag && firstTag.value.name === name) {
|
|
150
|
+
count++;
|
|
151
|
+
}
|
|
70
152
|
}
|
|
71
153
|
}
|
|
72
154
|
stack = stack.pop();
|
|
@@ -77,11 +159,17 @@ export const getChildPropertyIndex = (agAstNode, childrenIndex) => {
|
|
|
77
159
|
|
|
78
160
|
do {
|
|
79
161
|
for (let i = leafIdx - 1; i >= 0; i--) {
|
|
80
|
-
let
|
|
81
|
-
|
|
162
|
+
let value = Tags.getValues(node)[i];
|
|
163
|
+
|
|
164
|
+
if (Array.isArray(value)) {
|
|
165
|
+
let childNode = value;
|
|
166
|
+
let { references } = Tags.getSums(childNode);
|
|
82
167
|
|
|
83
|
-
|
|
84
|
-
|
|
168
|
+
let res;
|
|
169
|
+
if ((res = Tags.getAtName(name, references))) {
|
|
170
|
+
count += res;
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
85
173
|
}
|
|
86
174
|
}
|
|
87
175
|
stack = stack.pop();
|
|
@@ -95,61 +183,129 @@ export const getChildPropertyIndex = (agAstNode, childrenIndex) => {
|
|
|
95
183
|
return count - 1;
|
|
96
184
|
};
|
|
97
185
|
|
|
98
|
-
export const
|
|
99
|
-
let
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
186
|
+
export const getPropertyTagsIndex = (agAstNode, type, name, index, shiftIndex) => {
|
|
187
|
+
let firstPropsIndex = __getPropertyTagsIndex(agAstNode, type, name, 0);
|
|
188
|
+
let prop = firstPropsIndex == null ? null : Tags.getAt(firstPropsIndex, agAstNode.tags);
|
|
189
|
+
let initializerOffset = prop?.value.tags[1]?.type === InitializerTag ? 1 : 0;
|
|
190
|
+
let ref = prop?.value.property.reference;
|
|
191
|
+
let sums = Tags.getSums(agAstNode.tags);
|
|
192
|
+
|
|
193
|
+
if (ref?.isArray) {
|
|
194
|
+
if (index < 0) {
|
|
195
|
+
if (name) {
|
|
196
|
+
index = Tags.getAtName(name, sums.references) - initializerOffset + index;
|
|
197
|
+
} else {
|
|
198
|
+
index = Tags.getAtName(type, sums.specialTypes) - initializerOffset + index;
|
|
199
|
+
}
|
|
200
|
+
} else if (index == null) {
|
|
201
|
+
if (name) {
|
|
202
|
+
index = Tags.getAtName(name, sums.references) - 1 - initializerOffset;
|
|
203
|
+
} else {
|
|
204
|
+
index = Tags.getAtName(type, sums.specialTypes) - 1 - initializerOffset;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (index < 0) return null;
|
|
103
208
|
}
|
|
104
209
|
}
|
|
105
210
|
|
|
106
|
-
let
|
|
107
|
-
|
|
211
|
+
let parentIndex = __getPropertyTagsIndex(agAstNode, type, name, (index ?? 0) + initializerOffset);
|
|
212
|
+
|
|
213
|
+
if (ref?.flags.expression) {
|
|
214
|
+
let shiftIndex_ = shiftIndex == null ? -1 : shiftIndex;
|
|
215
|
+
if (shiftIndex_ < 0) {
|
|
216
|
+
let shifts = 0;
|
|
217
|
+
// TODO speed this up for deeply nested shifts
|
|
218
|
+
// algorithm: make big jump forward, then look at shift index to see if we overshot completely
|
|
219
|
+
// works because we know the size of the thing and a bigger thing doesn't fit in a smaller one
|
|
220
|
+
while (Tags.getAt(parentIndex + shifts + 1, agAstNode.tags, 0)?.type === ShiftTag) {
|
|
221
|
+
shifts++;
|
|
222
|
+
}
|
|
108
223
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
224
|
+
if (-shiftIndex_ > shifts + 1) return null;
|
|
225
|
+
|
|
226
|
+
return parentIndex + shifts + shiftIndex_ + 1;
|
|
227
|
+
} else {
|
|
228
|
+
if (parentIndex + shiftIndex_ >= Tags.getSize(agAstNode.tags)) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return parentIndex + shiftIndex_;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return parentIndex;
|
|
114
237
|
};
|
|
115
238
|
|
|
116
|
-
export const
|
|
117
|
-
|
|
239
|
+
export const getInitializerTagsIndex = (agAstNode, referenceTag) => {
|
|
240
|
+
let { type, name } = referenceTag.value;
|
|
241
|
+
|
|
242
|
+
if (type === '#') return null;
|
|
243
|
+
|
|
244
|
+
let index = __getPropertyTagsIndex(agAstNode, type, name, 0);
|
|
245
|
+
|
|
246
|
+
if (index == null) return null;
|
|
247
|
+
|
|
248
|
+
let nextTag = Tags.getAt(index, agAstNode.tags, 1);
|
|
249
|
+
|
|
250
|
+
return nextTag?.type === InitializerTag ? index : null;
|
|
118
251
|
};
|
|
119
252
|
|
|
120
|
-
const
|
|
253
|
+
const __getPropertyTagsIndex = (agAstNode, type, name, index) => {
|
|
121
254
|
let nameCount = 0;
|
|
122
|
-
let node = agAstNode.
|
|
255
|
+
let node = Tags.getValues(agAstNode.tags)[1];
|
|
123
256
|
let idx = -1;
|
|
124
257
|
|
|
125
258
|
// drill into subtrees, passing over subtrees with too few references of the desired name
|
|
126
259
|
outer: while (node) {
|
|
127
|
-
let
|
|
128
|
-
|
|
129
|
-
|
|
260
|
+
let sums = Tags.getSums(node);
|
|
261
|
+
|
|
262
|
+
if (!sums) return null;
|
|
263
|
+
|
|
264
|
+
let valueNameCount =
|
|
265
|
+
name != null
|
|
266
|
+
? Tags.getAtName(name, sums.references)
|
|
267
|
+
: Tags.getAtName(type, sums.specialTypes);
|
|
130
268
|
|
|
131
269
|
if (nameCount + valueNameCount < index) {
|
|
132
270
|
return null;
|
|
133
271
|
}
|
|
134
272
|
|
|
135
|
-
for (const value of
|
|
136
|
-
if (
|
|
273
|
+
for (const value of Tags.getValues(node)) {
|
|
274
|
+
if (!isArray(value)) {
|
|
137
275
|
idx++;
|
|
138
276
|
let tag = value;
|
|
139
|
-
if (tag.type ===
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
277
|
+
if (tag.type === PropertyWrapper) {
|
|
278
|
+
let { tags, property } = tag.value;
|
|
279
|
+
let { reference } = property;
|
|
280
|
+
if (tags[0].type === ReferenceTag) {
|
|
281
|
+
if (
|
|
282
|
+
(name != null && reference.name === name) ||
|
|
283
|
+
(type != null && reference.type === type)
|
|
284
|
+
) {
|
|
285
|
+
nameCount += 1;
|
|
286
|
+
if (nameCount > index) {
|
|
287
|
+
return idx + 1;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
143
290
|
}
|
|
144
291
|
}
|
|
145
292
|
} else {
|
|
146
|
-
let valueSums =
|
|
147
|
-
if (
|
|
293
|
+
let valueSums = Tags.getSums(value);
|
|
294
|
+
if (
|
|
295
|
+
nameCount +
|
|
296
|
+
(name != null
|
|
297
|
+
? Tags.getAtName(name, valueSums.references)
|
|
298
|
+
: Tags.getAtName(type, valueSums.specialTypes)) >
|
|
299
|
+
index
|
|
300
|
+
) {
|
|
148
301
|
node = value;
|
|
149
302
|
continue outer;
|
|
150
303
|
} else {
|
|
151
|
-
nameCount +=
|
|
152
|
-
|
|
304
|
+
nameCount +=
|
|
305
|
+
(name != null
|
|
306
|
+
? Tags.getAtName(name, valueSums.references)
|
|
307
|
+
: Tags.getAtName(type, valueSums.specialTypes)) ?? 0;
|
|
308
|
+
idx += Tags.getSize(value);
|
|
153
309
|
}
|
|
154
310
|
}
|
|
155
311
|
}
|
|
@@ -160,176 +316,161 @@ const __getPropertyChildrenIndex = (agAstNode, name, index) => {
|
|
|
160
316
|
return null;
|
|
161
317
|
};
|
|
162
318
|
|
|
163
|
-
const { hasOwn } = Object;
|
|
319
|
+
const { hasOwn, freeze } = Object;
|
|
164
320
|
const { isArray } = Array;
|
|
165
321
|
|
|
322
|
+
export const getOriginalFirstNode = (node, height = 1) => {
|
|
323
|
+
for (let child of Tags.traverse(node.tags)) {
|
|
324
|
+
if (child.type === PropertyWrapper) {
|
|
325
|
+
return child.value.property.node;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return null;
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
export const getFirstNode = (node) => {
|
|
332
|
+
return getFirstNodeProperty(node)?.node;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
export const getFirstNodeProperty = (node) => {
|
|
336
|
+
for (let child of Tags.traverse(node.tags)) {
|
|
337
|
+
if (child.type === PropertyWrapper) {
|
|
338
|
+
let ref = child.value.reference;
|
|
339
|
+
if (!ref.flags.expression) {
|
|
340
|
+
return child.value;
|
|
341
|
+
} else {
|
|
342
|
+
let tagsIndex = getPropertyTagsIndex(node, ref.type, ref.name, 0, -1);
|
|
343
|
+
return Tags.getAt(tagsIndex, node.tags + 2)?.value.node;
|
|
344
|
+
}
|
|
345
|
+
// is it shifted?
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return null;
|
|
349
|
+
};
|
|
350
|
+
|
|
166
351
|
export const referencesAreEqual = (a, b) => {
|
|
167
352
|
return (
|
|
168
353
|
a === b ||
|
|
169
|
-
(a.
|
|
170
|
-
a.
|
|
171
|
-
a.
|
|
172
|
-
a.
|
|
354
|
+
(a.type === b.type &&
|
|
355
|
+
a.name === b.name &&
|
|
356
|
+
a.isArray === b.isArray &&
|
|
357
|
+
a.flags.hasGap === b.flags.hasGap &&
|
|
358
|
+
a.flags.expression === b.flags.expression)
|
|
173
359
|
);
|
|
174
360
|
};
|
|
175
361
|
|
|
176
|
-
export const
|
|
177
|
-
|
|
362
|
+
export const isDefined = (obj, key) => hasOwn(obj, key) && obj[key] !== undefined;
|
|
363
|
+
export const isUndefined = (obj, key) => !hasOwn(obj, key) || obj[key] === undefined;
|
|
178
364
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
365
|
+
export function* relatedNodes(node) {
|
|
366
|
+
for (const child of Tags.traverse(node.tags)) {
|
|
367
|
+
if (child.type === PropertyWrapper) {
|
|
368
|
+
yield child.node;
|
|
182
369
|
}
|
|
183
370
|
}
|
|
371
|
+
}
|
|
184
372
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
} else {
|
|
188
|
-
return properties[name];
|
|
189
|
-
}
|
|
190
|
-
};
|
|
373
|
+
export const getProperty = (pathSegment, node) => {
|
|
374
|
+
if (!node) throw new Error();
|
|
191
375
|
|
|
192
|
-
|
|
193
|
-
const { name, index, isArray } = ref.value;
|
|
376
|
+
if (pathSegment == null) throw new Error('Bad path segment');
|
|
194
377
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
378
|
+
let { name, type, index, shiftIndex } =
|
|
379
|
+
typeof pathSegment === 'string' ? buildPathSegment(pathSegment) : pathSegment;
|
|
198
380
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
381
|
+
let propIndex = getPropertyTagsIndex(node, type, name, index, shiftIndex);
|
|
382
|
+
|
|
383
|
+
if (propIndex == null) return null;
|
|
384
|
+
|
|
385
|
+
return Tags.getAt(propIndex, node.tags)?.value.property;
|
|
204
386
|
};
|
|
205
387
|
|
|
206
|
-
export const
|
|
207
|
-
|
|
388
|
+
export const has = (path, node) => {
|
|
389
|
+
if (!isArray(path)) {
|
|
390
|
+
path = [path];
|
|
391
|
+
}
|
|
208
392
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
393
|
+
let pathArr = [...path];
|
|
394
|
+
let node_ = get(pathArr.slice(0, -1), node);
|
|
395
|
+
let seg = pathArr[pathArr.length - 1];
|
|
396
|
+
let name = typeof seg === 'string' ? seg : seg.name;
|
|
212
397
|
|
|
213
|
-
return
|
|
398
|
+
return (
|
|
399
|
+
!!getProperty(seg, node_) ||
|
|
400
|
+
getInitializerTagsIndex(node_, buildReferenceTag(null, name)) != null
|
|
401
|
+
);
|
|
214
402
|
};
|
|
215
403
|
|
|
216
|
-
export const
|
|
217
|
-
const { flags } = ref.value;
|
|
404
|
+
export const get = (path, node) => getOr(null, path, node);
|
|
218
405
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
406
|
+
export const getOr = (defaultValue, path, node) => {
|
|
407
|
+
if (!node) throw new Error();
|
|
408
|
+
|
|
409
|
+
if (path == null) throw new Error('Bad path');
|
|
222
410
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (value === node) {
|
|
226
|
-
throw new Error('cannot add a node to itself');
|
|
411
|
+
if (!isArray(path)) {
|
|
412
|
+
path = [path];
|
|
227
413
|
}
|
|
228
414
|
|
|
229
|
-
|
|
230
|
-
|
|
415
|
+
let root = getRoot(node);
|
|
416
|
+
let result = root || node;
|
|
231
417
|
|
|
232
|
-
|
|
233
|
-
|
|
418
|
+
let start = 0;
|
|
419
|
+
if (path[0]?.type === '.') {
|
|
420
|
+
if (!root) return null;
|
|
421
|
+
start = 1;
|
|
234
422
|
}
|
|
235
423
|
|
|
236
|
-
|
|
237
|
-
|
|
424
|
+
for (let i = start; i < path.length; i++) {
|
|
425
|
+
let nameOrSeg = path[i];
|
|
426
|
+
let isName = typeof nameOrSeg === 'string';
|
|
427
|
+
let property;
|
|
428
|
+
let index = path[i + 1];
|
|
429
|
+
|
|
430
|
+
if (typeof index === 'number') {
|
|
431
|
+
i++;
|
|
432
|
+
} else {
|
|
433
|
+
index = undefined;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (!isName && (!nameOrSeg || !hasOwn(nameOrSeg, 'shiftIndex'))) throw new Error('Bad path');
|
|
437
|
+
|
|
438
|
+
let seg = isName ? buildPathSegment(nameOrSeg, index) : nameOrSeg;
|
|
238
439
|
|
|
239
|
-
|
|
440
|
+
property = getProperty(seg, result);
|
|
240
441
|
|
|
241
|
-
|
|
442
|
+
if (!property) return defaultValue;
|
|
242
443
|
|
|
243
|
-
|
|
244
|
-
if (!referencesAreEqual(lastChild, reference)) throw new Error();
|
|
245
|
-
} else if (lastChild.type !== ShiftTag) {
|
|
246
|
-
if ([ShiftTag, ReferenceTag].includes(sumtree.getAt(-1, node.children).type)) throw new Error();
|
|
247
|
-
node.children = sumtree.push(node.children, shift > 0 ? buildShiftTag(shift) : reference);
|
|
444
|
+
result = property.node;
|
|
248
445
|
}
|
|
249
446
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
} else {
|
|
253
|
-
if (isArray) {
|
|
254
|
-
let isInitializer = Array.isArray(value);
|
|
255
|
-
let exists = !isInitializer && isDefined(properties, name);
|
|
256
|
-
|
|
257
|
-
let existed = exists;
|
|
258
|
-
if (!existed) {
|
|
259
|
-
if (isInitializer && value.length)
|
|
260
|
-
throw new Error('Array value only allowed for initialization');
|
|
261
|
-
|
|
262
|
-
properties[name] = [];
|
|
263
|
-
node.children = sumtree.push(node.children, buildInitializerTag(true));
|
|
264
|
-
exists = !isInitializer;
|
|
265
|
-
}
|
|
447
|
+
return result;
|
|
448
|
+
};
|
|
266
449
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if (sumtree.getAt(-1, node.children).type === ReferenceTag) throw new Error();
|
|
270
|
-
node.children = sumtree.push(node.children, reference);
|
|
271
|
-
}
|
|
450
|
+
export function* list(name, node) {
|
|
451
|
+
let count = countList(name, node);
|
|
272
452
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
453
|
+
for (let i = 0; i < count; i++) {
|
|
454
|
+
yield get(buildPathSegment(name, i, -1), node);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
276
457
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
node: btree.push(shiftedNodes, value),
|
|
280
|
-
};
|
|
281
|
-
} else {
|
|
282
|
-
newBinding = { reference, node: value };
|
|
283
|
-
}
|
|
458
|
+
export const countList = (name, node) => {
|
|
459
|
+
if (!node) throw new Error();
|
|
284
460
|
|
|
285
|
-
|
|
286
|
-
shift > 0
|
|
287
|
-
? btree.replaceAt(-1, properties[name], newBinding)
|
|
288
|
-
: btree.push(properties[name], newBinding);
|
|
461
|
+
if (name == null) throw new Error('Bad path');
|
|
289
462
|
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
} else {
|
|
293
|
-
if (value === undefined) {
|
|
294
|
-
if (isUndefined(properties, name)) {
|
|
295
|
-
let newBinding;
|
|
296
|
-
if (flags.expression) {
|
|
297
|
-
let shiftedNodes = shift > 0 ? btree.getAt(-1, properties[name])?.node : [];
|
|
298
|
-
|
|
299
|
-
newBinding = {
|
|
300
|
-
reference,
|
|
301
|
-
node: btree.push(shiftedNodes, undefined),
|
|
302
|
-
};
|
|
303
|
-
} else {
|
|
304
|
-
newBinding = { reference, node: undefined };
|
|
305
|
-
}
|
|
306
|
-
properties[name] = newBinding;
|
|
307
|
-
node.children = sumtree.push(node.children, buildInitializerTag());
|
|
308
|
-
}
|
|
309
|
-
} else {
|
|
310
|
-
if (flags.expression) {
|
|
311
|
-
if (shift == null) {
|
|
312
|
-
throw new Error();
|
|
313
|
-
}
|
|
463
|
+
let hasInitializer = getInitializerTagsIndex(node, buildReferenceTag(null, name)) != null;
|
|
314
464
|
|
|
315
|
-
|
|
316
|
-
properties[name] = { reference, node: btree.push(shiftedNodes, value) };
|
|
317
|
-
} else {
|
|
318
|
-
if (shift != null) throw new Error();
|
|
319
|
-
if (hasOwn(properties, name) && properties[name].node !== undefined) {
|
|
320
|
-
throw new Error();
|
|
321
|
-
}
|
|
322
|
-
properties[name] = { reference, node: value };
|
|
323
|
-
}
|
|
324
|
-
node.children = sumtree.push(node.children, buildGapTag(value));
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
465
|
+
return Tags.getAtName(name, Tags.getSums(node.tags).references) - (hasInitializer ? 1 : 0);
|
|
328
466
|
};
|
|
329
467
|
|
|
330
468
|
export function* allTagPathsFor(range, options = {}) {
|
|
331
469
|
if (range == null) return;
|
|
332
470
|
|
|
471
|
+
if (range[0] && !(range[0] instanceof TagPath)) throw new Error();
|
|
472
|
+
if (range[1] && !(range[1] instanceof TagPath)) throw new Error();
|
|
473
|
+
|
|
333
474
|
const { unshift = false } = options;
|
|
334
475
|
let startPath = range[0];
|
|
335
476
|
let endPath = range[1];
|
|
@@ -337,7 +478,7 @@ export function* allTagPathsFor(range, options = {}) {
|
|
|
337
478
|
|
|
338
479
|
while (path) {
|
|
339
480
|
if (path.inner && path.previousSibling.tag.type === ReferenceTag) {
|
|
340
|
-
path = new TagPath(path.
|
|
481
|
+
path = new TagPath(path.inner, 0);
|
|
341
482
|
}
|
|
342
483
|
|
|
343
484
|
if (path.path.depth < startPath.path.depth) {
|
|
@@ -346,21 +487,17 @@ export function* allTagPathsFor(range, options = {}) {
|
|
|
346
487
|
|
|
347
488
|
yield path;
|
|
348
489
|
|
|
349
|
-
if (
|
|
350
|
-
endPath &&
|
|
351
|
-
path.childrenIndex === endPath.childrenIndex &&
|
|
352
|
-
path.path.node === endPath.path.node
|
|
353
|
-
) {
|
|
490
|
+
if (endPath && path.tagsIndex === endPath.tagsIndex && path.path.node === endPath.path.node) {
|
|
354
491
|
return;
|
|
355
492
|
}
|
|
356
493
|
|
|
357
|
-
let gapPath = path.path.parent && TagPath.from(path.path.parent, path.path.
|
|
494
|
+
let gapPath = path.path.parent && TagPath.from(path.path.parent, path.path.parentIndex, 1);
|
|
358
495
|
|
|
359
496
|
if (
|
|
360
497
|
endPath &&
|
|
361
498
|
path.tag.type === CloseNodeTag &&
|
|
362
499
|
gapPath &&
|
|
363
|
-
gapPath.
|
|
500
|
+
gapPath.tagsIndex === endPath.tagsIndex &&
|
|
364
501
|
gapPath.path.node === endPath.path.node
|
|
365
502
|
) {
|
|
366
503
|
return;
|
|
@@ -370,34 +507,34 @@ export function* allTagPathsFor(range, options = {}) {
|
|
|
370
507
|
}
|
|
371
508
|
|
|
372
509
|
export function* allTagsFor(range, options = {}) {
|
|
373
|
-
for (
|
|
510
|
+
for (let path of allTagPathsFor(range, options)) {
|
|
374
511
|
yield path.tag;
|
|
375
512
|
}
|
|
376
513
|
}
|
|
377
514
|
|
|
378
515
|
export const buildFullRange = (node) => {
|
|
379
|
-
|
|
516
|
+
let sum = Tags.getSize(node.tags);
|
|
380
517
|
return sum ? [0, sum - 1] : null;
|
|
381
518
|
};
|
|
382
519
|
|
|
383
520
|
export function* ownTagPathsFor(range) {
|
|
384
521
|
if (!isArray(range)) throw new Error();
|
|
385
522
|
|
|
386
|
-
|
|
387
|
-
|
|
523
|
+
let startPath = range[0];
|
|
524
|
+
let endPath = range[1];
|
|
388
525
|
|
|
389
|
-
if (startPath.
|
|
526
|
+
if (startPath.parent.node !== endPath.parent.node) throw new Error();
|
|
390
527
|
|
|
391
|
-
|
|
528
|
+
let { tags } = startPath.parent.node;
|
|
392
529
|
|
|
393
|
-
for (let i = startPath.
|
|
394
|
-
yield
|
|
530
|
+
for (let i = startPath.tagsIndex; i < endPath.tagsIndex; i++) {
|
|
531
|
+
yield tags[i];
|
|
395
532
|
}
|
|
396
533
|
}
|
|
397
534
|
|
|
398
535
|
const findRight = (arr, predicate) => {
|
|
399
536
|
for (let i = arr.length - 1; i >= 0; i--) {
|
|
400
|
-
|
|
537
|
+
let value = arr[i];
|
|
401
538
|
if (predicate(value)) return value;
|
|
402
539
|
}
|
|
403
540
|
return null;
|
|
@@ -420,7 +557,7 @@ const buildSkips = (frame) => {
|
|
|
420
557
|
skipsByFrame.set(frame, skips);
|
|
421
558
|
}
|
|
422
559
|
|
|
423
|
-
skips[skipIdx] = frame.
|
|
560
|
+
skips[skipIdx] = frame.atDepth(frame.depth - skipAmount);
|
|
424
561
|
|
|
425
562
|
skipIdx++;
|
|
426
563
|
skipAmount = skipAmounts[skipIdx];
|
|
@@ -441,41 +578,79 @@ const skipToDepth = (depth, frame) => {
|
|
|
441
578
|
return parent;
|
|
442
579
|
};
|
|
443
580
|
|
|
581
|
+
export let pathForTagPath = (tagPath) => {
|
|
582
|
+
let refTagPath = tagPath;
|
|
583
|
+
let isShift = tagPath.tag.type === ShiftTag;
|
|
584
|
+
|
|
585
|
+
if (isShift) {
|
|
586
|
+
refTagPath = tagPath.siblingAt(tagPath.tagsIndex - tagPath.tag.value.index);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
let { type, name } = refTagPath.tag.value;
|
|
590
|
+
|
|
591
|
+
if (refTagPath.tag.type !== ReferenceTag) throw new Error();
|
|
592
|
+
|
|
593
|
+
let index = getChildPropertyIndex(tagPath.node, refTagPath.tagsIndex);
|
|
594
|
+
let shiftIndex = isShift ? (tagPath.tag.value.index ?? 0) + 1 : null;
|
|
595
|
+
|
|
596
|
+
return [{ type, name, index, shiftIndex }];
|
|
597
|
+
};
|
|
598
|
+
|
|
444
599
|
export const Path = class AgastPath extends WeakStackFrame {
|
|
445
600
|
static from(node) {
|
|
446
|
-
|
|
601
|
+
let node_ = isPlainObject(node) ? node : node.node;
|
|
602
|
+
return node_ && this.create(node_);
|
|
447
603
|
}
|
|
448
604
|
|
|
449
|
-
constructor(parent, node,
|
|
605
|
+
constructor(parent, node, parentIndex = null) {
|
|
450
606
|
super(parent);
|
|
451
607
|
|
|
452
|
-
if (!(hasOwn(node, 'type') && hasOwn(node, '
|
|
608
|
+
if (!node || !(hasOwn(node, 'type') && hasOwn(node, 'tags'))) throw new Error();
|
|
453
609
|
|
|
454
|
-
if (parent &&
|
|
610
|
+
if (parent && parentIndex == null) throw new Error();
|
|
455
611
|
if (!node) throw new Error();
|
|
456
612
|
if (isArray(node)) throw new Error();
|
|
457
613
|
|
|
458
614
|
this.node = node;
|
|
459
|
-
this.
|
|
615
|
+
this.parentIndex = parentIndex; // in the parent
|
|
460
616
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
) {
|
|
617
|
+
let parentTag = parent && Tags.getAt(parentIndex, parent.node.tags);
|
|
618
|
+
|
|
619
|
+
if (parentTag && parentTag.type !== PropertyWrapper) {
|
|
465
620
|
throw new Error();
|
|
466
621
|
}
|
|
467
622
|
|
|
468
|
-
|
|
623
|
+
parentIndex != null && parentTag?.value.tags[0];
|
|
624
|
+
|
|
625
|
+
if (
|
|
626
|
+
parent &&
|
|
627
|
+
(!this.referenceTag || ![ReferenceTag, ShiftTag].includes(this.referenceTag.type))
|
|
628
|
+
) {
|
|
469
629
|
throw new Error();
|
|
470
630
|
}
|
|
471
631
|
|
|
632
|
+
// if (
|
|
633
|
+
// parent &&
|
|
634
|
+
// (['#', '@'].includes(this.referenceTag.value.type)
|
|
635
|
+
// ? parent.tagPathAt(parentIndex, 1).tag.value
|
|
636
|
+
// : get(pathForTagPath(parent.tagPathAt(parentIndex)), parent.node)) !== node
|
|
637
|
+
// ) {
|
|
638
|
+
// throw new Error('Path not reachable');
|
|
639
|
+
// }
|
|
640
|
+
|
|
472
641
|
if (!Number.isFinite(this.depth)) throw new Error();
|
|
473
642
|
|
|
474
643
|
buildSkips(this);
|
|
644
|
+
|
|
645
|
+
freeze(this);
|
|
475
646
|
}
|
|
476
647
|
|
|
477
648
|
get openTagPath() {
|
|
478
|
-
|
|
649
|
+
let tagPath = TagPath.from(this, 0);
|
|
650
|
+
if (tagPath.tag.type === DoctypeTag) {
|
|
651
|
+
tagPath = tagPath.nextSibling;
|
|
652
|
+
}
|
|
653
|
+
return tagPath;
|
|
479
654
|
}
|
|
480
655
|
|
|
481
656
|
get openTag() {
|
|
@@ -483,271 +658,421 @@ export const Path = class AgastPath extends WeakStackFrame {
|
|
|
483
658
|
}
|
|
484
659
|
|
|
485
660
|
get closeTagPath() {
|
|
486
|
-
|
|
661
|
+
let tagPath = TagPath.from(this, -1);
|
|
662
|
+
if (tagPath.tag.type !== CloseNodeTag) return null;
|
|
663
|
+
return tagPath;
|
|
487
664
|
}
|
|
488
665
|
|
|
489
666
|
get closeTag() {
|
|
490
667
|
return this.closeTagPath.tag;
|
|
491
668
|
}
|
|
492
669
|
|
|
670
|
+
tagPathAt(idx, offset) {
|
|
671
|
+
return TagPath.from(this, idx, offset);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
get binding() {
|
|
675
|
+
return this.bindingTag?.value ?? null;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
get bindingTag() {
|
|
679
|
+
return this.bindingTagPath?.tag ?? null;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
get bindingTagPath() {
|
|
683
|
+
return (this.parent?.node ?? null) && new TagPath(this.parent, this.parentIndex, 1);
|
|
684
|
+
}
|
|
685
|
+
|
|
493
686
|
get reference() {
|
|
494
|
-
return this.
|
|
687
|
+
return this.referenceTag?.value ?? null;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
get referenceTag() {
|
|
691
|
+
return this.referenceTagPath?.tag ?? null;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
get referenceTagPath() {
|
|
695
|
+
if (!this.parent?.node) {
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
698
|
+
let path = new TagPath(this.parent, this.parentIndex, 0);
|
|
699
|
+
if (path.tag.type === ShiftTag) {
|
|
700
|
+
path = new TagPath(this.parent, this.parentIndex - path.tag.value.index, 0);
|
|
701
|
+
}
|
|
702
|
+
return path;
|
|
495
703
|
}
|
|
496
704
|
|
|
497
|
-
get
|
|
498
|
-
|
|
705
|
+
get parentPropertyPath() {
|
|
706
|
+
if (!this.parent?.node) {
|
|
707
|
+
return null;
|
|
708
|
+
}
|
|
709
|
+
let path = new TagPath(this.parent, this.parentIndex);
|
|
710
|
+
if (path.tag.type === ShiftTag) {
|
|
711
|
+
path = new TagPath(this.parent, this.parentIndex - path.tag.value.index);
|
|
712
|
+
}
|
|
713
|
+
return path;
|
|
499
714
|
}
|
|
500
715
|
|
|
501
|
-
get
|
|
502
|
-
return this.
|
|
716
|
+
get parentProperty() {
|
|
717
|
+
return this.parentPropertyPath?.tag ?? null;
|
|
503
718
|
}
|
|
504
719
|
|
|
505
|
-
get
|
|
506
|
-
|
|
720
|
+
get(path) {
|
|
721
|
+
let path_ = path;
|
|
722
|
+
if (typeof path_ === 'string') {
|
|
723
|
+
path_ = [path_];
|
|
724
|
+
}
|
|
725
|
+
if (!isArray(path_)) throw new Error();
|
|
726
|
+
|
|
727
|
+
let pathInst = this;
|
|
728
|
+
|
|
729
|
+
if (!pathInst.node.type && pathInst.node.flags.cover) {
|
|
730
|
+
if (pathInst.depth) throw new Error();
|
|
731
|
+
pathInst = pathInst.push(
|
|
732
|
+
getRoot(pathInst.node),
|
|
733
|
+
getPropertyTagsIndex(pathInst.node, '.', null, 0),
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
for (let i = 0; i < path_.length; i++) {
|
|
738
|
+
let nameOrSeg = path_[i];
|
|
739
|
+
|
|
740
|
+
let seg = nameOrSeg;
|
|
741
|
+
if (isString(nameOrSeg)) {
|
|
742
|
+
let index = path_[i + 1];
|
|
743
|
+
if (typeof index === 'number') {
|
|
744
|
+
i++;
|
|
745
|
+
} else {
|
|
746
|
+
index = undefined;
|
|
747
|
+
}
|
|
748
|
+
seg = buildPathSegment(nameOrSeg, index);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
let tagsIndex = getPropertyTagsIndex(
|
|
752
|
+
pathInst.node,
|
|
753
|
+
seg.type,
|
|
754
|
+
seg.name,
|
|
755
|
+
seg.index,
|
|
756
|
+
seg.shiftIndex,
|
|
757
|
+
);
|
|
758
|
+
|
|
759
|
+
let { property } = Tags.getAt(tagsIndex, pathInst.node.tags).value;
|
|
760
|
+
|
|
761
|
+
if (!property) return null;
|
|
762
|
+
|
|
763
|
+
let { node } = property;
|
|
764
|
+
|
|
765
|
+
pathInst = pathInst.push(node, tagsIndex);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
return pathInst;
|
|
507
769
|
}
|
|
508
770
|
|
|
509
|
-
|
|
510
|
-
return this.
|
|
771
|
+
replaceWith(node, binding = buildBinding()) {
|
|
772
|
+
return this.replaceAt([], node, binding);
|
|
511
773
|
}
|
|
512
774
|
|
|
513
|
-
|
|
514
|
-
|
|
775
|
+
replaceAt(path, node, binding = buildBinding()) {
|
|
776
|
+
throw new Error('not working yet');
|
|
777
|
+
|
|
778
|
+
let built;
|
|
779
|
+
let path_ = path;
|
|
780
|
+
if (typeof path_ === 'string') {
|
|
781
|
+
path_ = [path_];
|
|
782
|
+
}
|
|
783
|
+
if (!isArray(path_)) throw new Error();
|
|
784
|
+
|
|
785
|
+
let pathInst = this;
|
|
786
|
+
|
|
787
|
+
if (!pathInst.node.type && pathInst.node.flags.cover) {
|
|
788
|
+
if (pathInst.depth) throw new Error();
|
|
789
|
+
pathInst = pathInst.push(
|
|
790
|
+
getRoot(pathInst.node),
|
|
791
|
+
getPropertyTagsIndex(pathInst.node, '.', null, 0),
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
for (let i = 0; i < path_.length; i++) {
|
|
796
|
+
let nameOrSeg = path_[i];
|
|
797
|
+
|
|
798
|
+
built = { ...pathInst.node };
|
|
799
|
+
|
|
800
|
+
let seg = nameOrSeg;
|
|
801
|
+
if (isString(nameOrSeg)) {
|
|
802
|
+
let index = path_[i + 1];
|
|
803
|
+
if (typeof index === 'number') {
|
|
804
|
+
i++;
|
|
805
|
+
} else {
|
|
806
|
+
index = undefined;
|
|
807
|
+
}
|
|
808
|
+
seg = buildPathSegment(nameOrSeg, index);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
let tagsIndex = getPropertyTagsIndex(
|
|
812
|
+
pathInst.node,
|
|
813
|
+
seg.type,
|
|
814
|
+
seg.name,
|
|
815
|
+
seg.index,
|
|
816
|
+
seg.shiftIndex,
|
|
817
|
+
);
|
|
818
|
+
|
|
819
|
+
let tagPath = TagPath.from(pathInst, tagsIndex);
|
|
820
|
+
|
|
821
|
+
let {
|
|
822
|
+
property,
|
|
823
|
+
tags: { 0: refTag },
|
|
824
|
+
} = tagPath.tag.value;
|
|
825
|
+
|
|
826
|
+
if (refTag.type === ShiftTag) {
|
|
827
|
+
let { index } = refTag.value;
|
|
828
|
+
|
|
829
|
+
for (let i = 0; i < index - 1; i++) {
|
|
830
|
+
// update bounds!
|
|
831
|
+
}
|
|
832
|
+
tagsIndex -= index;
|
|
833
|
+
pathInst = pathInst.replace(built, tagsIndex);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
if (!property) return null;
|
|
837
|
+
|
|
838
|
+
let { node } = property;
|
|
839
|
+
|
|
840
|
+
pathInst = pathInst.push(node, tagsIndex);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
let node_ = isPlainObject(node) ? node : node.node;
|
|
844
|
+
|
|
845
|
+
if (!node_) throw new Error();
|
|
846
|
+
|
|
847
|
+
path = pathInst.parent;
|
|
848
|
+
let replacementPath = [];
|
|
849
|
+
|
|
850
|
+
let targetReference = pathInst.reference;
|
|
851
|
+
let targetBinding = binding;
|
|
852
|
+
let targetParentIndex = pathInst.parentIndex;
|
|
853
|
+
|
|
854
|
+
while (path) {
|
|
855
|
+
let value = built;
|
|
856
|
+
built = { ...path.node };
|
|
857
|
+
|
|
858
|
+
let { tags } = Tags.getAt(targetParentIndex, path.node.tags).value;
|
|
859
|
+
let property = buildProperty(targetReference, targetBinding, value);
|
|
860
|
+
|
|
861
|
+
let tags_ = [tags[0], buildChild(BindingTag, targetBinding), buildChild(Property, property)];
|
|
862
|
+
|
|
863
|
+
built.tags = Tags.replaceAt(
|
|
864
|
+
targetParentIndex,
|
|
865
|
+
built.tags,
|
|
866
|
+
buildChild(PropertyWrapper, buildPropertyWrapper(tags_, property)),
|
|
867
|
+
);
|
|
515
868
|
|
|
516
|
-
|
|
869
|
+
finalizeNode(built);
|
|
517
870
|
|
|
518
|
-
|
|
871
|
+
if (targetReference.name) {
|
|
872
|
+
replacementPath.push(
|
|
873
|
+
buildPathSegment(
|
|
874
|
+
targetReference.name,
|
|
875
|
+
getChildPropertyIndex(path.node, targetParentIndex),
|
|
876
|
+
),
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
targetReference = path.reference;
|
|
881
|
+
targetBinding = path.binding;
|
|
882
|
+
targetParentIndex = path.parentIndex;
|
|
883
|
+
path = path.parent;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
replacementPath.reverse();
|
|
887
|
+
|
|
888
|
+
return Path.from(built).get(replacementPath).atDepth(this.depth);
|
|
519
889
|
}
|
|
520
890
|
|
|
521
|
-
|
|
891
|
+
atDepth(depth) {
|
|
522
892
|
return skipToDepth(depth, this);
|
|
523
893
|
}
|
|
524
894
|
};
|
|
525
895
|
|
|
526
896
|
export const tagPathsAreEqual = (a, b) => {
|
|
527
897
|
if (a == null || b == null) return b == a;
|
|
528
|
-
return a.path.node === b.path.node && a.
|
|
898
|
+
return a.path.node === b.path.node && a.tagsIndex === b.tagsIndex;
|
|
529
899
|
};
|
|
530
900
|
|
|
531
901
|
export class TagPath {
|
|
532
|
-
constructor(path,
|
|
533
|
-
if (path == null ||
|
|
902
|
+
constructor(path, tagsIndex, wrapperIndex) {
|
|
903
|
+
if (path == null || tagsIndex == null) throw new Error();
|
|
904
|
+
|
|
905
|
+
let tag = Tags.getAt(tagsIndex, path.node.tags);
|
|
906
|
+
|
|
907
|
+
if (tag == null) throw new Error();
|
|
908
|
+
|
|
909
|
+
if (tag.type === PropertyWrapper && wrapperIndex != null) {
|
|
910
|
+
tag = tag.value.tags[wrapperIndex];
|
|
911
|
+
}
|
|
534
912
|
|
|
535
913
|
this.path = path;
|
|
536
|
-
this.
|
|
914
|
+
this.node = path.node;
|
|
915
|
+
this.tag = tag;
|
|
916
|
+
this.tagsIndex = tagsIndex;
|
|
917
|
+
this.wrapperIndex = wrapperIndex;
|
|
537
918
|
|
|
538
|
-
|
|
919
|
+
freeze(this);
|
|
539
920
|
}
|
|
540
921
|
|
|
541
|
-
static from(path,
|
|
542
|
-
let size =
|
|
543
|
-
let index =
|
|
922
|
+
static from(path, tagsIndex, wrapperIndex) {
|
|
923
|
+
let size = Tags.getSize(path.node.tags);
|
|
924
|
+
let index = tagsIndex < 0 ? size + tagsIndex : tagsIndex;
|
|
544
925
|
|
|
545
|
-
|
|
546
|
-
}
|
|
926
|
+
let tag = Tags.getAt(index, path.node.tags);
|
|
547
927
|
|
|
548
|
-
|
|
549
|
-
return TagPath.from(Path.from(node), childrenIndex);
|
|
550
|
-
}
|
|
928
|
+
if (!tag) return null;
|
|
551
929
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
930
|
+
let offset =
|
|
931
|
+
wrapperIndex == null || tag.type !== PropertyWrapper
|
|
932
|
+
? null
|
|
933
|
+
: wrapperIndex < 0
|
|
934
|
+
? tag.value.tags.length + wrapperIndex
|
|
935
|
+
: wrapperIndex;
|
|
555
936
|
|
|
556
|
-
|
|
557
|
-
return this.path.node;
|
|
937
|
+
return index >= 0 && index < size ? new TagPath(path, index, offset) : null;
|
|
558
938
|
}
|
|
559
939
|
|
|
560
|
-
|
|
561
|
-
return
|
|
940
|
+
static fromNode(node, tagsIndex, wrapperIndex) {
|
|
941
|
+
return TagPath.from(Path.from(node), tagsIndex, wrapperIndex);
|
|
562
942
|
}
|
|
563
943
|
|
|
564
|
-
|
|
565
|
-
return
|
|
944
|
+
get child() {
|
|
945
|
+
return this.tag;
|
|
566
946
|
}
|
|
567
947
|
|
|
568
948
|
siblingAt(index) {
|
|
569
|
-
return this.
|
|
949
|
+
return TagPath.from(this.path, index);
|
|
570
950
|
}
|
|
571
951
|
|
|
572
952
|
get nextSibling() {
|
|
573
|
-
const { path,
|
|
953
|
+
const { path, tagsIndex, wrapperIndex } = this;
|
|
574
954
|
|
|
575
|
-
|
|
576
|
-
childrenIndex + 1 >= sumtree.getSize(path.node.children)
|
|
577
|
-
? null
|
|
578
|
-
: sumtree.getAt(childrenIndex + 1, path.node.children);
|
|
955
|
+
let propPath = new TagPath(path, tagsIndex);
|
|
579
956
|
|
|
580
|
-
|
|
957
|
+
if (wrapperIndex != null && wrapperIndex + 1 < Tags.getSize(propPath.tag.value.tags)) {
|
|
958
|
+
return new TagPath(path, tagsIndex, wrapperIndex + 1);
|
|
959
|
+
} else if (tagsIndex + 1 < Tags.getSize(path.node.tags)) {
|
|
960
|
+
return new TagPath(path, tagsIndex + 1, 0);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
return TagPath.from(path, tagsIndex + 1, 0);
|
|
581
964
|
}
|
|
582
965
|
|
|
583
966
|
get next() {
|
|
584
|
-
let { path,
|
|
967
|
+
let { path, tagsIndex, wrapperIndex } = this;
|
|
585
968
|
|
|
586
969
|
let leaving = false;
|
|
587
970
|
|
|
588
971
|
for (;;) {
|
|
589
|
-
let
|
|
590
|
-
let tag =
|
|
591
|
-
let
|
|
972
|
+
let lastRef = Tags.getAt(tagsIndex, path.node.tags, 0);
|
|
973
|
+
let tag = Tags.getAt(tagsIndex, path.node.tags);
|
|
974
|
+
let wrapperTag = tag;
|
|
975
|
+
let isInitialTag =
|
|
976
|
+
path.node === this.path.node &&
|
|
977
|
+
tagsIndex === this.tagsIndex &&
|
|
978
|
+
wrapperIndex === this.wrapperIndex;
|
|
592
979
|
let wasLeaving = leaving;
|
|
593
980
|
leaving = false;
|
|
594
981
|
|
|
595
982
|
if (!tag) return null;
|
|
596
983
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
) {
|
|
603
|
-
return new TagPath(path, childrenIndex);
|
|
984
|
+
wrapperIndex =
|
|
985
|
+
tag.type === PropertyWrapper ? (wrapperIndex == null ? 0 : wrapperIndex) : null;
|
|
986
|
+
|
|
987
|
+
if (wrapperIndex != null) {
|
|
988
|
+
wrapperTag = tag.value.tags[wrapperIndex];
|
|
604
989
|
}
|
|
605
990
|
|
|
606
|
-
//
|
|
607
|
-
if (
|
|
608
|
-
|
|
609
|
-
childrenIndex = 0;
|
|
610
|
-
continue;
|
|
991
|
+
// done
|
|
992
|
+
if (!isInitialTag && wrapperTag.type !== Property) {
|
|
993
|
+
return new TagPath(path, tagsIndex, wrapperIndex);
|
|
611
994
|
}
|
|
612
995
|
|
|
613
996
|
// in
|
|
614
|
-
if (
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
continue;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
if (prevTag.type === ReferenceTag) {
|
|
634
|
-
refTag = prevTag;
|
|
635
|
-
|
|
636
|
-
if (nextTag && nextTag.type === ShiftTag) {
|
|
637
|
-
const shifts = getProperties(refTag, path.node.properties).node;
|
|
638
|
-
|
|
639
|
-
if (!Array.isArray(shifts)) throw new Error();
|
|
640
|
-
|
|
641
|
-
const { name, isArray, flags } = refTag.value;
|
|
642
|
-
let resolvedReference = refTag;
|
|
643
|
-
if (isArray) {
|
|
644
|
-
let index = getChildPropertyIndex(path.node, refIndex);
|
|
645
|
-
resolvedReference =
|
|
646
|
-
index === -1 ? null : buildReferenceTag(name, index != null, flags, index);
|
|
647
|
-
}
|
|
997
|
+
if (wrapperTag.type === Property && !wasLeaving) {
|
|
998
|
+
if (tag.value.tags[1]?.type === InitializerTag || !tag.value.property.node) {
|
|
999
|
+
} else {
|
|
1000
|
+
// jump to gap tag?
|
|
1001
|
+
let tag1;
|
|
1002
|
+
if (
|
|
1003
|
+
path.parent &&
|
|
1004
|
+
tag.value.property.reference.flags.expression &&
|
|
1005
|
+
(tagsIndex === 1 ||
|
|
1006
|
+
(tagsIndex === 2 &&
|
|
1007
|
+
(tag1 = Tags.getAt(1, path.node.tags)).type === PropertyWrapper &&
|
|
1008
|
+
tag1.value.tags[1].type === InitializerTag)) &&
|
|
1009
|
+
Tags.getAt(path.parentIndex, path.parent.node.tags, 0)?.type === ShiftTag
|
|
1010
|
+
) {
|
|
1011
|
+
let shiftStack = tag.value.property.node.bounds[0];
|
|
648
1012
|
|
|
649
|
-
|
|
650
|
-
childrenIndex = 0;
|
|
1013
|
+
let gapNode = BTree.getAt(-1, shiftStack).node;
|
|
651
1014
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
}
|
|
1015
|
+
path = new Path(path, gapNode, tagsIndex);
|
|
1016
|
+
tagsIndex = 0;
|
|
655
1017
|
continue;
|
|
656
|
-
} else {
|
|
657
|
-
if (
|
|
658
|
-
!['#', '@'].includes(refTag.value.name) &&
|
|
659
|
-
(!refTag.value.isArray || getChildPropertyIndex(path.node, refIndex) != null)
|
|
660
|
-
) {
|
|
661
|
-
const { name, isArray, flags } = refTag.value;
|
|
662
|
-
let resolvedReference = refTag;
|
|
663
|
-
if (isArray) {
|
|
664
|
-
let index = getChildPropertyIndex(path.node, refIndex);
|
|
665
|
-
resolvedReference =
|
|
666
|
-
index === -1 ? null : buildReferenceTag(name, index != null, flags, index);
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
if (resolvedReference) {
|
|
670
|
-
path = path.get(resolvedReference);
|
|
671
|
-
childrenIndex = 0;
|
|
672
|
-
|
|
673
|
-
if (!path) {
|
|
674
|
-
return null;
|
|
675
|
-
}
|
|
676
|
-
continue;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
} else if (prevTag.type === ShiftTag) {
|
|
681
|
-
let refIndex = childrenIndex - prevTag.value.index * 2 - 1;
|
|
682
|
-
let refTag = sumtree.getAt(refIndex, path.node.children);
|
|
683
|
-
|
|
684
|
-
const { name, isArray, flags } = refTag.value;
|
|
685
|
-
let resolvedReference = refTag;
|
|
686
|
-
if (isArray) {
|
|
687
|
-
let index = getChildPropertyIndex(path.node, refIndex);
|
|
688
|
-
resolvedReference =
|
|
689
|
-
index === -1 ? null : buildReferenceTag(name, index != null, flags, index);
|
|
690
1018
|
}
|
|
691
1019
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
// caused us to return to a point before we left
|
|
696
|
-
path.referenceIndex = childrenIndex;
|
|
697
|
-
childrenIndex = sumtree.getAt(2, path.node.children).type === InitializerTag ? 5 : 3;
|
|
698
|
-
continue;
|
|
699
|
-
}
|
|
700
|
-
} else {
|
|
701
|
-
throw new Error();
|
|
1020
|
+
path = new Path(path, tag.value.property.node, tagsIndex);
|
|
1021
|
+
tagsIndex = 0;
|
|
1022
|
+
continue;
|
|
702
1023
|
}
|
|
703
1024
|
}
|
|
704
1025
|
|
|
1026
|
+
tag;
|
|
705
1027
|
// shift
|
|
706
|
-
if (
|
|
707
|
-
let refIndex =
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
if (isArray) {
|
|
713
|
-
let index = getChildPropertyIndex(path.node, refIndex);
|
|
714
|
-
resolvedReference =
|
|
715
|
-
index === -1 ? null : buildReferenceTag(name, index != null, flags, index);
|
|
716
|
-
} else {
|
|
717
|
-
resolvedReference = refTag;
|
|
718
|
-
}
|
|
1028
|
+
if (wrapperTag.type === BindingTag && lastRef.type === ShiftTag) {
|
|
1029
|
+
let refIndex = tagsIndex - lastRef.value.index;
|
|
1030
|
+
if (refIndex < 0) throw new Error();
|
|
1031
|
+
let refTag = Tags.getAt(refIndex, path.node.tags, 0);
|
|
1032
|
+
|
|
1033
|
+
if (refTag.type !== ReferenceTag) throw new Error();
|
|
719
1034
|
|
|
720
|
-
if (
|
|
721
|
-
path = path
|
|
1035
|
+
if (Tags.getAt(refIndex, path.node.tags, 1).type !== InitializerTag) {
|
|
1036
|
+
path = new Path(path, tag.value.property.node, tagsIndex);
|
|
722
1037
|
|
|
723
1038
|
if (!path) return null;
|
|
724
1039
|
|
|
725
|
-
|
|
1040
|
+
tagsIndex = 0;
|
|
726
1041
|
continue;
|
|
727
1042
|
}
|
|
728
1043
|
}
|
|
729
1044
|
|
|
730
1045
|
// over
|
|
731
|
-
if (
|
|
732
|
-
|
|
1046
|
+
if (tag.type === PropertyWrapper && wrapperIndex + 1 < tag.value.tags.length) {
|
|
1047
|
+
wrapperIndex++;
|
|
1048
|
+
continue;
|
|
1049
|
+
} else if (path.node && tagsIndex + 1 < Tags.getSize(path.node.tags)) {
|
|
1050
|
+
tagsIndex++;
|
|
1051
|
+
wrapperIndex = 0;
|
|
733
1052
|
continue;
|
|
734
1053
|
}
|
|
735
1054
|
|
|
736
1055
|
// out
|
|
737
|
-
if (path.
|
|
1056
|
+
if (path.parentIndex != null && path.parent) {
|
|
738
1057
|
do {
|
|
739
|
-
if (
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
1058
|
+
if (
|
|
1059
|
+
path.parent &&
|
|
1060
|
+
Tags.getAt(path.parentIndex, path.parent.node.tags, 0)?.type === ShiftTag
|
|
1061
|
+
) {
|
|
1062
|
+
tagsIndex =
|
|
1063
|
+
Tags.getSize(path.parent.node.tags) > path.parentIndex + 1
|
|
1064
|
+
? path.parentIndex + 1
|
|
743
1065
|
: null;
|
|
744
1066
|
} else {
|
|
745
|
-
|
|
1067
|
+
tagsIndex = path.parentIndex + 1;
|
|
746
1068
|
}
|
|
747
1069
|
|
|
1070
|
+
wrapperIndex = 0;
|
|
748
1071
|
path = path.parent;
|
|
749
1072
|
leaving = true;
|
|
750
|
-
|
|
1073
|
+
|
|
1074
|
+
if (!path) return null;
|
|
1075
|
+
} while (tagsIndex == null);
|
|
751
1076
|
|
|
752
1077
|
leaving = true;
|
|
753
1078
|
continue;
|
|
@@ -758,87 +1083,77 @@ export class TagPath {
|
|
|
758
1083
|
}
|
|
759
1084
|
|
|
760
1085
|
get nextUnshifted() {
|
|
761
|
-
let { path,
|
|
1086
|
+
let { path, tagsIndex, wrapperIndex } = this;
|
|
762
1087
|
|
|
763
1088
|
let leaving = false;
|
|
764
1089
|
|
|
765
1090
|
for (;;) {
|
|
766
|
-
let tag =
|
|
767
|
-
let
|
|
1091
|
+
let tag = Tags.getAt(tagsIndex, path.node.tags);
|
|
1092
|
+
let wrapperTag = tag;
|
|
1093
|
+
let isInitialTag =
|
|
1094
|
+
path.node === this.path.node &&
|
|
1095
|
+
tagsIndex === this.tagsIndex &&
|
|
1096
|
+
wrapperIndex === this.wrapperIndex;
|
|
768
1097
|
let wasLeaving = leaving;
|
|
769
1098
|
leaving = false;
|
|
770
1099
|
|
|
771
1100
|
if (!tag) return null;
|
|
772
1101
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
!isInitialTag &&
|
|
776
|
-
tag.type !== EmbeddedNode &&
|
|
777
|
-
tag.type !== ShiftTag &&
|
|
778
|
-
(tag.type !== GapTag || isGapNode(path.node))
|
|
779
|
-
) {
|
|
780
|
-
return new TagPath(path, childrenIndex);
|
|
781
|
-
}
|
|
1102
|
+
wrapperIndex =
|
|
1103
|
+
tag.type === PropertyWrapper ? (wrapperIndex == null ? 0 : wrapperIndex) : null;
|
|
782
1104
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
path = path.push(tag.value, childrenIndex - 1);
|
|
786
|
-
childrenIndex = 0;
|
|
787
|
-
continue;
|
|
1105
|
+
if (wrapperIndex != null) {
|
|
1106
|
+
wrapperTag = tag.value.tags[wrapperIndex];
|
|
788
1107
|
}
|
|
789
1108
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
let refIndex = childrenIndex - 1;
|
|
793
|
-
let refTag;
|
|
794
|
-
let prevTag = sumtree.getAt(childrenIndex - 1, path.node.children);
|
|
1109
|
+
if (wrapperTag.type === ReferenceTag && wrapperTag.value.flags.expression) {
|
|
1110
|
+
// move past shifts
|
|
795
1111
|
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
} else if (prevTag.type === ReferenceTag) {
|
|
799
|
-
refTag = prevTag;
|
|
1112
|
+
let shifts = 0;
|
|
1113
|
+
let tag = Tags.getAt(tagsIndex + 1, path.node.tags);
|
|
800
1114
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
)
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
}
|
|
1115
|
+
while (tag?.type === PropertyWrapper && tag.value.tags[0].type === ShiftTag) {
|
|
1116
|
+
shifts++;
|
|
1117
|
+
wrapperIndex = 1;
|
|
1118
|
+
tag = Tags.getAt(tagsIndex + shifts + 1, path.node.tags);
|
|
1119
|
+
}
|
|
1120
|
+
if (shifts) {
|
|
1121
|
+
tagsIndex += shifts;
|
|
1122
|
+
continue;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
812
1125
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1126
|
+
// done
|
|
1127
|
+
if (!isInitialTag && wrapperTag.type !== Property) {
|
|
1128
|
+
return new TagPath(path, tagsIndex, wrapperIndex);
|
|
1129
|
+
}
|
|
816
1130
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
1131
|
+
// in
|
|
1132
|
+
if (tag.type === PropertyWrapper) {
|
|
1133
|
+
if (wrapperIndex + 1 < tag.value.tags.length) {
|
|
1134
|
+
wrapperIndex++;
|
|
1135
|
+
continue;
|
|
1136
|
+
} else if (!wasLeaving && tag.value.tags[1] && tag.value.tags[1].type !== InitializerTag) {
|
|
1137
|
+
path = path.push(tag.value.property.node, tagsIndex);
|
|
1138
|
+
tagsIndex = 0;
|
|
1139
|
+
continue;
|
|
825
1140
|
}
|
|
826
1141
|
}
|
|
827
1142
|
|
|
828
1143
|
// over
|
|
829
|
-
if (path.node &&
|
|
830
|
-
|
|
1144
|
+
if (path.node && tagsIndex + 1 < Tags.getSize(path.node.tags)) {
|
|
1145
|
+
tagsIndex++;
|
|
831
1146
|
continue;
|
|
832
1147
|
}
|
|
833
1148
|
|
|
834
1149
|
// out
|
|
835
|
-
if (path.
|
|
1150
|
+
if (path.parentIndex != null) {
|
|
836
1151
|
do {
|
|
837
|
-
|
|
1152
|
+
tagsIndex = path.parentIndex + 1;
|
|
838
1153
|
|
|
839
1154
|
path = path.parent;
|
|
840
1155
|
leaving = true;
|
|
841
|
-
} while (
|
|
1156
|
+
} while (tagsIndex == null);
|
|
842
1157
|
|
|
843
1158
|
leaving = true;
|
|
844
1159
|
continue;
|
|
@@ -849,143 +1164,52 @@ export class TagPath {
|
|
|
849
1164
|
}
|
|
850
1165
|
|
|
851
1166
|
get previousSibling() {
|
|
852
|
-
const { path,
|
|
1167
|
+
const { path, tagsIndex, wrapperIndex } = this;
|
|
853
1168
|
|
|
854
|
-
|
|
1169
|
+
if (wrapperIndex > 0) {
|
|
1170
|
+
return new TagPath(path, tagsIndex, wrapperIndex - 1);
|
|
1171
|
+
}
|
|
855
1172
|
|
|
856
|
-
|
|
857
|
-
}
|
|
1173
|
+
const child = tagsIndex - 1 < 0 ? null : BTree.getAt(tagsIndex - 1, path.node.tags);
|
|
858
1174
|
|
|
859
|
-
|
|
860
|
-
throw new Error('not implemented');
|
|
1175
|
+
return child && TagPath.from(path, tagsIndex - 1, -1);
|
|
861
1176
|
}
|
|
862
1177
|
|
|
863
|
-
get
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
let leaving = false;
|
|
867
|
-
|
|
868
|
-
for (;;) {
|
|
869
|
-
let tag = sumtree.getAt(childrenIndex, path.node.children);
|
|
870
|
-
let isInitialTag = path.node === this.path.node && childrenIndex === this.childrenIndex;
|
|
871
|
-
let wasLeaving = leaving;
|
|
872
|
-
leaving = false;
|
|
873
|
-
|
|
874
|
-
if (!tag) return null;
|
|
875
|
-
|
|
876
|
-
// done
|
|
877
|
-
if (
|
|
878
|
-
!isInitialTag &&
|
|
879
|
-
tag.type !== EmbeddedNode &&
|
|
880
|
-
tag.type !== ShiftTag &&
|
|
881
|
-
(tag.type !== GapTag || isGapNode(path.node))
|
|
882
|
-
) {
|
|
883
|
-
return new TagPath(path, childrenIndex);
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
// in
|
|
887
|
-
if (tag.type === EmbeddedNode && !wasLeaving) {
|
|
888
|
-
path = path.push(tag.value, childrenIndex - 1);
|
|
889
|
-
childrenIndex = sumtree.getSize(tag.value.children) - 1;
|
|
890
|
-
continue;
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
// in
|
|
894
|
-
if (tag.type === GapTag && !wasLeaving && !isGapNode(path.node)) {
|
|
895
|
-
let refIndex = childrenIndex - 1;
|
|
896
|
-
let refTag;
|
|
897
|
-
let prevTag = sumtree.getAt(childrenIndex - 1, path.node.children);
|
|
898
|
-
|
|
899
|
-
if (prevTag.type === ShiftTag) {
|
|
900
|
-
// continue
|
|
901
|
-
} else if (prevTag.type === ReferenceTag) {
|
|
902
|
-
refTag = prevTag;
|
|
903
|
-
|
|
904
|
-
if (
|
|
905
|
-
!['#', '@'].includes(refTag.value.name) &&
|
|
906
|
-
(!refTag.value.isArray || getChildPropertyIndex(path.node, refIndex) != null)
|
|
907
|
-
) {
|
|
908
|
-
const { name, isArray, flags } = refTag.value;
|
|
909
|
-
let resolvedReference = refTag;
|
|
910
|
-
if (isArray) {
|
|
911
|
-
let index = getChildPropertyIndex(path.node, refIndex);
|
|
912
|
-
resolvedReference =
|
|
913
|
-
index === -1 ? null : buildReferenceTag(name, index != null, flags, index);
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
if (resolvedReference) {
|
|
917
|
-
path = path.get(resolvedReference);
|
|
918
|
-
childrenIndex = 0;
|
|
919
|
-
|
|
920
|
-
if (!path) {
|
|
921
|
-
return null;
|
|
922
|
-
}
|
|
923
|
-
continue;
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
} else {
|
|
927
|
-
throw new Error();
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
// over
|
|
932
|
-
if (path.node && childrenIndex + 1 < sumtree.getSize(path.node.children)) {
|
|
933
|
-
childrenIndex--;
|
|
934
|
-
continue;
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
// out
|
|
938
|
-
if (path.referenceIndex != null) {
|
|
939
|
-
do {
|
|
940
|
-
childrenIndex = path.referenceIndex;
|
|
941
|
-
|
|
942
|
-
path = path.parent;
|
|
943
|
-
leaving = true;
|
|
944
|
-
} while (childrenIndex == null);
|
|
945
|
-
|
|
946
|
-
leaving = true;
|
|
947
|
-
continue;
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
return null;
|
|
951
|
-
}
|
|
1178
|
+
get innerNode() {
|
|
1179
|
+
return this.inner?.node;
|
|
952
1180
|
}
|
|
953
1181
|
|
|
954
1182
|
get inner() {
|
|
955
|
-
|
|
956
|
-
}
|
|
1183
|
+
let { path, tagsIndex, tag, previousSibling } = this;
|
|
957
1184
|
|
|
958
|
-
|
|
959
|
-
let { tag, previousSibling: refPath } = this;
|
|
1185
|
+
let refPath = TagPath.from(path, tagsIndex, 0);
|
|
960
1186
|
|
|
961
|
-
if (tag.type !==
|
|
1187
|
+
if (tag.type !== PropertyWrapper) {
|
|
962
1188
|
return null;
|
|
963
1189
|
}
|
|
964
1190
|
|
|
965
1191
|
let shiftPath = null;
|
|
966
1192
|
if (refPath.tag.type === ShiftTag) {
|
|
967
1193
|
shiftPath = refPath;
|
|
968
|
-
|
|
1194
|
+
throw new Error('not implemented');
|
|
1195
|
+
refPath = TagPath.from(this.path, this.tagsIndex - refPath.tag.value.index - 2);
|
|
969
1196
|
}
|
|
970
1197
|
|
|
971
1198
|
if (refPath.tag.type !== ReferenceTag) throw new Error();
|
|
972
1199
|
|
|
973
|
-
|
|
1200
|
+
const { type, name } = refPath.tag.value;
|
|
974
1201
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
1202
|
+
return this.path.get([
|
|
1203
|
+
buildFullPathSegment(
|
|
1204
|
+
type,
|
|
978
1205
|
name,
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
return this.path.get(resolvedRef, shiftPath?.tag.value.index);
|
|
1206
|
+
getChildPropertyIndex(refPath.path.node, refPath.tagsIndex),
|
|
1207
|
+
shiftPath?.tag.value.index,
|
|
1208
|
+
),
|
|
1209
|
+
]);
|
|
986
1210
|
}
|
|
987
1211
|
|
|
988
1212
|
equalTo(tagPath) {
|
|
989
|
-
return this.node === tagPath.node && this.
|
|
1213
|
+
return this.node === tagPath.node && this.tagsIndex === tagPath.tagsIndex;
|
|
990
1214
|
}
|
|
991
1215
|
}
|