@lezer/common 1.0.4 → 1.1.1
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/dist/index.cjs +186 -86
- package/dist/index.d.cts +19 -9
- package/dist/index.d.ts +19 -9
- package/dist/index.js +186 -86
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// FIXME profile adding a per-Tree TreeNode cache, validating it by
|
|
4
|
-
// parent pointer
|
|
5
3
|
/**
|
|
6
4
|
The default maximum length of a `TreeBuffer` node.
|
|
7
5
|
*/
|
|
@@ -116,6 +114,12 @@ class MountedTree {
|
|
|
116
114
|
this.overlay = overlay;
|
|
117
115
|
this.parser = parser;
|
|
118
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
@internal
|
|
119
|
+
*/
|
|
120
|
+
static get(tree) {
|
|
121
|
+
return tree && tree.props && tree.props[NodeProp.mounted.id];
|
|
122
|
+
}
|
|
119
123
|
}
|
|
120
124
|
const noProps = Object.create(null);
|
|
121
125
|
/**
|
|
@@ -371,7 +375,7 @@ class Tree {
|
|
|
371
375
|
@internal
|
|
372
376
|
*/
|
|
373
377
|
toString() {
|
|
374
|
-
let mounted =
|
|
378
|
+
let mounted = MountedTree.get(this);
|
|
375
379
|
if (mounted && !mounted.overlay)
|
|
376
380
|
return mounted.tree.toString();
|
|
377
381
|
let children = "";
|
|
@@ -443,6 +447,16 @@ class Tree {
|
|
|
443
447
|
return node;
|
|
444
448
|
}
|
|
445
449
|
/**
|
|
450
|
+
In some situations, it can be useful to iterate through all
|
|
451
|
+
nodes around a position, including those in overlays that don't
|
|
452
|
+
directly cover the position. This method gives you an iterator
|
|
453
|
+
that will produce all nodes, from small to big, around the given
|
|
454
|
+
position.
|
|
455
|
+
*/
|
|
456
|
+
resolveStack(pos, side = 0) {
|
|
457
|
+
return stackIterator(this, pos, side);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
446
460
|
Iterate over the tree and its children, calling `enter` for any
|
|
447
461
|
node that touches the `from`/`to` region (if given) before
|
|
448
462
|
running over such a node's children, and `leave` (if given) when
|
|
@@ -621,22 +635,6 @@ function checkSide(side, pos, from, to) {
|
|
|
621
635
|
case 4 /* Side.DontCare */: return true;
|
|
622
636
|
}
|
|
623
637
|
}
|
|
624
|
-
function enterUnfinishedNodesBefore(node, pos) {
|
|
625
|
-
let scan = node.childBefore(pos);
|
|
626
|
-
while (scan) {
|
|
627
|
-
let last = scan.lastChild;
|
|
628
|
-
if (!last || last.to != scan.to)
|
|
629
|
-
break;
|
|
630
|
-
if (last.type.isError && last.from == last.to) {
|
|
631
|
-
node = scan;
|
|
632
|
-
scan = last.prevSibling;
|
|
633
|
-
}
|
|
634
|
-
else {
|
|
635
|
-
scan = last;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
return node;
|
|
639
|
-
}
|
|
640
638
|
function resolveNode(node, pos, side, overlays) {
|
|
641
639
|
var _a;
|
|
642
640
|
// Move up to a node that actually holds the position, if possible
|
|
@@ -662,10 +660,48 @@ function resolveNode(node, pos, side, overlays) {
|
|
|
662
660
|
node = inner;
|
|
663
661
|
}
|
|
664
662
|
}
|
|
665
|
-
class
|
|
663
|
+
class BaseNode {
|
|
664
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
665
|
+
getChild(type, before = null, after = null) {
|
|
666
|
+
let r = getChildren(this, type, before, after);
|
|
667
|
+
return r.length ? r[0] : null;
|
|
668
|
+
}
|
|
669
|
+
getChildren(type, before = null, after = null) {
|
|
670
|
+
return getChildren(this, type, before, after);
|
|
671
|
+
}
|
|
672
|
+
resolve(pos, side = 0) {
|
|
673
|
+
return resolveNode(this, pos, side, false);
|
|
674
|
+
}
|
|
675
|
+
resolveInner(pos, side = 0) {
|
|
676
|
+
return resolveNode(this, pos, side, true);
|
|
677
|
+
}
|
|
678
|
+
matchContext(context) {
|
|
679
|
+
return matchNodeContext(this, context);
|
|
680
|
+
}
|
|
681
|
+
enterUnfinishedNodesBefore(pos) {
|
|
682
|
+
let scan = this.childBefore(pos), node = this;
|
|
683
|
+
while (scan) {
|
|
684
|
+
let last = scan.lastChild;
|
|
685
|
+
if (!last || last.to != scan.to)
|
|
686
|
+
break;
|
|
687
|
+
if (last.type.isError && last.from == last.to) {
|
|
688
|
+
node = scan;
|
|
689
|
+
scan = last.prevSibling;
|
|
690
|
+
}
|
|
691
|
+
else {
|
|
692
|
+
scan = last;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
return node;
|
|
696
|
+
}
|
|
697
|
+
get node() { return this; }
|
|
698
|
+
get next() { return this.parent; }
|
|
699
|
+
}
|
|
700
|
+
class TreeNode extends BaseNode {
|
|
666
701
|
constructor(_tree, from,
|
|
667
702
|
// Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
|
|
668
703
|
index, _parent) {
|
|
704
|
+
super();
|
|
669
705
|
this._tree = _tree;
|
|
670
706
|
this.from = from;
|
|
671
707
|
this.index = index;
|
|
@@ -689,8 +725,7 @@ class TreeNode {
|
|
|
689
725
|
}
|
|
690
726
|
else if ((mode & exports.IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
|
|
691
727
|
let mounted;
|
|
692
|
-
if (!(mode & exports.IterMode.IgnoreMounts) &&
|
|
693
|
-
next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
|
|
728
|
+
if (!(mode & exports.IterMode.IgnoreMounts) && (mounted = MountedTree.get(next)) && !mounted.overlay)
|
|
694
729
|
return new TreeNode(mounted.tree, start, i, parent);
|
|
695
730
|
let inner = new TreeNode(next, start, i, parent);
|
|
696
731
|
return (mode & exports.IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
|
|
@@ -714,7 +749,7 @@ class TreeNode {
|
|
|
714
749
|
childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Side.Before */); }
|
|
715
750
|
enter(pos, side, mode = 0) {
|
|
716
751
|
let mounted;
|
|
717
|
-
if (!(mode & exports.IterMode.IgnoreOverlays) && (mounted = this._tree
|
|
752
|
+
if (!(mode & exports.IterMode.IgnoreOverlays) && (mounted = MountedTree.get(this._tree)) && mounted.overlay) {
|
|
718
753
|
let rPos = pos - this.from;
|
|
719
754
|
for (let { from, to } of mounted.overlay) {
|
|
720
755
|
if ((side > 0 ? from <= rPos : from < rPos) &&
|
|
@@ -739,29 +774,12 @@ class TreeNode {
|
|
|
739
774
|
get prevSibling() {
|
|
740
775
|
return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* Side.DontCare */) : null;
|
|
741
776
|
}
|
|
742
|
-
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
743
777
|
get tree() { return this._tree; }
|
|
744
778
|
toTree() { return this._tree; }
|
|
745
|
-
resolve(pos, side = 0) {
|
|
746
|
-
return resolveNode(this, pos, side, false);
|
|
747
|
-
}
|
|
748
|
-
resolveInner(pos, side = 0) {
|
|
749
|
-
return resolveNode(this, pos, side, true);
|
|
750
|
-
}
|
|
751
|
-
enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
|
|
752
|
-
getChild(type, before = null, after = null) {
|
|
753
|
-
let r = getChildren(this, type, before, after);
|
|
754
|
-
return r.length ? r[0] : null;
|
|
755
|
-
}
|
|
756
|
-
getChildren(type, before = null, after = null) {
|
|
757
|
-
return getChildren(this, type, before, after);
|
|
758
|
-
}
|
|
759
779
|
/**
|
|
760
780
|
@internal
|
|
761
781
|
*/
|
|
762
782
|
toString() { return this._tree.toString(); }
|
|
763
|
-
get node() { return this; }
|
|
764
|
-
matchContext(context) { return matchNodeContext(this, context); }
|
|
765
783
|
}
|
|
766
784
|
function getChildren(node, type, before, after) {
|
|
767
785
|
let cur = node.cursor(), result = [];
|
|
@@ -800,11 +818,12 @@ class BufferContext {
|
|
|
800
818
|
this.start = start;
|
|
801
819
|
}
|
|
802
820
|
}
|
|
803
|
-
class BufferNode {
|
|
821
|
+
class BufferNode extends BaseNode {
|
|
804
822
|
get name() { return this.type.name; }
|
|
805
823
|
get from() { return this.context.start + this.context.buffer.buffer[this.index + 1]; }
|
|
806
824
|
get to() { return this.context.start + this.context.buffer.buffer[this.index + 2]; }
|
|
807
825
|
constructor(context, _parent, index) {
|
|
826
|
+
super();
|
|
808
827
|
this.context = context;
|
|
809
828
|
this._parent = _parent;
|
|
810
829
|
this.index = index;
|
|
@@ -846,7 +865,6 @@ class BufferNode {
|
|
|
846
865
|
return this.externalSibling(-1);
|
|
847
866
|
return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* Side.DontCare */));
|
|
848
867
|
}
|
|
849
|
-
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
850
868
|
get tree() { return null; }
|
|
851
869
|
toTree() {
|
|
852
870
|
let children = [], positions = [];
|
|
@@ -859,26 +877,55 @@ class BufferNode {
|
|
|
859
877
|
}
|
|
860
878
|
return new Tree(this.type, children, positions, this.to - this.from);
|
|
861
879
|
}
|
|
862
|
-
resolve(pos, side = 0) {
|
|
863
|
-
return resolveNode(this, pos, side, false);
|
|
864
|
-
}
|
|
865
|
-
resolveInner(pos, side = 0) {
|
|
866
|
-
return resolveNode(this, pos, side, true);
|
|
867
|
-
}
|
|
868
|
-
enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
|
|
869
880
|
/**
|
|
870
881
|
@internal
|
|
871
882
|
*/
|
|
872
883
|
toString() { return this.context.buffer.childString(this.index); }
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
884
|
+
}
|
|
885
|
+
function iterStack(heads) {
|
|
886
|
+
if (!heads.length)
|
|
887
|
+
return null;
|
|
888
|
+
let pick = 0, picked = heads[0];
|
|
889
|
+
for (let i = 1; i < heads.length; i++) {
|
|
890
|
+
let node = heads[i];
|
|
891
|
+
if (node.from > picked.from || node.to < picked.to) {
|
|
892
|
+
picked = node;
|
|
893
|
+
pick = i;
|
|
894
|
+
}
|
|
876
895
|
}
|
|
877
|
-
|
|
878
|
-
|
|
896
|
+
let next = picked instanceof TreeNode && picked.index < 0 ? null : picked.parent;
|
|
897
|
+
let newHeads = heads.slice();
|
|
898
|
+
if (next)
|
|
899
|
+
newHeads[pick] = next;
|
|
900
|
+
else
|
|
901
|
+
newHeads.splice(pick, 1);
|
|
902
|
+
return new StackIterator(newHeads, picked);
|
|
903
|
+
}
|
|
904
|
+
class StackIterator {
|
|
905
|
+
constructor(heads, node) {
|
|
906
|
+
this.heads = heads;
|
|
907
|
+
this.node = node;
|
|
879
908
|
}
|
|
880
|
-
get
|
|
881
|
-
|
|
909
|
+
get next() { return iterStack(this.heads); }
|
|
910
|
+
}
|
|
911
|
+
function stackIterator(tree, pos, side) {
|
|
912
|
+
let inner = tree.resolveInner(pos, side), layers = null;
|
|
913
|
+
for (let scan = inner instanceof TreeNode ? inner : inner.context.parent; scan; scan = scan.parent) {
|
|
914
|
+
if (scan.index < 0) { // This is an overlay root
|
|
915
|
+
let parent = scan.parent;
|
|
916
|
+
(layers || (layers = [inner])).push(parent.resolve(pos, side));
|
|
917
|
+
scan = parent;
|
|
918
|
+
}
|
|
919
|
+
else {
|
|
920
|
+
let mount = MountedTree.get(scan.tree);
|
|
921
|
+
// Relevant overlay branching off
|
|
922
|
+
if (mount && mount.overlay && mount.overlay[0].from <= pos && mount.overlay[mount.overlay.length - 1].to >= pos) {
|
|
923
|
+
let root = new TreeNode(mount.tree, mount.overlay[0].from + scan.from, -1, scan);
|
|
924
|
+
(layers || (layers = [inner])).push(resolveNode(root, pos, side, false));
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return layers ? iterStack(layers) : inner;
|
|
882
929
|
}
|
|
883
930
|
/**
|
|
884
931
|
A tree cursor object focuses on a given node in a syntax tree, and
|
|
@@ -937,6 +984,9 @@ class TreeCursor {
|
|
|
937
984
|
this.to = start + buffer.buffer[index + 2];
|
|
938
985
|
return true;
|
|
939
986
|
}
|
|
987
|
+
/**
|
|
988
|
+
@internal
|
|
989
|
+
*/
|
|
940
990
|
yield(node) {
|
|
941
991
|
if (!node)
|
|
942
992
|
return false;
|
|
@@ -1202,7 +1252,7 @@ function buildTree(data) {
|
|
|
1202
1252
|
let cursor = Array.isArray(buffer) ? new FlatBufferCursor(buffer, buffer.length) : buffer;
|
|
1203
1253
|
let types = nodeSet.types;
|
|
1204
1254
|
let contextHash = 0, lookAhead = 0;
|
|
1205
|
-
function takeNode(parentStart, minPos, children, positions, inRepeat) {
|
|
1255
|
+
function takeNode(parentStart, minPos, children, positions, inRepeat, depth) {
|
|
1206
1256
|
let { id, start, end, size } = cursor;
|
|
1207
1257
|
let lookAheadAtStart = lookAhead;
|
|
1208
1258
|
while (size < 0) {
|
|
@@ -1251,8 +1301,11 @@ function buildTree(data) {
|
|
|
1251
1301
|
}
|
|
1252
1302
|
cursor.next();
|
|
1253
1303
|
}
|
|
1304
|
+
else if (depth > 2500 /* CutOff.Depth */) {
|
|
1305
|
+
takeFlatNode(start, endPos, localChildren, localPositions);
|
|
1306
|
+
}
|
|
1254
1307
|
else {
|
|
1255
|
-
takeNode(start, endPos, localChildren, localPositions, localInRepeat);
|
|
1308
|
+
takeNode(start, endPos, localChildren, localPositions, localInRepeat, depth + 1);
|
|
1256
1309
|
}
|
|
1257
1310
|
}
|
|
1258
1311
|
if (localInRepeat >= 0 && lastGroup > 0 && lastGroup < localChildren.length)
|
|
@@ -1270,6 +1323,38 @@ function buildTree(data) {
|
|
|
1270
1323
|
children.push(node);
|
|
1271
1324
|
positions.push(startPos);
|
|
1272
1325
|
}
|
|
1326
|
+
function takeFlatNode(parentStart, minPos, children, positions) {
|
|
1327
|
+
let nodes = []; // Temporary, inverted array of leaf nodes found, with absolute positions
|
|
1328
|
+
let nodeCount = 0, stopAt = -1;
|
|
1329
|
+
while (cursor.pos > minPos) {
|
|
1330
|
+
let { id, start, end, size } = cursor;
|
|
1331
|
+
if (size > 4) { // Not a leaf
|
|
1332
|
+
cursor.next();
|
|
1333
|
+
}
|
|
1334
|
+
else if (stopAt > -1 && start < stopAt) {
|
|
1335
|
+
break;
|
|
1336
|
+
}
|
|
1337
|
+
else {
|
|
1338
|
+
if (stopAt < 0)
|
|
1339
|
+
stopAt = end - maxBufferLength;
|
|
1340
|
+
nodes.push(id, start, end);
|
|
1341
|
+
nodeCount++;
|
|
1342
|
+
cursor.next();
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
if (nodeCount) {
|
|
1346
|
+
let buffer = new Uint16Array(nodeCount * 4);
|
|
1347
|
+
let start = nodes[nodes.length - 2];
|
|
1348
|
+
for (let i = nodes.length - 3, j = 0; i >= 0; i -= 3) {
|
|
1349
|
+
buffer[j++] = nodes[i];
|
|
1350
|
+
buffer[j++] = nodes[i + 1] - start;
|
|
1351
|
+
buffer[j++] = nodes[i + 2] - start;
|
|
1352
|
+
buffer[j++] = j;
|
|
1353
|
+
}
|
|
1354
|
+
children.push(new TreeBuffer(buffer, nodes[2] - start, nodeSet));
|
|
1355
|
+
positions.push(start - parentStart);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1273
1358
|
function makeBalanced(type) {
|
|
1274
1359
|
return (children, positions, length) => {
|
|
1275
1360
|
let lookAhead = 0, lastI = children.length - 1, last, lookAheadProp;
|
|
@@ -1380,7 +1465,7 @@ function buildTree(data) {
|
|
|
1380
1465
|
}
|
|
1381
1466
|
let children = [], positions = [];
|
|
1382
1467
|
while (cursor.pos > 0)
|
|
1383
|
-
takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1);
|
|
1468
|
+
takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1, 0);
|
|
1384
1469
|
let length = (_a = data.length) !== null && _a !== void 0 ? _a : (children.length ? positions[0] + children[0].length : 0);
|
|
1385
1470
|
return new Tree(types[data.topID], children.reverse(), positions.reverse(), length);
|
|
1386
1471
|
}
|
|
@@ -1661,16 +1746,18 @@ function parseMixed(nest) {
|
|
|
1661
1746
|
return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges);
|
|
1662
1747
|
}
|
|
1663
1748
|
class InnerParse {
|
|
1664
|
-
constructor(parser, parse, overlay, target,
|
|
1749
|
+
constructor(parser, parse, overlay, target, from) {
|
|
1665
1750
|
this.parser = parser;
|
|
1666
1751
|
this.parse = parse;
|
|
1667
1752
|
this.overlay = overlay;
|
|
1668
1753
|
this.target = target;
|
|
1669
|
-
this.
|
|
1670
|
-
if (!ranges.length || ranges.some(r => r.from >= r.to))
|
|
1671
|
-
throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
|
|
1754
|
+
this.from = from;
|
|
1672
1755
|
}
|
|
1673
1756
|
}
|
|
1757
|
+
function checkRanges(ranges) {
|
|
1758
|
+
if (!ranges.length || ranges.some(r => r.from >= r.to))
|
|
1759
|
+
throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
|
|
1760
|
+
}
|
|
1674
1761
|
class ActiveOverlay {
|
|
1675
1762
|
constructor(parser, predicate, mounts, index, start, target, prev) {
|
|
1676
1763
|
this.parser = parser;
|
|
@@ -1733,7 +1820,7 @@ class MixedParse {
|
|
|
1733
1820
|
return 0;
|
|
1734
1821
|
let pos = this.input.length;
|
|
1735
1822
|
for (let i = this.innerDone; i < this.inner.length; i++) {
|
|
1736
|
-
if (this.inner[i].
|
|
1823
|
+
if (this.inner[i].from < pos)
|
|
1737
1824
|
pos = Math.min(pos, this.inner[i].parse.parsedPos);
|
|
1738
1825
|
}
|
|
1739
1826
|
return pos;
|
|
@@ -1751,9 +1838,12 @@ class MixedParse {
|
|
|
1751
1838
|
let overlay = null;
|
|
1752
1839
|
let covered = null;
|
|
1753
1840
|
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), exports.IterMode.IncludeAnonymous | exports.IterMode.IgnoreMounts);
|
|
1754
|
-
scan: for (let nest, isCovered
|
|
1841
|
+
scan: for (let nest, isCovered;;) {
|
|
1755
1842
|
let enter = true, range;
|
|
1756
|
-
if (
|
|
1843
|
+
if (this.stoppedAt != null && cursor.from >= this.stoppedAt) {
|
|
1844
|
+
enter = false;
|
|
1845
|
+
}
|
|
1846
|
+
else if (fragmentCursor.hasNode(cursor)) {
|
|
1757
1847
|
if (overlay) {
|
|
1758
1848
|
let match = overlay.mounts.find(m => m.frag.from <= cursor.from && m.frag.to >= cursor.to && m.mount.overlay);
|
|
1759
1849
|
if (match)
|
|
@@ -1768,7 +1858,8 @@ class MixedParse {
|
|
|
1768
1858
|
else if (covered && (isCovered = checkCover(covered.ranges, cursor.from, cursor.to))) {
|
|
1769
1859
|
enter = isCovered != 2 /* Cover.Full */;
|
|
1770
1860
|
}
|
|
1771
|
-
else if (!cursor.type.isAnonymous &&
|
|
1861
|
+
else if (!cursor.type.isAnonymous && (nest = this.nest(cursor, this.input)) &&
|
|
1862
|
+
(cursor.from < cursor.to || !nest.overlay)) {
|
|
1772
1863
|
if (!cursor.tree)
|
|
1773
1864
|
materialize(cursor);
|
|
1774
1865
|
let oldMounts = fragmentCursor.findMounts(cursor.from, nest.parser);
|
|
@@ -1776,9 +1867,13 @@ class MixedParse {
|
|
|
1776
1867
|
overlay = new ActiveOverlay(nest.parser, nest.overlay, oldMounts, this.inner.length, cursor.from, cursor.tree, overlay);
|
|
1777
1868
|
}
|
|
1778
1869
|
else {
|
|
1779
|
-
let ranges = punchRanges(this.ranges, nest.overlay ||
|
|
1870
|
+
let ranges = punchRanges(this.ranges, nest.overlay ||
|
|
1871
|
+
(cursor.from < cursor.to ? [new Range(cursor.from, cursor.to)] : []));
|
|
1780
1872
|
if (ranges.length)
|
|
1781
|
-
|
|
1873
|
+
checkRanges(ranges);
|
|
1874
|
+
if (ranges.length || !nest.overlay)
|
|
1875
|
+
this.inner.push(new InnerParse(nest.parser, ranges.length ? nest.parser.startParse(this.input, enterFragments(oldMounts, ranges), ranges)
|
|
1876
|
+
: nest.parser.startParse(""), nest.overlay ? nest.overlay.map(r => new Range(r.from - cursor.from, r.to - cursor.from)) : null, cursor.tree, ranges.length ? ranges[0].from : cursor.from));
|
|
1782
1877
|
if (!nest.overlay)
|
|
1783
1878
|
enter = false;
|
|
1784
1879
|
else if (ranges.length)
|
|
@@ -1805,8 +1900,10 @@ class MixedParse {
|
|
|
1805
1900
|
break scan;
|
|
1806
1901
|
if (overlay && !--overlay.depth) {
|
|
1807
1902
|
let ranges = punchRanges(this.ranges, overlay.ranges);
|
|
1808
|
-
if (ranges.length)
|
|
1809
|
-
|
|
1903
|
+
if (ranges.length) {
|
|
1904
|
+
checkRanges(ranges);
|
|
1905
|
+
this.inner.splice(overlay.index, 0, new InnerParse(overlay.parser, overlay.parser.startParse(this.input, enterFragments(overlay.mounts, ranges), ranges), overlay.ranges.map(r => new Range(r.from - overlay.start, r.to - overlay.start)), overlay.target, ranges[0].from));
|
|
1906
|
+
}
|
|
1810
1907
|
overlay = overlay.prev;
|
|
1811
1908
|
}
|
|
1812
1909
|
if (covered && !--covered.depth)
|
|
@@ -1840,11 +1937,11 @@ function sliceBuf(buf, startI, endI, nodes, positions, off) {
|
|
|
1840
1937
|
// parse that was ran via the mix parser, and thus aren't shared with
|
|
1841
1938
|
// any other code, making violations of the immutability safe.
|
|
1842
1939
|
function materialize(cursor) {
|
|
1843
|
-
let { node } = cursor,
|
|
1940
|
+
let { node } = cursor, stack = [];
|
|
1844
1941
|
// Scan up to the nearest tree
|
|
1845
1942
|
do {
|
|
1943
|
+
stack.push(cursor.index);
|
|
1846
1944
|
cursor.parent();
|
|
1847
|
-
depth++;
|
|
1848
1945
|
} while (!cursor.tree);
|
|
1849
1946
|
// Find the index of the buffer in that tree
|
|
1850
1947
|
let i = 0, base = cursor.tree, off = 0;
|
|
@@ -1853,26 +1950,29 @@ function materialize(cursor) {
|
|
|
1853
1950
|
if (off <= node.from && off + base.children[i].length >= node.to)
|
|
1854
1951
|
break;
|
|
1855
1952
|
}
|
|
1856
|
-
let buf = base.children[i], b = buf.buffer;
|
|
1953
|
+
let buf = base.children[i], b = buf.buffer, newStack = [i];
|
|
1857
1954
|
// Split a level in the buffer, putting the nodes before and after
|
|
1858
1955
|
// the child that contains `node` into new buffers.
|
|
1859
|
-
function split(startI, endI, type, innerOffset, length) {
|
|
1860
|
-
let
|
|
1861
|
-
while (b[i + 2] + off <= node.from)
|
|
1862
|
-
i = b[i + 3];
|
|
1956
|
+
function split(startI, endI, type, innerOffset, length, stackPos) {
|
|
1957
|
+
let targetI = stack[stackPos];
|
|
1863
1958
|
let children = [], positions = [];
|
|
1864
|
-
sliceBuf(buf, startI,
|
|
1865
|
-
let from = b[
|
|
1866
|
-
|
|
1867
|
-
|
|
1959
|
+
sliceBuf(buf, startI, targetI, children, positions, innerOffset);
|
|
1960
|
+
let from = b[targetI + 1], to = b[targetI + 2];
|
|
1961
|
+
newStack.push(children.length);
|
|
1962
|
+
let child = stackPos
|
|
1963
|
+
? split(targetI + 4, b[targetI + 3], buf.set.types[b[targetI]], from, to - from, stackPos - 1)
|
|
1964
|
+
: node.toTree();
|
|
1965
|
+
children.push(child);
|
|
1868
1966
|
positions.push(from - innerOffset);
|
|
1869
|
-
sliceBuf(buf, b[
|
|
1967
|
+
sliceBuf(buf, b[targetI + 3], endI, children, positions, innerOffset);
|
|
1870
1968
|
return new Tree(type, children, positions, length);
|
|
1871
1969
|
}
|
|
1872
|
-
base.children[i] = split(0, b.length, NodeType.none, 0, buf.length);
|
|
1970
|
+
base.children[i] = split(0, b.length, NodeType.none, 0, buf.length, stack.length - 1);
|
|
1873
1971
|
// Move the cursor back to the target node
|
|
1874
|
-
for (let
|
|
1875
|
-
cursor.
|
|
1972
|
+
for (let index of newStack) {
|
|
1973
|
+
let tree = cursor.tree.children[index], pos = cursor.tree.positions[index];
|
|
1974
|
+
cursor.yield(new TreeNode(tree, pos + cursor.from, index, cursor._tree));
|
|
1975
|
+
}
|
|
1876
1976
|
}
|
|
1877
1977
|
class StructureCursor {
|
|
1878
1978
|
constructor(root, offset) {
|
package/dist/index.d.cts
CHANGED
|
@@ -615,6 +615,14 @@ declare class Tree {
|
|
|
615
615
|
*/
|
|
616
616
|
resolveInner(pos: number, side?: -1 | 0 | 1): SyntaxNode;
|
|
617
617
|
/**
|
|
618
|
+
In some situations, it can be useful to iterate through all
|
|
619
|
+
nodes around a position, including those in overlays that don't
|
|
620
|
+
directly cover the position. This method gives you an iterator
|
|
621
|
+
that will produce all nodes, from small to big, around the given
|
|
622
|
+
position.
|
|
623
|
+
*/
|
|
624
|
+
resolveStack(pos: number, side?: -1 | 0 | 1): NodeIterator;
|
|
625
|
+
/**
|
|
618
626
|
Iterate over the tree and its children, calling `enter` for any
|
|
619
627
|
node that touches the `from`/`to` region (if given) before
|
|
620
628
|
running over such a node's children, and `leave` (if given) when
|
|
@@ -656,6 +664,13 @@ declare class Tree {
|
|
|
656
664
|
*/
|
|
657
665
|
static build(data: BuildData): Tree;
|
|
658
666
|
}
|
|
667
|
+
/**
|
|
668
|
+
Represents a sequence of nodes.
|
|
669
|
+
*/
|
|
670
|
+
type NodeIterator = {
|
|
671
|
+
node: SyntaxNode;
|
|
672
|
+
next: NodeIterator | null;
|
|
673
|
+
};
|
|
659
674
|
type BuildData = {
|
|
660
675
|
/**
|
|
661
676
|
The buffer or buffer cursor to read the node data from.
|
|
@@ -827,7 +842,9 @@ interface SyntaxNodeRef {
|
|
|
827
842
|
*/
|
|
828
843
|
readonly node: SyntaxNode;
|
|
829
844
|
/**
|
|
830
|
-
Test whether the node matches a given context
|
|
845
|
+
Test whether the node matches a given context—a sequence of
|
|
846
|
+
direct parent nodes. Empty strings in the context array act as
|
|
847
|
+
wildcards, other strings must match the ancestor node's name.
|
|
831
848
|
*/
|
|
832
849
|
matchContext(context: readonly string[]): boolean;
|
|
833
850
|
}
|
|
@@ -921,12 +938,6 @@ interface SyntaxNode extends SyntaxNodeRef {
|
|
|
921
938
|
matching children, not just the first.
|
|
922
939
|
*/
|
|
923
940
|
getChildren(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode[];
|
|
924
|
-
/**
|
|
925
|
-
Test whether the node matches a given context—a sequence of
|
|
926
|
-
direct parent nodes. Empty strings in the context array act as
|
|
927
|
-
wildcards, other strings must match the ancestor node's name.
|
|
928
|
-
*/
|
|
929
|
-
matchContext(context: readonly string[]): boolean;
|
|
930
941
|
}
|
|
931
942
|
/**
|
|
932
943
|
A tree cursor object focuses on a given node in a syntax tree, and
|
|
@@ -953,7 +964,6 @@ declare class TreeCursor implements SyntaxNodeRef {
|
|
|
953
964
|
private bufferNode;
|
|
954
965
|
private yieldNode;
|
|
955
966
|
private yieldBuf;
|
|
956
|
-
private yield;
|
|
957
967
|
/**
|
|
958
968
|
Move the cursor to this node's first child. When this returns
|
|
959
969
|
false, the node has no child, and the cursor has not been moved.
|
|
@@ -1112,4 +1122,4 @@ tree.
|
|
|
1112
1122
|
*/
|
|
1113
1123
|
declare function parseMixed(nest: (node: SyntaxNodeRef, input: Input) => NestedParse | null): ParseWrapper;
|
|
1114
1124
|
|
|
1115
|
-
export { BufferCursor, ChangedRange, DefaultBufferLength, Input, IterMode, MountedTree, NestedParse, NodeProp, NodePropSource, NodeSet, NodeType, NodeWeakMap, ParseWrapper, Parser, PartialParse, SyntaxNode, SyntaxNodeRef, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
|
|
1125
|
+
export { BufferCursor, ChangedRange, DefaultBufferLength, Input, IterMode, MountedTree, NestedParse, NodeIterator, NodeProp, NodePropSource, NodeSet, NodeType, NodeWeakMap, ParseWrapper, Parser, PartialParse, SyntaxNode, SyntaxNodeRef, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
|
package/dist/index.d.ts
CHANGED
|
@@ -615,6 +615,14 @@ declare class Tree {
|
|
|
615
615
|
*/
|
|
616
616
|
resolveInner(pos: number, side?: -1 | 0 | 1): SyntaxNode;
|
|
617
617
|
/**
|
|
618
|
+
In some situations, it can be useful to iterate through all
|
|
619
|
+
nodes around a position, including those in overlays that don't
|
|
620
|
+
directly cover the position. This method gives you an iterator
|
|
621
|
+
that will produce all nodes, from small to big, around the given
|
|
622
|
+
position.
|
|
623
|
+
*/
|
|
624
|
+
resolveStack(pos: number, side?: -1 | 0 | 1): NodeIterator;
|
|
625
|
+
/**
|
|
618
626
|
Iterate over the tree and its children, calling `enter` for any
|
|
619
627
|
node that touches the `from`/`to` region (if given) before
|
|
620
628
|
running over such a node's children, and `leave` (if given) when
|
|
@@ -656,6 +664,13 @@ declare class Tree {
|
|
|
656
664
|
*/
|
|
657
665
|
static build(data: BuildData): Tree;
|
|
658
666
|
}
|
|
667
|
+
/**
|
|
668
|
+
Represents a sequence of nodes.
|
|
669
|
+
*/
|
|
670
|
+
type NodeIterator = {
|
|
671
|
+
node: SyntaxNode;
|
|
672
|
+
next: NodeIterator | null;
|
|
673
|
+
};
|
|
659
674
|
type BuildData = {
|
|
660
675
|
/**
|
|
661
676
|
The buffer or buffer cursor to read the node data from.
|
|
@@ -827,7 +842,9 @@ interface SyntaxNodeRef {
|
|
|
827
842
|
*/
|
|
828
843
|
readonly node: SyntaxNode;
|
|
829
844
|
/**
|
|
830
|
-
Test whether the node matches a given context
|
|
845
|
+
Test whether the node matches a given context—a sequence of
|
|
846
|
+
direct parent nodes. Empty strings in the context array act as
|
|
847
|
+
wildcards, other strings must match the ancestor node's name.
|
|
831
848
|
*/
|
|
832
849
|
matchContext(context: readonly string[]): boolean;
|
|
833
850
|
}
|
|
@@ -921,12 +938,6 @@ interface SyntaxNode extends SyntaxNodeRef {
|
|
|
921
938
|
matching children, not just the first.
|
|
922
939
|
*/
|
|
923
940
|
getChildren(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode[];
|
|
924
|
-
/**
|
|
925
|
-
Test whether the node matches a given context—a sequence of
|
|
926
|
-
direct parent nodes. Empty strings in the context array act as
|
|
927
|
-
wildcards, other strings must match the ancestor node's name.
|
|
928
|
-
*/
|
|
929
|
-
matchContext(context: readonly string[]): boolean;
|
|
930
941
|
}
|
|
931
942
|
/**
|
|
932
943
|
A tree cursor object focuses on a given node in a syntax tree, and
|
|
@@ -953,7 +964,6 @@ declare class TreeCursor implements SyntaxNodeRef {
|
|
|
953
964
|
private bufferNode;
|
|
954
965
|
private yieldNode;
|
|
955
966
|
private yieldBuf;
|
|
956
|
-
private yield;
|
|
957
967
|
/**
|
|
958
968
|
Move the cursor to this node's first child. When this returns
|
|
959
969
|
false, the node has no child, and the cursor has not been moved.
|
|
@@ -1112,4 +1122,4 @@ tree.
|
|
|
1112
1122
|
*/
|
|
1113
1123
|
declare function parseMixed(nest: (node: SyntaxNodeRef, input: Input) => NestedParse | null): ParseWrapper;
|
|
1114
1124
|
|
|
1115
|
-
export { BufferCursor, ChangedRange, DefaultBufferLength, Input, IterMode, MountedTree, NestedParse, NodeProp, NodePropSource, NodeSet, NodeType, NodeWeakMap, ParseWrapper, Parser, PartialParse, SyntaxNode, SyntaxNodeRef, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
|
|
1125
|
+
export { BufferCursor, ChangedRange, DefaultBufferLength, Input, IterMode, MountedTree, NestedParse, NodeIterator, NodeProp, NodePropSource, NodeSet, NodeType, NodeWeakMap, ParseWrapper, Parser, PartialParse, SyntaxNode, SyntaxNodeRef, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// FIXME profile adding a per-Tree TreeNode cache, validating it by
|
|
2
|
-
// parent pointer
|
|
3
1
|
/**
|
|
4
2
|
The default maximum length of a `TreeBuffer` node.
|
|
5
3
|
*/
|
|
@@ -114,6 +112,12 @@ class MountedTree {
|
|
|
114
112
|
this.overlay = overlay;
|
|
115
113
|
this.parser = parser;
|
|
116
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
@internal
|
|
117
|
+
*/
|
|
118
|
+
static get(tree) {
|
|
119
|
+
return tree && tree.props && tree.props[NodeProp.mounted.id];
|
|
120
|
+
}
|
|
117
121
|
}
|
|
118
122
|
const noProps = Object.create(null);
|
|
119
123
|
/**
|
|
@@ -369,7 +373,7 @@ class Tree {
|
|
|
369
373
|
@internal
|
|
370
374
|
*/
|
|
371
375
|
toString() {
|
|
372
|
-
let mounted =
|
|
376
|
+
let mounted = MountedTree.get(this);
|
|
373
377
|
if (mounted && !mounted.overlay)
|
|
374
378
|
return mounted.tree.toString();
|
|
375
379
|
let children = "";
|
|
@@ -441,6 +445,16 @@ class Tree {
|
|
|
441
445
|
return node;
|
|
442
446
|
}
|
|
443
447
|
/**
|
|
448
|
+
In some situations, it can be useful to iterate through all
|
|
449
|
+
nodes around a position, including those in overlays that don't
|
|
450
|
+
directly cover the position. This method gives you an iterator
|
|
451
|
+
that will produce all nodes, from small to big, around the given
|
|
452
|
+
position.
|
|
453
|
+
*/
|
|
454
|
+
resolveStack(pos, side = 0) {
|
|
455
|
+
return stackIterator(this, pos, side);
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
444
458
|
Iterate over the tree and its children, calling `enter` for any
|
|
445
459
|
node that touches the `from`/`to` region (if given) before
|
|
446
460
|
running over such a node's children, and `leave` (if given) when
|
|
@@ -619,22 +633,6 @@ function checkSide(side, pos, from, to) {
|
|
|
619
633
|
case 4 /* Side.DontCare */: return true;
|
|
620
634
|
}
|
|
621
635
|
}
|
|
622
|
-
function enterUnfinishedNodesBefore(node, pos) {
|
|
623
|
-
let scan = node.childBefore(pos);
|
|
624
|
-
while (scan) {
|
|
625
|
-
let last = scan.lastChild;
|
|
626
|
-
if (!last || last.to != scan.to)
|
|
627
|
-
break;
|
|
628
|
-
if (last.type.isError && last.from == last.to) {
|
|
629
|
-
node = scan;
|
|
630
|
-
scan = last.prevSibling;
|
|
631
|
-
}
|
|
632
|
-
else {
|
|
633
|
-
scan = last;
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
return node;
|
|
637
|
-
}
|
|
638
636
|
function resolveNode(node, pos, side, overlays) {
|
|
639
637
|
var _a;
|
|
640
638
|
// Move up to a node that actually holds the position, if possible
|
|
@@ -660,10 +658,48 @@ function resolveNode(node, pos, side, overlays) {
|
|
|
660
658
|
node = inner;
|
|
661
659
|
}
|
|
662
660
|
}
|
|
663
|
-
class
|
|
661
|
+
class BaseNode {
|
|
662
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
663
|
+
getChild(type, before = null, after = null) {
|
|
664
|
+
let r = getChildren(this, type, before, after);
|
|
665
|
+
return r.length ? r[0] : null;
|
|
666
|
+
}
|
|
667
|
+
getChildren(type, before = null, after = null) {
|
|
668
|
+
return getChildren(this, type, before, after);
|
|
669
|
+
}
|
|
670
|
+
resolve(pos, side = 0) {
|
|
671
|
+
return resolveNode(this, pos, side, false);
|
|
672
|
+
}
|
|
673
|
+
resolveInner(pos, side = 0) {
|
|
674
|
+
return resolveNode(this, pos, side, true);
|
|
675
|
+
}
|
|
676
|
+
matchContext(context) {
|
|
677
|
+
return matchNodeContext(this, context);
|
|
678
|
+
}
|
|
679
|
+
enterUnfinishedNodesBefore(pos) {
|
|
680
|
+
let scan = this.childBefore(pos), node = this;
|
|
681
|
+
while (scan) {
|
|
682
|
+
let last = scan.lastChild;
|
|
683
|
+
if (!last || last.to != scan.to)
|
|
684
|
+
break;
|
|
685
|
+
if (last.type.isError && last.from == last.to) {
|
|
686
|
+
node = scan;
|
|
687
|
+
scan = last.prevSibling;
|
|
688
|
+
}
|
|
689
|
+
else {
|
|
690
|
+
scan = last;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return node;
|
|
694
|
+
}
|
|
695
|
+
get node() { return this; }
|
|
696
|
+
get next() { return this.parent; }
|
|
697
|
+
}
|
|
698
|
+
class TreeNode extends BaseNode {
|
|
664
699
|
constructor(_tree, from,
|
|
665
700
|
// Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
|
|
666
701
|
index, _parent) {
|
|
702
|
+
super();
|
|
667
703
|
this._tree = _tree;
|
|
668
704
|
this.from = from;
|
|
669
705
|
this.index = index;
|
|
@@ -687,8 +723,7 @@ class TreeNode {
|
|
|
687
723
|
}
|
|
688
724
|
else if ((mode & IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
|
|
689
725
|
let mounted;
|
|
690
|
-
if (!(mode & IterMode.IgnoreMounts) &&
|
|
691
|
-
next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
|
|
726
|
+
if (!(mode & IterMode.IgnoreMounts) && (mounted = MountedTree.get(next)) && !mounted.overlay)
|
|
692
727
|
return new TreeNode(mounted.tree, start, i, parent);
|
|
693
728
|
let inner = new TreeNode(next, start, i, parent);
|
|
694
729
|
return (mode & IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
|
|
@@ -712,7 +747,7 @@ class TreeNode {
|
|
|
712
747
|
childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Side.Before */); }
|
|
713
748
|
enter(pos, side, mode = 0) {
|
|
714
749
|
let mounted;
|
|
715
|
-
if (!(mode & IterMode.IgnoreOverlays) && (mounted = this._tree
|
|
750
|
+
if (!(mode & IterMode.IgnoreOverlays) && (mounted = MountedTree.get(this._tree)) && mounted.overlay) {
|
|
716
751
|
let rPos = pos - this.from;
|
|
717
752
|
for (let { from, to } of mounted.overlay) {
|
|
718
753
|
if ((side > 0 ? from <= rPos : from < rPos) &&
|
|
@@ -737,29 +772,12 @@ class TreeNode {
|
|
|
737
772
|
get prevSibling() {
|
|
738
773
|
return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* Side.DontCare */) : null;
|
|
739
774
|
}
|
|
740
|
-
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
741
775
|
get tree() { return this._tree; }
|
|
742
776
|
toTree() { return this._tree; }
|
|
743
|
-
resolve(pos, side = 0) {
|
|
744
|
-
return resolveNode(this, pos, side, false);
|
|
745
|
-
}
|
|
746
|
-
resolveInner(pos, side = 0) {
|
|
747
|
-
return resolveNode(this, pos, side, true);
|
|
748
|
-
}
|
|
749
|
-
enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
|
|
750
|
-
getChild(type, before = null, after = null) {
|
|
751
|
-
let r = getChildren(this, type, before, after);
|
|
752
|
-
return r.length ? r[0] : null;
|
|
753
|
-
}
|
|
754
|
-
getChildren(type, before = null, after = null) {
|
|
755
|
-
return getChildren(this, type, before, after);
|
|
756
|
-
}
|
|
757
777
|
/**
|
|
758
778
|
@internal
|
|
759
779
|
*/
|
|
760
780
|
toString() { return this._tree.toString(); }
|
|
761
|
-
get node() { return this; }
|
|
762
|
-
matchContext(context) { return matchNodeContext(this, context); }
|
|
763
781
|
}
|
|
764
782
|
function getChildren(node, type, before, after) {
|
|
765
783
|
let cur = node.cursor(), result = [];
|
|
@@ -798,11 +816,12 @@ class BufferContext {
|
|
|
798
816
|
this.start = start;
|
|
799
817
|
}
|
|
800
818
|
}
|
|
801
|
-
class BufferNode {
|
|
819
|
+
class BufferNode extends BaseNode {
|
|
802
820
|
get name() { return this.type.name; }
|
|
803
821
|
get from() { return this.context.start + this.context.buffer.buffer[this.index + 1]; }
|
|
804
822
|
get to() { return this.context.start + this.context.buffer.buffer[this.index + 2]; }
|
|
805
823
|
constructor(context, _parent, index) {
|
|
824
|
+
super();
|
|
806
825
|
this.context = context;
|
|
807
826
|
this._parent = _parent;
|
|
808
827
|
this.index = index;
|
|
@@ -844,7 +863,6 @@ class BufferNode {
|
|
|
844
863
|
return this.externalSibling(-1);
|
|
845
864
|
return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* Side.DontCare */));
|
|
846
865
|
}
|
|
847
|
-
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
848
866
|
get tree() { return null; }
|
|
849
867
|
toTree() {
|
|
850
868
|
let children = [], positions = [];
|
|
@@ -857,26 +875,55 @@ class BufferNode {
|
|
|
857
875
|
}
|
|
858
876
|
return new Tree(this.type, children, positions, this.to - this.from);
|
|
859
877
|
}
|
|
860
|
-
resolve(pos, side = 0) {
|
|
861
|
-
return resolveNode(this, pos, side, false);
|
|
862
|
-
}
|
|
863
|
-
resolveInner(pos, side = 0) {
|
|
864
|
-
return resolveNode(this, pos, side, true);
|
|
865
|
-
}
|
|
866
|
-
enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
|
|
867
878
|
/**
|
|
868
879
|
@internal
|
|
869
880
|
*/
|
|
870
881
|
toString() { return this.context.buffer.childString(this.index); }
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
882
|
+
}
|
|
883
|
+
function iterStack(heads) {
|
|
884
|
+
if (!heads.length)
|
|
885
|
+
return null;
|
|
886
|
+
let pick = 0, picked = heads[0];
|
|
887
|
+
for (let i = 1; i < heads.length; i++) {
|
|
888
|
+
let node = heads[i];
|
|
889
|
+
if (node.from > picked.from || node.to < picked.to) {
|
|
890
|
+
picked = node;
|
|
891
|
+
pick = i;
|
|
892
|
+
}
|
|
874
893
|
}
|
|
875
|
-
|
|
876
|
-
|
|
894
|
+
let next = picked instanceof TreeNode && picked.index < 0 ? null : picked.parent;
|
|
895
|
+
let newHeads = heads.slice();
|
|
896
|
+
if (next)
|
|
897
|
+
newHeads[pick] = next;
|
|
898
|
+
else
|
|
899
|
+
newHeads.splice(pick, 1);
|
|
900
|
+
return new StackIterator(newHeads, picked);
|
|
901
|
+
}
|
|
902
|
+
class StackIterator {
|
|
903
|
+
constructor(heads, node) {
|
|
904
|
+
this.heads = heads;
|
|
905
|
+
this.node = node;
|
|
877
906
|
}
|
|
878
|
-
get
|
|
879
|
-
|
|
907
|
+
get next() { return iterStack(this.heads); }
|
|
908
|
+
}
|
|
909
|
+
function stackIterator(tree, pos, side) {
|
|
910
|
+
let inner = tree.resolveInner(pos, side), layers = null;
|
|
911
|
+
for (let scan = inner instanceof TreeNode ? inner : inner.context.parent; scan; scan = scan.parent) {
|
|
912
|
+
if (scan.index < 0) { // This is an overlay root
|
|
913
|
+
let parent = scan.parent;
|
|
914
|
+
(layers || (layers = [inner])).push(parent.resolve(pos, side));
|
|
915
|
+
scan = parent;
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
let mount = MountedTree.get(scan.tree);
|
|
919
|
+
// Relevant overlay branching off
|
|
920
|
+
if (mount && mount.overlay && mount.overlay[0].from <= pos && mount.overlay[mount.overlay.length - 1].to >= pos) {
|
|
921
|
+
let root = new TreeNode(mount.tree, mount.overlay[0].from + scan.from, -1, scan);
|
|
922
|
+
(layers || (layers = [inner])).push(resolveNode(root, pos, side, false));
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
return layers ? iterStack(layers) : inner;
|
|
880
927
|
}
|
|
881
928
|
/**
|
|
882
929
|
A tree cursor object focuses on a given node in a syntax tree, and
|
|
@@ -935,6 +982,9 @@ class TreeCursor {
|
|
|
935
982
|
this.to = start + buffer.buffer[index + 2];
|
|
936
983
|
return true;
|
|
937
984
|
}
|
|
985
|
+
/**
|
|
986
|
+
@internal
|
|
987
|
+
*/
|
|
938
988
|
yield(node) {
|
|
939
989
|
if (!node)
|
|
940
990
|
return false;
|
|
@@ -1200,7 +1250,7 @@ function buildTree(data) {
|
|
|
1200
1250
|
let cursor = Array.isArray(buffer) ? new FlatBufferCursor(buffer, buffer.length) : buffer;
|
|
1201
1251
|
let types = nodeSet.types;
|
|
1202
1252
|
let contextHash = 0, lookAhead = 0;
|
|
1203
|
-
function takeNode(parentStart, minPos, children, positions, inRepeat) {
|
|
1253
|
+
function takeNode(parentStart, minPos, children, positions, inRepeat, depth) {
|
|
1204
1254
|
let { id, start, end, size } = cursor;
|
|
1205
1255
|
let lookAheadAtStart = lookAhead;
|
|
1206
1256
|
while (size < 0) {
|
|
@@ -1249,8 +1299,11 @@ function buildTree(data) {
|
|
|
1249
1299
|
}
|
|
1250
1300
|
cursor.next();
|
|
1251
1301
|
}
|
|
1302
|
+
else if (depth > 2500 /* CutOff.Depth */) {
|
|
1303
|
+
takeFlatNode(start, endPos, localChildren, localPositions);
|
|
1304
|
+
}
|
|
1252
1305
|
else {
|
|
1253
|
-
takeNode(start, endPos, localChildren, localPositions, localInRepeat);
|
|
1306
|
+
takeNode(start, endPos, localChildren, localPositions, localInRepeat, depth + 1);
|
|
1254
1307
|
}
|
|
1255
1308
|
}
|
|
1256
1309
|
if (localInRepeat >= 0 && lastGroup > 0 && lastGroup < localChildren.length)
|
|
@@ -1268,6 +1321,38 @@ function buildTree(data) {
|
|
|
1268
1321
|
children.push(node);
|
|
1269
1322
|
positions.push(startPos);
|
|
1270
1323
|
}
|
|
1324
|
+
function takeFlatNode(parentStart, minPos, children, positions) {
|
|
1325
|
+
let nodes = []; // Temporary, inverted array of leaf nodes found, with absolute positions
|
|
1326
|
+
let nodeCount = 0, stopAt = -1;
|
|
1327
|
+
while (cursor.pos > minPos) {
|
|
1328
|
+
let { id, start, end, size } = cursor;
|
|
1329
|
+
if (size > 4) { // Not a leaf
|
|
1330
|
+
cursor.next();
|
|
1331
|
+
}
|
|
1332
|
+
else if (stopAt > -1 && start < stopAt) {
|
|
1333
|
+
break;
|
|
1334
|
+
}
|
|
1335
|
+
else {
|
|
1336
|
+
if (stopAt < 0)
|
|
1337
|
+
stopAt = end - maxBufferLength;
|
|
1338
|
+
nodes.push(id, start, end);
|
|
1339
|
+
nodeCount++;
|
|
1340
|
+
cursor.next();
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
if (nodeCount) {
|
|
1344
|
+
let buffer = new Uint16Array(nodeCount * 4);
|
|
1345
|
+
let start = nodes[nodes.length - 2];
|
|
1346
|
+
for (let i = nodes.length - 3, j = 0; i >= 0; i -= 3) {
|
|
1347
|
+
buffer[j++] = nodes[i];
|
|
1348
|
+
buffer[j++] = nodes[i + 1] - start;
|
|
1349
|
+
buffer[j++] = nodes[i + 2] - start;
|
|
1350
|
+
buffer[j++] = j;
|
|
1351
|
+
}
|
|
1352
|
+
children.push(new TreeBuffer(buffer, nodes[2] - start, nodeSet));
|
|
1353
|
+
positions.push(start - parentStart);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1271
1356
|
function makeBalanced(type) {
|
|
1272
1357
|
return (children, positions, length) => {
|
|
1273
1358
|
let lookAhead = 0, lastI = children.length - 1, last, lookAheadProp;
|
|
@@ -1378,7 +1463,7 @@ function buildTree(data) {
|
|
|
1378
1463
|
}
|
|
1379
1464
|
let children = [], positions = [];
|
|
1380
1465
|
while (cursor.pos > 0)
|
|
1381
|
-
takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1);
|
|
1466
|
+
takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1, 0);
|
|
1382
1467
|
let length = (_a = data.length) !== null && _a !== void 0 ? _a : (children.length ? positions[0] + children[0].length : 0);
|
|
1383
1468
|
return new Tree(types[data.topID], children.reverse(), positions.reverse(), length);
|
|
1384
1469
|
}
|
|
@@ -1659,16 +1744,18 @@ function parseMixed(nest) {
|
|
|
1659
1744
|
return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges);
|
|
1660
1745
|
}
|
|
1661
1746
|
class InnerParse {
|
|
1662
|
-
constructor(parser, parse, overlay, target,
|
|
1747
|
+
constructor(parser, parse, overlay, target, from) {
|
|
1663
1748
|
this.parser = parser;
|
|
1664
1749
|
this.parse = parse;
|
|
1665
1750
|
this.overlay = overlay;
|
|
1666
1751
|
this.target = target;
|
|
1667
|
-
this.
|
|
1668
|
-
if (!ranges.length || ranges.some(r => r.from >= r.to))
|
|
1669
|
-
throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
|
|
1752
|
+
this.from = from;
|
|
1670
1753
|
}
|
|
1671
1754
|
}
|
|
1755
|
+
function checkRanges(ranges) {
|
|
1756
|
+
if (!ranges.length || ranges.some(r => r.from >= r.to))
|
|
1757
|
+
throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
|
|
1758
|
+
}
|
|
1672
1759
|
class ActiveOverlay {
|
|
1673
1760
|
constructor(parser, predicate, mounts, index, start, target, prev) {
|
|
1674
1761
|
this.parser = parser;
|
|
@@ -1731,7 +1818,7 @@ class MixedParse {
|
|
|
1731
1818
|
return 0;
|
|
1732
1819
|
let pos = this.input.length;
|
|
1733
1820
|
for (let i = this.innerDone; i < this.inner.length; i++) {
|
|
1734
|
-
if (this.inner[i].
|
|
1821
|
+
if (this.inner[i].from < pos)
|
|
1735
1822
|
pos = Math.min(pos, this.inner[i].parse.parsedPos);
|
|
1736
1823
|
}
|
|
1737
1824
|
return pos;
|
|
@@ -1749,9 +1836,12 @@ class MixedParse {
|
|
|
1749
1836
|
let overlay = null;
|
|
1750
1837
|
let covered = null;
|
|
1751
1838
|
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), IterMode.IncludeAnonymous | IterMode.IgnoreMounts);
|
|
1752
|
-
scan: for (let nest, isCovered
|
|
1839
|
+
scan: for (let nest, isCovered;;) {
|
|
1753
1840
|
let enter = true, range;
|
|
1754
|
-
if (
|
|
1841
|
+
if (this.stoppedAt != null && cursor.from >= this.stoppedAt) {
|
|
1842
|
+
enter = false;
|
|
1843
|
+
}
|
|
1844
|
+
else if (fragmentCursor.hasNode(cursor)) {
|
|
1755
1845
|
if (overlay) {
|
|
1756
1846
|
let match = overlay.mounts.find(m => m.frag.from <= cursor.from && m.frag.to >= cursor.to && m.mount.overlay);
|
|
1757
1847
|
if (match)
|
|
@@ -1766,7 +1856,8 @@ class MixedParse {
|
|
|
1766
1856
|
else if (covered && (isCovered = checkCover(covered.ranges, cursor.from, cursor.to))) {
|
|
1767
1857
|
enter = isCovered != 2 /* Cover.Full */;
|
|
1768
1858
|
}
|
|
1769
|
-
else if (!cursor.type.isAnonymous &&
|
|
1859
|
+
else if (!cursor.type.isAnonymous && (nest = this.nest(cursor, this.input)) &&
|
|
1860
|
+
(cursor.from < cursor.to || !nest.overlay)) {
|
|
1770
1861
|
if (!cursor.tree)
|
|
1771
1862
|
materialize(cursor);
|
|
1772
1863
|
let oldMounts = fragmentCursor.findMounts(cursor.from, nest.parser);
|
|
@@ -1774,9 +1865,13 @@ class MixedParse {
|
|
|
1774
1865
|
overlay = new ActiveOverlay(nest.parser, nest.overlay, oldMounts, this.inner.length, cursor.from, cursor.tree, overlay);
|
|
1775
1866
|
}
|
|
1776
1867
|
else {
|
|
1777
|
-
let ranges = punchRanges(this.ranges, nest.overlay ||
|
|
1868
|
+
let ranges = punchRanges(this.ranges, nest.overlay ||
|
|
1869
|
+
(cursor.from < cursor.to ? [new Range(cursor.from, cursor.to)] : []));
|
|
1778
1870
|
if (ranges.length)
|
|
1779
|
-
|
|
1871
|
+
checkRanges(ranges);
|
|
1872
|
+
if (ranges.length || !nest.overlay)
|
|
1873
|
+
this.inner.push(new InnerParse(nest.parser, ranges.length ? nest.parser.startParse(this.input, enterFragments(oldMounts, ranges), ranges)
|
|
1874
|
+
: nest.parser.startParse(""), nest.overlay ? nest.overlay.map(r => new Range(r.from - cursor.from, r.to - cursor.from)) : null, cursor.tree, ranges.length ? ranges[0].from : cursor.from));
|
|
1780
1875
|
if (!nest.overlay)
|
|
1781
1876
|
enter = false;
|
|
1782
1877
|
else if (ranges.length)
|
|
@@ -1803,8 +1898,10 @@ class MixedParse {
|
|
|
1803
1898
|
break scan;
|
|
1804
1899
|
if (overlay && !--overlay.depth) {
|
|
1805
1900
|
let ranges = punchRanges(this.ranges, overlay.ranges);
|
|
1806
|
-
if (ranges.length)
|
|
1807
|
-
|
|
1901
|
+
if (ranges.length) {
|
|
1902
|
+
checkRanges(ranges);
|
|
1903
|
+
this.inner.splice(overlay.index, 0, new InnerParse(overlay.parser, overlay.parser.startParse(this.input, enterFragments(overlay.mounts, ranges), ranges), overlay.ranges.map(r => new Range(r.from - overlay.start, r.to - overlay.start)), overlay.target, ranges[0].from));
|
|
1904
|
+
}
|
|
1808
1905
|
overlay = overlay.prev;
|
|
1809
1906
|
}
|
|
1810
1907
|
if (covered && !--covered.depth)
|
|
@@ -1838,11 +1935,11 @@ function sliceBuf(buf, startI, endI, nodes, positions, off) {
|
|
|
1838
1935
|
// parse that was ran via the mix parser, and thus aren't shared with
|
|
1839
1936
|
// any other code, making violations of the immutability safe.
|
|
1840
1937
|
function materialize(cursor) {
|
|
1841
|
-
let { node } = cursor,
|
|
1938
|
+
let { node } = cursor, stack = [];
|
|
1842
1939
|
// Scan up to the nearest tree
|
|
1843
1940
|
do {
|
|
1941
|
+
stack.push(cursor.index);
|
|
1844
1942
|
cursor.parent();
|
|
1845
|
-
depth++;
|
|
1846
1943
|
} while (!cursor.tree);
|
|
1847
1944
|
// Find the index of the buffer in that tree
|
|
1848
1945
|
let i = 0, base = cursor.tree, off = 0;
|
|
@@ -1851,26 +1948,29 @@ function materialize(cursor) {
|
|
|
1851
1948
|
if (off <= node.from && off + base.children[i].length >= node.to)
|
|
1852
1949
|
break;
|
|
1853
1950
|
}
|
|
1854
|
-
let buf = base.children[i], b = buf.buffer;
|
|
1951
|
+
let buf = base.children[i], b = buf.buffer, newStack = [i];
|
|
1855
1952
|
// Split a level in the buffer, putting the nodes before and after
|
|
1856
1953
|
// the child that contains `node` into new buffers.
|
|
1857
|
-
function split(startI, endI, type, innerOffset, length) {
|
|
1858
|
-
let
|
|
1859
|
-
while (b[i + 2] + off <= node.from)
|
|
1860
|
-
i = b[i + 3];
|
|
1954
|
+
function split(startI, endI, type, innerOffset, length, stackPos) {
|
|
1955
|
+
let targetI = stack[stackPos];
|
|
1861
1956
|
let children = [], positions = [];
|
|
1862
|
-
sliceBuf(buf, startI,
|
|
1863
|
-
let from = b[
|
|
1864
|
-
|
|
1865
|
-
|
|
1957
|
+
sliceBuf(buf, startI, targetI, children, positions, innerOffset);
|
|
1958
|
+
let from = b[targetI + 1], to = b[targetI + 2];
|
|
1959
|
+
newStack.push(children.length);
|
|
1960
|
+
let child = stackPos
|
|
1961
|
+
? split(targetI + 4, b[targetI + 3], buf.set.types[b[targetI]], from, to - from, stackPos - 1)
|
|
1962
|
+
: node.toTree();
|
|
1963
|
+
children.push(child);
|
|
1866
1964
|
positions.push(from - innerOffset);
|
|
1867
|
-
sliceBuf(buf, b[
|
|
1965
|
+
sliceBuf(buf, b[targetI + 3], endI, children, positions, innerOffset);
|
|
1868
1966
|
return new Tree(type, children, positions, length);
|
|
1869
1967
|
}
|
|
1870
|
-
base.children[i] = split(0, b.length, NodeType.none, 0, buf.length);
|
|
1968
|
+
base.children[i] = split(0, b.length, NodeType.none, 0, buf.length, stack.length - 1);
|
|
1871
1969
|
// Move the cursor back to the target node
|
|
1872
|
-
for (let
|
|
1873
|
-
cursor.
|
|
1970
|
+
for (let index of newStack) {
|
|
1971
|
+
let tree = cursor.tree.children[index], pos = cursor.tree.positions[index];
|
|
1972
|
+
cursor.yield(new TreeNode(tree, pos + cursor.from, index, cursor._tree));
|
|
1973
|
+
}
|
|
1874
1974
|
}
|
|
1875
1975
|
class StructureCursor {
|
|
1876
1976
|
constructor(root, offset) {
|