@lezer/common 0.15.12 → 0.16.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/dist/index.cjs +198 -68
- package/dist/index.d.ts +1 -1
- package/dist/index.js +198 -69
- package/dist/mix.d.ts +3 -3
- package/dist/tree.d.ts +48 -29
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -214,6 +214,28 @@ class NodeSet {
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
const CachedNode = new WeakMap(), CachedInnerNode = new WeakMap();
|
|
217
|
+
/// Options that control iteration. Can be combined with the `|`
|
|
218
|
+
/// operator to enable multiple ones.
|
|
219
|
+
exports.IterMode = void 0;
|
|
220
|
+
(function (IterMode) {
|
|
221
|
+
/// When enabled, iteration will only visit [`Tree`](#common.Tree)
|
|
222
|
+
/// objects, not nodes packed into
|
|
223
|
+
/// [`TreeBuffer`](#common.TreeBuffer)s.
|
|
224
|
+
IterMode[IterMode["ExcludeBuffers"] = 1] = "ExcludeBuffers";
|
|
225
|
+
/// Enable this to make iteration include anonymous nodes (such as
|
|
226
|
+
/// the nodes that wrap repeated grammar constructs into a balanced
|
|
227
|
+
/// tree).
|
|
228
|
+
IterMode[IterMode["IncludeAnonymous"] = 2] = "IncludeAnonymous";
|
|
229
|
+
/// By default, regular [mounted](#common.NodeProp^mounted) nodes
|
|
230
|
+
/// replace their base node in iteration. Enable this to ignore them
|
|
231
|
+
/// instead.
|
|
232
|
+
IterMode[IterMode["IgnoreMounts"] = 4] = "IgnoreMounts";
|
|
233
|
+
/// This option only applies in
|
|
234
|
+
/// [`enter`](#common.SyntaxNode.enter)-style methods. It tells the
|
|
235
|
+
/// library to not enter mounted overlays if one covers the given
|
|
236
|
+
/// position.
|
|
237
|
+
IterMode[IterMode["IgnoreOverlays"] = 8] = "IgnoreOverlays";
|
|
238
|
+
})(exports.IterMode || (exports.IterMode = {}));
|
|
217
239
|
/// A piece of syntax tree. There are two ways to approach these
|
|
218
240
|
/// trees: the way they are actually stored in memory, and the
|
|
219
241
|
/// convenient way.
|
|
@@ -272,25 +294,22 @@ class Tree {
|
|
|
272
294
|
(/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) +
|
|
273
295
|
(children.length ? "(" + children + ")" : "");
|
|
274
296
|
}
|
|
275
|
-
/// Get a [tree cursor](#common.TreeCursor)
|
|
276
|
-
///
|
|
277
|
-
///
|
|
278
|
-
cursor(
|
|
279
|
-
|
|
297
|
+
/// Get a [tree cursor](#common.TreeCursor) positioned at the top of
|
|
298
|
+
/// the tree. Mode can be used to [control](#common.IterMode) which
|
|
299
|
+
/// nodes the cursor visits.
|
|
300
|
+
cursor(mode = 0) {
|
|
301
|
+
return new TreeCursor(this.topNode, mode);
|
|
302
|
+
}
|
|
303
|
+
/// Get a [tree cursor](#common.TreeCursor) pointing into this tree
|
|
304
|
+
/// at the given position and side (see
|
|
305
|
+
/// [`moveTo`](#common.TreeCursor.moveTo).
|
|
306
|
+
cursorAt(pos, side = 0, mode = 0) {
|
|
307
|
+
let scope = CachedNode.get(this) || this.topNode;
|
|
280
308
|
let cursor = new TreeCursor(scope);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
CachedNode.set(this, cursor._tree);
|
|
284
|
-
}
|
|
309
|
+
cursor.moveTo(pos, side);
|
|
310
|
+
CachedNode.set(this, cursor._tree);
|
|
285
311
|
return cursor;
|
|
286
312
|
}
|
|
287
|
-
/// Get a [tree cursor](#common.TreeCursor) that, unlike regular
|
|
288
|
-
/// cursors, doesn't skip through
|
|
289
|
-
/// [anonymous](#common.NodeType.isAnonymous) nodes and doesn't
|
|
290
|
-
/// automatically enter mounted nodes.
|
|
291
|
-
fullCursor() {
|
|
292
|
-
return new TreeCursor(this.topNode, 1 /* Full */);
|
|
293
|
-
}
|
|
294
313
|
/// Get a [syntax node](#common.SyntaxNode) object for the top of the
|
|
295
314
|
/// tree.
|
|
296
315
|
get topNode() {
|
|
@@ -323,23 +342,21 @@ class Tree {
|
|
|
323
342
|
/// not have its children iterated over (or `leave` called).
|
|
324
343
|
iterate(spec) {
|
|
325
344
|
let { enter, leave, from = 0, to = this.length } = spec;
|
|
326
|
-
for (let c = this.cursor(
|
|
327
|
-
let
|
|
328
|
-
if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c
|
|
345
|
+
for (let c = this.cursor((spec.mode || 0) | exports.IterMode.IncludeAnonymous);;) {
|
|
346
|
+
let entered = false;
|
|
347
|
+
if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c) !== false)) {
|
|
329
348
|
if (c.firstChild())
|
|
330
349
|
continue;
|
|
331
|
-
|
|
332
|
-
mustLeave = true;
|
|
350
|
+
entered = true;
|
|
333
351
|
}
|
|
334
352
|
for (;;) {
|
|
335
|
-
if (
|
|
336
|
-
leave(c
|
|
337
|
-
mustLeave = c.type.isAnonymous;
|
|
353
|
+
if (entered && leave && !c.type.isAnonymous)
|
|
354
|
+
leave(c);
|
|
338
355
|
if (c.nextSibling())
|
|
339
356
|
break;
|
|
340
357
|
if (!c.parent())
|
|
341
358
|
return;
|
|
342
|
-
|
|
359
|
+
entered = true;
|
|
343
360
|
}
|
|
344
361
|
}
|
|
345
362
|
}
|
|
@@ -490,72 +507,73 @@ function resolveNode(node, pos, side, overlays) {
|
|
|
490
507
|
return node;
|
|
491
508
|
node = parent;
|
|
492
509
|
}
|
|
510
|
+
let mode = overlays ? 0 : exports.IterMode.IgnoreOverlays;
|
|
493
511
|
// Must go up out of overlays when those do not overlap with pos
|
|
494
512
|
if (overlays)
|
|
495
513
|
for (let scan = node, parent = scan.parent; parent; scan = parent, parent = scan.parent) {
|
|
496
|
-
if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side,
|
|
514
|
+
if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side, mode)) === null || _a === void 0 ? void 0 : _a.from) != scan.from)
|
|
497
515
|
node = parent;
|
|
498
516
|
}
|
|
499
517
|
for (;;) {
|
|
500
|
-
let inner = node.enter(pos, side,
|
|
518
|
+
let inner = node.enter(pos, side, mode);
|
|
501
519
|
if (!inner)
|
|
502
520
|
return node;
|
|
503
521
|
node = inner;
|
|
504
522
|
}
|
|
505
523
|
}
|
|
506
524
|
class TreeNode {
|
|
507
|
-
constructor(
|
|
525
|
+
constructor(_tree, from,
|
|
508
526
|
// Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
|
|
509
527
|
index, _parent) {
|
|
510
|
-
this.
|
|
511
|
-
this.
|
|
528
|
+
this._tree = _tree;
|
|
529
|
+
this.from = from;
|
|
512
530
|
this.index = index;
|
|
513
531
|
this._parent = _parent;
|
|
514
532
|
}
|
|
515
|
-
get type() { return this.
|
|
516
|
-
get name() { return this.
|
|
517
|
-
get
|
|
518
|
-
get to() { return this._from + this.node.length; }
|
|
533
|
+
get type() { return this._tree.type; }
|
|
534
|
+
get name() { return this._tree.type.name; }
|
|
535
|
+
get to() { return this.from + this._tree.length; }
|
|
519
536
|
nextChild(i, dir, pos, side, mode = 0) {
|
|
520
537
|
for (let parent = this;;) {
|
|
521
|
-
for (let { children, positions } = parent.
|
|
522
|
-
let next = children[i], start = positions[i] + parent.
|
|
538
|
+
for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) {
|
|
539
|
+
let next = children[i], start = positions[i] + parent.from;
|
|
523
540
|
if (!checkSide(side, pos, start, start + next.length))
|
|
524
541
|
continue;
|
|
525
542
|
if (next instanceof TreeBuffer) {
|
|
526
|
-
if (mode &
|
|
543
|
+
if (mode & exports.IterMode.ExcludeBuffers)
|
|
527
544
|
continue;
|
|
528
545
|
let index = next.findChild(0, next.buffer.length, dir, pos - start, side);
|
|
529
546
|
if (index > -1)
|
|
530
547
|
return new BufferNode(new BufferContext(parent, next, i, start), null, index);
|
|
531
548
|
}
|
|
532
|
-
else if ((mode &
|
|
549
|
+
else if ((mode & exports.IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
|
|
533
550
|
let mounted;
|
|
534
|
-
if (!(mode &
|
|
551
|
+
if (!(mode & exports.IterMode.IgnoreMounts) &&
|
|
552
|
+
next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
|
|
535
553
|
return new TreeNode(mounted.tree, start, i, parent);
|
|
536
554
|
let inner = new TreeNode(next, start, i, parent);
|
|
537
|
-
return (mode &
|
|
555
|
+
return (mode & exports.IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
|
|
538
556
|
: inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side);
|
|
539
557
|
}
|
|
540
558
|
}
|
|
541
|
-
if ((mode &
|
|
559
|
+
if ((mode & exports.IterMode.IncludeAnonymous) || !parent.type.isAnonymous)
|
|
542
560
|
return null;
|
|
543
561
|
if (parent.index >= 0)
|
|
544
562
|
i = parent.index + dir;
|
|
545
563
|
else
|
|
546
|
-
i = dir < 0 ? -1 : parent._parent.
|
|
564
|
+
i = dir < 0 ? -1 : parent._parent._tree.children.length;
|
|
547
565
|
parent = parent._parent;
|
|
548
566
|
if (!parent)
|
|
549
567
|
return null;
|
|
550
568
|
}
|
|
551
569
|
}
|
|
552
570
|
get firstChild() { return this.nextChild(0, 1, 0, 4 /* DontCare */); }
|
|
553
|
-
get lastChild() { return this.nextChild(this.
|
|
571
|
+
get lastChild() { return this.nextChild(this._tree.children.length - 1, -1, 0, 4 /* DontCare */); }
|
|
554
572
|
childAfter(pos) { return this.nextChild(0, 1, pos, 2 /* After */); }
|
|
555
|
-
childBefore(pos) { return this.nextChild(this.
|
|
556
|
-
enter(pos, side,
|
|
573
|
+
childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Before */); }
|
|
574
|
+
enter(pos, side, mode = 0) {
|
|
557
575
|
let mounted;
|
|
558
|
-
if (
|
|
576
|
+
if (!(mode & exports.IterMode.IgnoreOverlays) && (mounted = this._tree.prop(NodeProp.mounted)) && mounted.overlay) {
|
|
559
577
|
let rPos = pos - this.from;
|
|
560
578
|
for (let { from, to } of mounted.overlay) {
|
|
561
579
|
if ((side > 0 ? from <= rPos : from < rPos) &&
|
|
@@ -563,7 +581,7 @@ class TreeNode {
|
|
|
563
581
|
return new TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this);
|
|
564
582
|
}
|
|
565
583
|
}
|
|
566
|
-
return this.nextChild(0, 1, pos, side,
|
|
584
|
+
return this.nextChild(0, 1, pos, side, mode);
|
|
567
585
|
}
|
|
568
586
|
nextSignificantParent() {
|
|
569
587
|
let val = this;
|
|
@@ -580,9 +598,9 @@ class TreeNode {
|
|
|
580
598
|
get prevSibling() {
|
|
581
599
|
return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* DontCare */) : null;
|
|
582
600
|
}
|
|
583
|
-
|
|
584
|
-
get tree() { return this.
|
|
585
|
-
toTree() { return this.
|
|
601
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
602
|
+
get tree() { return this._tree; }
|
|
603
|
+
toTree() { return this._tree; }
|
|
586
604
|
resolve(pos, side = 0) {
|
|
587
605
|
return resolveNode(this, pos, side, false);
|
|
588
606
|
}
|
|
@@ -598,10 +616,12 @@ class TreeNode {
|
|
|
598
616
|
return getChildren(this, type, before, after);
|
|
599
617
|
}
|
|
600
618
|
/// @internal
|
|
601
|
-
toString() { return this.
|
|
619
|
+
toString() { return this._tree.toString(); }
|
|
620
|
+
get node() { return this; }
|
|
621
|
+
matchContext(context) { return matchNodeContext(this, context); }
|
|
602
622
|
}
|
|
603
623
|
function getChildren(node, type, before, after) {
|
|
604
|
-
let cur = node.cursor, result = [];
|
|
624
|
+
let cur = node.cursor(), result = [];
|
|
605
625
|
if (!cur.firstChild())
|
|
606
626
|
return result;
|
|
607
627
|
if (before != null)
|
|
@@ -617,6 +637,18 @@ function getChildren(node, type, before, after) {
|
|
|
617
637
|
return after == null ? result : [];
|
|
618
638
|
}
|
|
619
639
|
}
|
|
640
|
+
function matchNodeContext(node, context, i = context.length - 1) {
|
|
641
|
+
for (let p = node.parent; i >= 0; p = p.parent) {
|
|
642
|
+
if (!p)
|
|
643
|
+
return false;
|
|
644
|
+
if (!p.type.isAnonymous) {
|
|
645
|
+
if (context[i] && context[i] != p.name)
|
|
646
|
+
return false;
|
|
647
|
+
i--;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return true;
|
|
651
|
+
}
|
|
620
652
|
class BufferContext {
|
|
621
653
|
constructor(parent, buffer, index, start) {
|
|
622
654
|
this.parent = parent;
|
|
@@ -644,8 +676,8 @@ class BufferNode {
|
|
|
644
676
|
get lastChild() { return this.child(-1, 0, 4 /* DontCare */); }
|
|
645
677
|
childAfter(pos) { return this.child(1, pos, 2 /* After */); }
|
|
646
678
|
childBefore(pos) { return this.child(-1, pos, -2 /* Before */); }
|
|
647
|
-
enter(pos, side,
|
|
648
|
-
if (
|
|
679
|
+
enter(pos, side, mode = 0) {
|
|
680
|
+
if (mode & exports.IterMode.ExcludeBuffers)
|
|
649
681
|
return null;
|
|
650
682
|
let { buffer } = this.context;
|
|
651
683
|
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side);
|
|
@@ -671,7 +703,7 @@ class BufferNode {
|
|
|
671
703
|
return this.externalSibling(-1);
|
|
672
704
|
return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* DontCare */));
|
|
673
705
|
}
|
|
674
|
-
|
|
706
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
675
707
|
get tree() { return null; }
|
|
676
708
|
toTree() {
|
|
677
709
|
let children = [], positions = [];
|
|
@@ -700,6 +732,8 @@ class BufferNode {
|
|
|
700
732
|
getChildren(type, before = null, after = null) {
|
|
701
733
|
return getChildren(this, type, before, after);
|
|
702
734
|
}
|
|
735
|
+
get node() { return this; }
|
|
736
|
+
matchContext(context) { return matchNodeContext(this, context); }
|
|
703
737
|
}
|
|
704
738
|
/// A tree cursor object focuses on a given node in a syntax tree, and
|
|
705
739
|
/// allows you to move to adjacent nodes.
|
|
@@ -709,8 +743,10 @@ class TreeCursor {
|
|
|
709
743
|
/// @internal
|
|
710
744
|
mode = 0) {
|
|
711
745
|
this.mode = mode;
|
|
746
|
+
/// @internal
|
|
712
747
|
this.buffer = null;
|
|
713
748
|
this.stack = [];
|
|
749
|
+
/// @internal
|
|
714
750
|
this.index = 0;
|
|
715
751
|
this.bufferNode = null;
|
|
716
752
|
if (node instanceof TreeNode) {
|
|
@@ -761,7 +797,7 @@ class TreeCursor {
|
|
|
761
797
|
/// @internal
|
|
762
798
|
enterChild(dir, pos, side) {
|
|
763
799
|
if (!this.buffer)
|
|
764
|
-
return this.yield(this._tree.nextChild(dir < 0 ? this._tree.
|
|
800
|
+
return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode));
|
|
765
801
|
let { buffer } = this.buffer;
|
|
766
802
|
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.buffer.start, side);
|
|
767
803
|
if (index < 0)
|
|
@@ -783,18 +819,18 @@ class TreeCursor {
|
|
|
783
819
|
/// will also enter [overlaid](#common.MountedTree.overlay)
|
|
784
820
|
/// [mounted](#common.NodeProp^mounted) trees unless `overlays` is
|
|
785
821
|
/// set to false.
|
|
786
|
-
enter(pos, side,
|
|
822
|
+
enter(pos, side, mode = this.mode) {
|
|
787
823
|
if (!this.buffer)
|
|
788
|
-
return this.yield(this._tree.enter(pos, side,
|
|
789
|
-
return
|
|
824
|
+
return this.yield(this._tree.enter(pos, side, mode));
|
|
825
|
+
return mode & exports.IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side);
|
|
790
826
|
}
|
|
791
827
|
/// Move to the node's parent node, if this isn't the top node.
|
|
792
828
|
parent() {
|
|
793
829
|
if (!this.buffer)
|
|
794
|
-
return this.yieldNode((this.mode &
|
|
830
|
+
return this.yieldNode((this.mode & exports.IterMode.IncludeAnonymous) ? this._tree._parent : this._tree.parent);
|
|
795
831
|
if (this.stack.length)
|
|
796
832
|
return this.yieldBuf(this.stack.pop());
|
|
797
|
-
let parent = (this.mode &
|
|
833
|
+
let parent = (this.mode & exports.IterMode.IncludeAnonymous) ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
|
|
798
834
|
this.buffer = null;
|
|
799
835
|
return this.yieldNode(parent);
|
|
800
836
|
}
|
|
@@ -840,9 +876,12 @@ class TreeCursor {
|
|
|
840
876
|
}
|
|
841
877
|
for (; parent; { index, _parent: parent } = parent) {
|
|
842
878
|
if (index > -1)
|
|
843
|
-
for (let i = index + dir, e = dir < 0 ? -1 : parent.
|
|
844
|
-
let child = parent.
|
|
845
|
-
if ((this.mode &
|
|
879
|
+
for (let i = index + dir, e = dir < 0 ? -1 : parent._tree.children.length; i != e; i += dir) {
|
|
880
|
+
let child = parent._tree.children[i];
|
|
881
|
+
if ((this.mode & exports.IterMode.IncludeAnonymous) ||
|
|
882
|
+
child instanceof TreeBuffer ||
|
|
883
|
+
!child.type.isAnonymous ||
|
|
884
|
+
hasChild(child))
|
|
846
885
|
return false;
|
|
847
886
|
}
|
|
848
887
|
}
|
|
@@ -910,7 +949,55 @@ class TreeCursor {
|
|
|
910
949
|
/// any. Will return null when the node is in a [tree
|
|
911
950
|
/// buffer](#common.TreeBuffer).
|
|
912
951
|
get tree() {
|
|
913
|
-
return this.buffer ? null : this._tree.
|
|
952
|
+
return this.buffer ? null : this._tree._tree;
|
|
953
|
+
}
|
|
954
|
+
/// Iterate over the current node and all its descendants, calling
|
|
955
|
+
/// `enter` when entering a node and `leave`, if given, when leaving
|
|
956
|
+
/// one. When `enter` returns `false`, any children of that node are
|
|
957
|
+
/// skipped, and `leave` isn't called for it.
|
|
958
|
+
iterate(enter, leave) {
|
|
959
|
+
for (let depth = 0;;) {
|
|
960
|
+
let mustLeave = false;
|
|
961
|
+
if (this.type.isAnonymous || enter(this) !== false) {
|
|
962
|
+
if (this.firstChild()) {
|
|
963
|
+
depth++;
|
|
964
|
+
continue;
|
|
965
|
+
}
|
|
966
|
+
if (!this.type.isAnonymous)
|
|
967
|
+
mustLeave = true;
|
|
968
|
+
}
|
|
969
|
+
for (;;) {
|
|
970
|
+
if (mustLeave && leave)
|
|
971
|
+
leave(this);
|
|
972
|
+
mustLeave = this.type.isAnonymous;
|
|
973
|
+
if (this.nextSibling())
|
|
974
|
+
break;
|
|
975
|
+
if (!depth)
|
|
976
|
+
return;
|
|
977
|
+
this.parent();
|
|
978
|
+
depth--;
|
|
979
|
+
mustLeave = true;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
/// Test whether the current node matches a given context—a sequence
|
|
984
|
+
/// of direct parent node names. Empty strings in the context array
|
|
985
|
+
/// are treated as wildcards.
|
|
986
|
+
matchContext(context) {
|
|
987
|
+
if (!this.buffer)
|
|
988
|
+
return matchNodeContext(this.node, context);
|
|
989
|
+
let { buffer } = this.buffer, { types } = buffer.set;
|
|
990
|
+
for (let i = context.length - 1, d = this.stack.length - 1; i >= 0; d--) {
|
|
991
|
+
if (d < 0)
|
|
992
|
+
return matchNodeContext(this.node, context, i);
|
|
993
|
+
let type = types[buffer.buffer[this.stack[d]]];
|
|
994
|
+
if (!type.isAnonymous) {
|
|
995
|
+
if (context[i] && context[i] != type.name)
|
|
996
|
+
return false;
|
|
997
|
+
i--;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
return true;
|
|
914
1001
|
}
|
|
915
1002
|
}
|
|
916
1003
|
function hasChild(tree) {
|
|
@@ -1170,6 +1257,48 @@ mkTree) {
|
|
|
1170
1257
|
divide(children, positions, from, to, 0);
|
|
1171
1258
|
return (mkTop || mkTree)(localChildren, localPositions, length);
|
|
1172
1259
|
}
|
|
1260
|
+
/// Provides a way to associate values with pieces of trees. As long
|
|
1261
|
+
/// as that part of the tree is reused, the associated values can be
|
|
1262
|
+
/// retrieved from an updated tree.
|
|
1263
|
+
class NodeWeakMap {
|
|
1264
|
+
constructor() {
|
|
1265
|
+
this.map = new WeakMap();
|
|
1266
|
+
}
|
|
1267
|
+
setBuffer(buffer, index, value) {
|
|
1268
|
+
let inner = this.map.get(buffer);
|
|
1269
|
+
if (!inner)
|
|
1270
|
+
this.map.set(buffer, inner = new Map);
|
|
1271
|
+
inner.set(index, value);
|
|
1272
|
+
}
|
|
1273
|
+
getBuffer(buffer, index) {
|
|
1274
|
+
let inner = this.map.get(buffer);
|
|
1275
|
+
return inner && inner.get(index);
|
|
1276
|
+
}
|
|
1277
|
+
/// Set the value for this syntax node.
|
|
1278
|
+
set(node, value) {
|
|
1279
|
+
if (node instanceof BufferNode)
|
|
1280
|
+
this.setBuffer(node.context.buffer, node.index, value);
|
|
1281
|
+
else if (node instanceof TreeNode)
|
|
1282
|
+
this.map.set(node.tree, value);
|
|
1283
|
+
}
|
|
1284
|
+
/// Retrieve value for this syntax node, if it exists in the map.
|
|
1285
|
+
get(node) {
|
|
1286
|
+
return node instanceof BufferNode ? this.getBuffer(node.context.buffer, node.index)
|
|
1287
|
+
: node instanceof TreeNode ? this.map.get(node.tree) : undefined;
|
|
1288
|
+
}
|
|
1289
|
+
/// Set the value for the node that a cursor currently points to.
|
|
1290
|
+
cursorSet(cursor, value) {
|
|
1291
|
+
if (cursor.buffer)
|
|
1292
|
+
this.setBuffer(cursor.buffer.buffer, cursor.index, value);
|
|
1293
|
+
else
|
|
1294
|
+
this.map.set(cursor.tree, value);
|
|
1295
|
+
}
|
|
1296
|
+
/// Retrieve the value for the node that a cursor currently points
|
|
1297
|
+
/// to.
|
|
1298
|
+
cursorGet(cursor) {
|
|
1299
|
+
return cursor.buffer ? this.getBuffer(cursor.buffer.buffer, cursor.index) : this.map.get(cursor.tree);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1173
1302
|
|
|
1174
1303
|
/// Tree fragments are used during [incremental
|
|
1175
1304
|
/// parsing](#common.Parser.startParse) to track parts of old trees
|
|
@@ -1390,7 +1519,7 @@ class MixedParse {
|
|
|
1390
1519
|
let fragmentCursor = new FragmentCursor(this.fragments);
|
|
1391
1520
|
let overlay = null;
|
|
1392
1521
|
let covered = null;
|
|
1393
|
-
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null),
|
|
1522
|
+
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), exports.IterMode.IncludeAnonymous | exports.IterMode.IgnoreMounts);
|
|
1394
1523
|
scan: for (let nest, isCovered; this.stoppedAt == null || cursor.from < this.stoppedAt;) {
|
|
1395
1524
|
let enter = true, range;
|
|
1396
1525
|
if (fragmentCursor.hasNode(cursor)) {
|
|
@@ -1518,13 +1647,13 @@ class StructureCursor {
|
|
|
1518
1647
|
constructor(root, offset) {
|
|
1519
1648
|
this.offset = offset;
|
|
1520
1649
|
this.done = false;
|
|
1521
|
-
this.cursor = root.
|
|
1650
|
+
this.cursor = root.cursor(exports.IterMode.IncludeAnonymous | exports.IterMode.IgnoreMounts);
|
|
1522
1651
|
}
|
|
1523
1652
|
// Move to the first node (in pre-order) that starts at or after `pos`.
|
|
1524
1653
|
moveTo(pos) {
|
|
1525
1654
|
let { cursor } = this, p = pos - this.offset;
|
|
1526
1655
|
while (!this.done && cursor.from < p) {
|
|
1527
|
-
if (cursor.to >= pos && cursor.enter(p, 1,
|
|
1656
|
+
if (cursor.to >= pos && cursor.enter(p, 1, exports.IterMode.IgnoreOverlays | exports.IterMode.ExcludeBuffers)) ;
|
|
1528
1657
|
else if (!cursor.next(false))
|
|
1529
1658
|
this.done = true;
|
|
1530
1659
|
}
|
|
@@ -1693,6 +1822,7 @@ exports.MountedTree = MountedTree;
|
|
|
1693
1822
|
exports.NodeProp = NodeProp;
|
|
1694
1823
|
exports.NodeSet = NodeSet;
|
|
1695
1824
|
exports.NodeType = NodeType;
|
|
1825
|
+
exports.NodeWeakMap = NodeWeakMap;
|
|
1696
1826
|
exports.Parser = Parser;
|
|
1697
1827
|
exports.Tree = Tree;
|
|
1698
1828
|
exports.TreeBuffer = TreeBuffer;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { DefaultBufferLength, NodeProp, MountedTree, NodePropSource, NodeType, NodeSet, Tree, TreeBuffer, SyntaxNode, TreeCursor, BufferCursor } from "./tree";
|
|
1
|
+
export { DefaultBufferLength, NodeProp, MountedTree, NodePropSource, NodeType, NodeSet, Tree, TreeBuffer, SyntaxNode, SyntaxNodeRef, TreeCursor, BufferCursor, NodeWeakMap, IterMode } from "./tree";
|
|
2
2
|
export { ChangedRange, TreeFragment, PartialParse, Parser, Input, ParseWrapper } from "./parse";
|
|
3
3
|
export { NestedParse, parseMixed } from "./mix";
|
package/dist/index.js
CHANGED
|
@@ -210,6 +210,28 @@ class NodeSet {
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
const CachedNode = new WeakMap(), CachedInnerNode = new WeakMap();
|
|
213
|
+
/// Options that control iteration. Can be combined with the `|`
|
|
214
|
+
/// operator to enable multiple ones.
|
|
215
|
+
var IterMode;
|
|
216
|
+
(function (IterMode) {
|
|
217
|
+
/// When enabled, iteration will only visit [`Tree`](#common.Tree)
|
|
218
|
+
/// objects, not nodes packed into
|
|
219
|
+
/// [`TreeBuffer`](#common.TreeBuffer)s.
|
|
220
|
+
IterMode[IterMode["ExcludeBuffers"] = 1] = "ExcludeBuffers";
|
|
221
|
+
/// Enable this to make iteration include anonymous nodes (such as
|
|
222
|
+
/// the nodes that wrap repeated grammar constructs into a balanced
|
|
223
|
+
/// tree).
|
|
224
|
+
IterMode[IterMode["IncludeAnonymous"] = 2] = "IncludeAnonymous";
|
|
225
|
+
/// By default, regular [mounted](#common.NodeProp^mounted) nodes
|
|
226
|
+
/// replace their base node in iteration. Enable this to ignore them
|
|
227
|
+
/// instead.
|
|
228
|
+
IterMode[IterMode["IgnoreMounts"] = 4] = "IgnoreMounts";
|
|
229
|
+
/// This option only applies in
|
|
230
|
+
/// [`enter`](#common.SyntaxNode.enter)-style methods. It tells the
|
|
231
|
+
/// library to not enter mounted overlays if one covers the given
|
|
232
|
+
/// position.
|
|
233
|
+
IterMode[IterMode["IgnoreOverlays"] = 8] = "IgnoreOverlays";
|
|
234
|
+
})(IterMode || (IterMode = {}));
|
|
213
235
|
/// A piece of syntax tree. There are two ways to approach these
|
|
214
236
|
/// trees: the way they are actually stored in memory, and the
|
|
215
237
|
/// convenient way.
|
|
@@ -268,25 +290,22 @@ class Tree {
|
|
|
268
290
|
(/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) +
|
|
269
291
|
(children.length ? "(" + children + ")" : "");
|
|
270
292
|
}
|
|
271
|
-
/// Get a [tree cursor](#common.TreeCursor)
|
|
272
|
-
///
|
|
273
|
-
///
|
|
274
|
-
cursor(
|
|
275
|
-
|
|
293
|
+
/// Get a [tree cursor](#common.TreeCursor) positioned at the top of
|
|
294
|
+
/// the tree. Mode can be used to [control](#common.IterMode) which
|
|
295
|
+
/// nodes the cursor visits.
|
|
296
|
+
cursor(mode = 0) {
|
|
297
|
+
return new TreeCursor(this.topNode, mode);
|
|
298
|
+
}
|
|
299
|
+
/// Get a [tree cursor](#common.TreeCursor) pointing into this tree
|
|
300
|
+
/// at the given position and side (see
|
|
301
|
+
/// [`moveTo`](#common.TreeCursor.moveTo).
|
|
302
|
+
cursorAt(pos, side = 0, mode = 0) {
|
|
303
|
+
let scope = CachedNode.get(this) || this.topNode;
|
|
276
304
|
let cursor = new TreeCursor(scope);
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
CachedNode.set(this, cursor._tree);
|
|
280
|
-
}
|
|
305
|
+
cursor.moveTo(pos, side);
|
|
306
|
+
CachedNode.set(this, cursor._tree);
|
|
281
307
|
return cursor;
|
|
282
308
|
}
|
|
283
|
-
/// Get a [tree cursor](#common.TreeCursor) that, unlike regular
|
|
284
|
-
/// cursors, doesn't skip through
|
|
285
|
-
/// [anonymous](#common.NodeType.isAnonymous) nodes and doesn't
|
|
286
|
-
/// automatically enter mounted nodes.
|
|
287
|
-
fullCursor() {
|
|
288
|
-
return new TreeCursor(this.topNode, 1 /* Full */);
|
|
289
|
-
}
|
|
290
309
|
/// Get a [syntax node](#common.SyntaxNode) object for the top of the
|
|
291
310
|
/// tree.
|
|
292
311
|
get topNode() {
|
|
@@ -319,23 +338,21 @@ class Tree {
|
|
|
319
338
|
/// not have its children iterated over (or `leave` called).
|
|
320
339
|
iterate(spec) {
|
|
321
340
|
let { enter, leave, from = 0, to = this.length } = spec;
|
|
322
|
-
for (let c = this.cursor(
|
|
323
|
-
let
|
|
324
|
-
if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c
|
|
341
|
+
for (let c = this.cursor((spec.mode || 0) | IterMode.IncludeAnonymous);;) {
|
|
342
|
+
let entered = false;
|
|
343
|
+
if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c) !== false)) {
|
|
325
344
|
if (c.firstChild())
|
|
326
345
|
continue;
|
|
327
|
-
|
|
328
|
-
mustLeave = true;
|
|
346
|
+
entered = true;
|
|
329
347
|
}
|
|
330
348
|
for (;;) {
|
|
331
|
-
if (
|
|
332
|
-
leave(c
|
|
333
|
-
mustLeave = c.type.isAnonymous;
|
|
349
|
+
if (entered && leave && !c.type.isAnonymous)
|
|
350
|
+
leave(c);
|
|
334
351
|
if (c.nextSibling())
|
|
335
352
|
break;
|
|
336
353
|
if (!c.parent())
|
|
337
354
|
return;
|
|
338
|
-
|
|
355
|
+
entered = true;
|
|
339
356
|
}
|
|
340
357
|
}
|
|
341
358
|
}
|
|
@@ -486,72 +503,73 @@ function resolveNode(node, pos, side, overlays) {
|
|
|
486
503
|
return node;
|
|
487
504
|
node = parent;
|
|
488
505
|
}
|
|
506
|
+
let mode = overlays ? 0 : IterMode.IgnoreOverlays;
|
|
489
507
|
// Must go up out of overlays when those do not overlap with pos
|
|
490
508
|
if (overlays)
|
|
491
509
|
for (let scan = node, parent = scan.parent; parent; scan = parent, parent = scan.parent) {
|
|
492
|
-
if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side,
|
|
510
|
+
if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side, mode)) === null || _a === void 0 ? void 0 : _a.from) != scan.from)
|
|
493
511
|
node = parent;
|
|
494
512
|
}
|
|
495
513
|
for (;;) {
|
|
496
|
-
let inner = node.enter(pos, side,
|
|
514
|
+
let inner = node.enter(pos, side, mode);
|
|
497
515
|
if (!inner)
|
|
498
516
|
return node;
|
|
499
517
|
node = inner;
|
|
500
518
|
}
|
|
501
519
|
}
|
|
502
520
|
class TreeNode {
|
|
503
|
-
constructor(
|
|
521
|
+
constructor(_tree, from,
|
|
504
522
|
// Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
|
|
505
523
|
index, _parent) {
|
|
506
|
-
this.
|
|
507
|
-
this.
|
|
524
|
+
this._tree = _tree;
|
|
525
|
+
this.from = from;
|
|
508
526
|
this.index = index;
|
|
509
527
|
this._parent = _parent;
|
|
510
528
|
}
|
|
511
|
-
get type() { return this.
|
|
512
|
-
get name() { return this.
|
|
513
|
-
get
|
|
514
|
-
get to() { return this._from + this.node.length; }
|
|
529
|
+
get type() { return this._tree.type; }
|
|
530
|
+
get name() { return this._tree.type.name; }
|
|
531
|
+
get to() { return this.from + this._tree.length; }
|
|
515
532
|
nextChild(i, dir, pos, side, mode = 0) {
|
|
516
533
|
for (let parent = this;;) {
|
|
517
|
-
for (let { children, positions } = parent.
|
|
518
|
-
let next = children[i], start = positions[i] + parent.
|
|
534
|
+
for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) {
|
|
535
|
+
let next = children[i], start = positions[i] + parent.from;
|
|
519
536
|
if (!checkSide(side, pos, start, start + next.length))
|
|
520
537
|
continue;
|
|
521
538
|
if (next instanceof TreeBuffer) {
|
|
522
|
-
if (mode &
|
|
539
|
+
if (mode & IterMode.ExcludeBuffers)
|
|
523
540
|
continue;
|
|
524
541
|
let index = next.findChild(0, next.buffer.length, dir, pos - start, side);
|
|
525
542
|
if (index > -1)
|
|
526
543
|
return new BufferNode(new BufferContext(parent, next, i, start), null, index);
|
|
527
544
|
}
|
|
528
|
-
else if ((mode &
|
|
545
|
+
else if ((mode & IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
|
|
529
546
|
let mounted;
|
|
530
|
-
if (!(mode &
|
|
547
|
+
if (!(mode & IterMode.IgnoreMounts) &&
|
|
548
|
+
next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
|
|
531
549
|
return new TreeNode(mounted.tree, start, i, parent);
|
|
532
550
|
let inner = new TreeNode(next, start, i, parent);
|
|
533
|
-
return (mode &
|
|
551
|
+
return (mode & IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
|
|
534
552
|
: inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side);
|
|
535
553
|
}
|
|
536
554
|
}
|
|
537
|
-
if ((mode &
|
|
555
|
+
if ((mode & IterMode.IncludeAnonymous) || !parent.type.isAnonymous)
|
|
538
556
|
return null;
|
|
539
557
|
if (parent.index >= 0)
|
|
540
558
|
i = parent.index + dir;
|
|
541
559
|
else
|
|
542
|
-
i = dir < 0 ? -1 : parent._parent.
|
|
560
|
+
i = dir < 0 ? -1 : parent._parent._tree.children.length;
|
|
543
561
|
parent = parent._parent;
|
|
544
562
|
if (!parent)
|
|
545
563
|
return null;
|
|
546
564
|
}
|
|
547
565
|
}
|
|
548
566
|
get firstChild() { return this.nextChild(0, 1, 0, 4 /* DontCare */); }
|
|
549
|
-
get lastChild() { return this.nextChild(this.
|
|
567
|
+
get lastChild() { return this.nextChild(this._tree.children.length - 1, -1, 0, 4 /* DontCare */); }
|
|
550
568
|
childAfter(pos) { return this.nextChild(0, 1, pos, 2 /* After */); }
|
|
551
|
-
childBefore(pos) { return this.nextChild(this.
|
|
552
|
-
enter(pos, side,
|
|
569
|
+
childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Before */); }
|
|
570
|
+
enter(pos, side, mode = 0) {
|
|
553
571
|
let mounted;
|
|
554
|
-
if (
|
|
572
|
+
if (!(mode & IterMode.IgnoreOverlays) && (mounted = this._tree.prop(NodeProp.mounted)) && mounted.overlay) {
|
|
555
573
|
let rPos = pos - this.from;
|
|
556
574
|
for (let { from, to } of mounted.overlay) {
|
|
557
575
|
if ((side > 0 ? from <= rPos : from < rPos) &&
|
|
@@ -559,7 +577,7 @@ class TreeNode {
|
|
|
559
577
|
return new TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this);
|
|
560
578
|
}
|
|
561
579
|
}
|
|
562
|
-
return this.nextChild(0, 1, pos, side,
|
|
580
|
+
return this.nextChild(0, 1, pos, side, mode);
|
|
563
581
|
}
|
|
564
582
|
nextSignificantParent() {
|
|
565
583
|
let val = this;
|
|
@@ -576,9 +594,9 @@ class TreeNode {
|
|
|
576
594
|
get prevSibling() {
|
|
577
595
|
return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* DontCare */) : null;
|
|
578
596
|
}
|
|
579
|
-
|
|
580
|
-
get tree() { return this.
|
|
581
|
-
toTree() { return this.
|
|
597
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
598
|
+
get tree() { return this._tree; }
|
|
599
|
+
toTree() { return this._tree; }
|
|
582
600
|
resolve(pos, side = 0) {
|
|
583
601
|
return resolveNode(this, pos, side, false);
|
|
584
602
|
}
|
|
@@ -594,10 +612,12 @@ class TreeNode {
|
|
|
594
612
|
return getChildren(this, type, before, after);
|
|
595
613
|
}
|
|
596
614
|
/// @internal
|
|
597
|
-
toString() { return this.
|
|
615
|
+
toString() { return this._tree.toString(); }
|
|
616
|
+
get node() { return this; }
|
|
617
|
+
matchContext(context) { return matchNodeContext(this, context); }
|
|
598
618
|
}
|
|
599
619
|
function getChildren(node, type, before, after) {
|
|
600
|
-
let cur = node.cursor, result = [];
|
|
620
|
+
let cur = node.cursor(), result = [];
|
|
601
621
|
if (!cur.firstChild())
|
|
602
622
|
return result;
|
|
603
623
|
if (before != null)
|
|
@@ -613,6 +633,18 @@ function getChildren(node, type, before, after) {
|
|
|
613
633
|
return after == null ? result : [];
|
|
614
634
|
}
|
|
615
635
|
}
|
|
636
|
+
function matchNodeContext(node, context, i = context.length - 1) {
|
|
637
|
+
for (let p = node.parent; i >= 0; p = p.parent) {
|
|
638
|
+
if (!p)
|
|
639
|
+
return false;
|
|
640
|
+
if (!p.type.isAnonymous) {
|
|
641
|
+
if (context[i] && context[i] != p.name)
|
|
642
|
+
return false;
|
|
643
|
+
i--;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return true;
|
|
647
|
+
}
|
|
616
648
|
class BufferContext {
|
|
617
649
|
constructor(parent, buffer, index, start) {
|
|
618
650
|
this.parent = parent;
|
|
@@ -640,8 +672,8 @@ class BufferNode {
|
|
|
640
672
|
get lastChild() { return this.child(-1, 0, 4 /* DontCare */); }
|
|
641
673
|
childAfter(pos) { return this.child(1, pos, 2 /* After */); }
|
|
642
674
|
childBefore(pos) { return this.child(-1, pos, -2 /* Before */); }
|
|
643
|
-
enter(pos, side,
|
|
644
|
-
if (
|
|
675
|
+
enter(pos, side, mode = 0) {
|
|
676
|
+
if (mode & IterMode.ExcludeBuffers)
|
|
645
677
|
return null;
|
|
646
678
|
let { buffer } = this.context;
|
|
647
679
|
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side);
|
|
@@ -667,7 +699,7 @@ class BufferNode {
|
|
|
667
699
|
return this.externalSibling(-1);
|
|
668
700
|
return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* DontCare */));
|
|
669
701
|
}
|
|
670
|
-
|
|
702
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
671
703
|
get tree() { return null; }
|
|
672
704
|
toTree() {
|
|
673
705
|
let children = [], positions = [];
|
|
@@ -696,6 +728,8 @@ class BufferNode {
|
|
|
696
728
|
getChildren(type, before = null, after = null) {
|
|
697
729
|
return getChildren(this, type, before, after);
|
|
698
730
|
}
|
|
731
|
+
get node() { return this; }
|
|
732
|
+
matchContext(context) { return matchNodeContext(this, context); }
|
|
699
733
|
}
|
|
700
734
|
/// A tree cursor object focuses on a given node in a syntax tree, and
|
|
701
735
|
/// allows you to move to adjacent nodes.
|
|
@@ -705,8 +739,10 @@ class TreeCursor {
|
|
|
705
739
|
/// @internal
|
|
706
740
|
mode = 0) {
|
|
707
741
|
this.mode = mode;
|
|
742
|
+
/// @internal
|
|
708
743
|
this.buffer = null;
|
|
709
744
|
this.stack = [];
|
|
745
|
+
/// @internal
|
|
710
746
|
this.index = 0;
|
|
711
747
|
this.bufferNode = null;
|
|
712
748
|
if (node instanceof TreeNode) {
|
|
@@ -757,7 +793,7 @@ class TreeCursor {
|
|
|
757
793
|
/// @internal
|
|
758
794
|
enterChild(dir, pos, side) {
|
|
759
795
|
if (!this.buffer)
|
|
760
|
-
return this.yield(this._tree.nextChild(dir < 0 ? this._tree.
|
|
796
|
+
return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode));
|
|
761
797
|
let { buffer } = this.buffer;
|
|
762
798
|
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.buffer.start, side);
|
|
763
799
|
if (index < 0)
|
|
@@ -779,18 +815,18 @@ class TreeCursor {
|
|
|
779
815
|
/// will also enter [overlaid](#common.MountedTree.overlay)
|
|
780
816
|
/// [mounted](#common.NodeProp^mounted) trees unless `overlays` is
|
|
781
817
|
/// set to false.
|
|
782
|
-
enter(pos, side,
|
|
818
|
+
enter(pos, side, mode = this.mode) {
|
|
783
819
|
if (!this.buffer)
|
|
784
|
-
return this.yield(this._tree.enter(pos, side,
|
|
785
|
-
return
|
|
820
|
+
return this.yield(this._tree.enter(pos, side, mode));
|
|
821
|
+
return mode & IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side);
|
|
786
822
|
}
|
|
787
823
|
/// Move to the node's parent node, if this isn't the top node.
|
|
788
824
|
parent() {
|
|
789
825
|
if (!this.buffer)
|
|
790
|
-
return this.yieldNode((this.mode &
|
|
826
|
+
return this.yieldNode((this.mode & IterMode.IncludeAnonymous) ? this._tree._parent : this._tree.parent);
|
|
791
827
|
if (this.stack.length)
|
|
792
828
|
return this.yieldBuf(this.stack.pop());
|
|
793
|
-
let parent = (this.mode &
|
|
829
|
+
let parent = (this.mode & IterMode.IncludeAnonymous) ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
|
|
794
830
|
this.buffer = null;
|
|
795
831
|
return this.yieldNode(parent);
|
|
796
832
|
}
|
|
@@ -836,9 +872,12 @@ class TreeCursor {
|
|
|
836
872
|
}
|
|
837
873
|
for (; parent; { index, _parent: parent } = parent) {
|
|
838
874
|
if (index > -1)
|
|
839
|
-
for (let i = index + dir, e = dir < 0 ? -1 : parent.
|
|
840
|
-
let child = parent.
|
|
841
|
-
if ((this.mode &
|
|
875
|
+
for (let i = index + dir, e = dir < 0 ? -1 : parent._tree.children.length; i != e; i += dir) {
|
|
876
|
+
let child = parent._tree.children[i];
|
|
877
|
+
if ((this.mode & IterMode.IncludeAnonymous) ||
|
|
878
|
+
child instanceof TreeBuffer ||
|
|
879
|
+
!child.type.isAnonymous ||
|
|
880
|
+
hasChild(child))
|
|
842
881
|
return false;
|
|
843
882
|
}
|
|
844
883
|
}
|
|
@@ -906,7 +945,55 @@ class TreeCursor {
|
|
|
906
945
|
/// any. Will return null when the node is in a [tree
|
|
907
946
|
/// buffer](#common.TreeBuffer).
|
|
908
947
|
get tree() {
|
|
909
|
-
return this.buffer ? null : this._tree.
|
|
948
|
+
return this.buffer ? null : this._tree._tree;
|
|
949
|
+
}
|
|
950
|
+
/// Iterate over the current node and all its descendants, calling
|
|
951
|
+
/// `enter` when entering a node and `leave`, if given, when leaving
|
|
952
|
+
/// one. When `enter` returns `false`, any children of that node are
|
|
953
|
+
/// skipped, and `leave` isn't called for it.
|
|
954
|
+
iterate(enter, leave) {
|
|
955
|
+
for (let depth = 0;;) {
|
|
956
|
+
let mustLeave = false;
|
|
957
|
+
if (this.type.isAnonymous || enter(this) !== false) {
|
|
958
|
+
if (this.firstChild()) {
|
|
959
|
+
depth++;
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
962
|
+
if (!this.type.isAnonymous)
|
|
963
|
+
mustLeave = true;
|
|
964
|
+
}
|
|
965
|
+
for (;;) {
|
|
966
|
+
if (mustLeave && leave)
|
|
967
|
+
leave(this);
|
|
968
|
+
mustLeave = this.type.isAnonymous;
|
|
969
|
+
if (this.nextSibling())
|
|
970
|
+
break;
|
|
971
|
+
if (!depth)
|
|
972
|
+
return;
|
|
973
|
+
this.parent();
|
|
974
|
+
depth--;
|
|
975
|
+
mustLeave = true;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
/// Test whether the current node matches a given context—a sequence
|
|
980
|
+
/// of direct parent node names. Empty strings in the context array
|
|
981
|
+
/// are treated as wildcards.
|
|
982
|
+
matchContext(context) {
|
|
983
|
+
if (!this.buffer)
|
|
984
|
+
return matchNodeContext(this.node, context);
|
|
985
|
+
let { buffer } = this.buffer, { types } = buffer.set;
|
|
986
|
+
for (let i = context.length - 1, d = this.stack.length - 1; i >= 0; d--) {
|
|
987
|
+
if (d < 0)
|
|
988
|
+
return matchNodeContext(this.node, context, i);
|
|
989
|
+
let type = types[buffer.buffer[this.stack[d]]];
|
|
990
|
+
if (!type.isAnonymous) {
|
|
991
|
+
if (context[i] && context[i] != type.name)
|
|
992
|
+
return false;
|
|
993
|
+
i--;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
return true;
|
|
910
997
|
}
|
|
911
998
|
}
|
|
912
999
|
function hasChild(tree) {
|
|
@@ -1166,6 +1253,48 @@ mkTree) {
|
|
|
1166
1253
|
divide(children, positions, from, to, 0);
|
|
1167
1254
|
return (mkTop || mkTree)(localChildren, localPositions, length);
|
|
1168
1255
|
}
|
|
1256
|
+
/// Provides a way to associate values with pieces of trees. As long
|
|
1257
|
+
/// as that part of the tree is reused, the associated values can be
|
|
1258
|
+
/// retrieved from an updated tree.
|
|
1259
|
+
class NodeWeakMap {
|
|
1260
|
+
constructor() {
|
|
1261
|
+
this.map = new WeakMap();
|
|
1262
|
+
}
|
|
1263
|
+
setBuffer(buffer, index, value) {
|
|
1264
|
+
let inner = this.map.get(buffer);
|
|
1265
|
+
if (!inner)
|
|
1266
|
+
this.map.set(buffer, inner = new Map);
|
|
1267
|
+
inner.set(index, value);
|
|
1268
|
+
}
|
|
1269
|
+
getBuffer(buffer, index) {
|
|
1270
|
+
let inner = this.map.get(buffer);
|
|
1271
|
+
return inner && inner.get(index);
|
|
1272
|
+
}
|
|
1273
|
+
/// Set the value for this syntax node.
|
|
1274
|
+
set(node, value) {
|
|
1275
|
+
if (node instanceof BufferNode)
|
|
1276
|
+
this.setBuffer(node.context.buffer, node.index, value);
|
|
1277
|
+
else if (node instanceof TreeNode)
|
|
1278
|
+
this.map.set(node.tree, value);
|
|
1279
|
+
}
|
|
1280
|
+
/// Retrieve value for this syntax node, if it exists in the map.
|
|
1281
|
+
get(node) {
|
|
1282
|
+
return node instanceof BufferNode ? this.getBuffer(node.context.buffer, node.index)
|
|
1283
|
+
: node instanceof TreeNode ? this.map.get(node.tree) : undefined;
|
|
1284
|
+
}
|
|
1285
|
+
/// Set the value for the node that a cursor currently points to.
|
|
1286
|
+
cursorSet(cursor, value) {
|
|
1287
|
+
if (cursor.buffer)
|
|
1288
|
+
this.setBuffer(cursor.buffer.buffer, cursor.index, value);
|
|
1289
|
+
else
|
|
1290
|
+
this.map.set(cursor.tree, value);
|
|
1291
|
+
}
|
|
1292
|
+
/// Retrieve the value for the node that a cursor currently points
|
|
1293
|
+
/// to.
|
|
1294
|
+
cursorGet(cursor) {
|
|
1295
|
+
return cursor.buffer ? this.getBuffer(cursor.buffer.buffer, cursor.index) : this.map.get(cursor.tree);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1169
1298
|
|
|
1170
1299
|
/// Tree fragments are used during [incremental
|
|
1171
1300
|
/// parsing](#common.Parser.startParse) to track parts of old trees
|
|
@@ -1386,7 +1515,7 @@ class MixedParse {
|
|
|
1386
1515
|
let fragmentCursor = new FragmentCursor(this.fragments);
|
|
1387
1516
|
let overlay = null;
|
|
1388
1517
|
let covered = null;
|
|
1389
|
-
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null),
|
|
1518
|
+
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), IterMode.IncludeAnonymous | IterMode.IgnoreMounts);
|
|
1390
1519
|
scan: for (let nest, isCovered; this.stoppedAt == null || cursor.from < this.stoppedAt;) {
|
|
1391
1520
|
let enter = true, range;
|
|
1392
1521
|
if (fragmentCursor.hasNode(cursor)) {
|
|
@@ -1514,13 +1643,13 @@ class StructureCursor {
|
|
|
1514
1643
|
constructor(root, offset) {
|
|
1515
1644
|
this.offset = offset;
|
|
1516
1645
|
this.done = false;
|
|
1517
|
-
this.cursor = root.
|
|
1646
|
+
this.cursor = root.cursor(IterMode.IncludeAnonymous | IterMode.IgnoreMounts);
|
|
1518
1647
|
}
|
|
1519
1648
|
// Move to the first node (in pre-order) that starts at or after `pos`.
|
|
1520
1649
|
moveTo(pos) {
|
|
1521
1650
|
let { cursor } = this, p = pos - this.offset;
|
|
1522
1651
|
while (!this.done && cursor.from < p) {
|
|
1523
|
-
if (cursor.to >= pos && cursor.enter(p, 1,
|
|
1652
|
+
if (cursor.to >= pos && cursor.enter(p, 1, IterMode.IgnoreOverlays | IterMode.ExcludeBuffers)) ;
|
|
1524
1653
|
else if (!cursor.next(false))
|
|
1525
1654
|
this.done = true;
|
|
1526
1655
|
}
|
|
@@ -1684,4 +1813,4 @@ function enterFragments(mounts, ranges) {
|
|
|
1684
1813
|
return result;
|
|
1685
1814
|
}
|
|
1686
1815
|
|
|
1687
|
-
export { DefaultBufferLength, MountedTree, NodeProp, NodeSet, NodeType, Parser, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
|
|
1816
|
+
export { DefaultBufferLength, IterMode, MountedTree, NodeProp, NodeSet, NodeType, NodeWeakMap, Parser, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
|
package/dist/mix.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SyntaxNodeRef } from "./tree";
|
|
2
2
|
import { Input, Parser, ParseWrapper } from "./parse";
|
|
3
3
|
export interface NestedParse {
|
|
4
4
|
parser: Parser;
|
|
5
5
|
overlay?: readonly {
|
|
6
6
|
from: number;
|
|
7
7
|
to: number;
|
|
8
|
-
}[] | ((node:
|
|
8
|
+
}[] | ((node: SyntaxNodeRef) => {
|
|
9
9
|
from: number;
|
|
10
10
|
to: number;
|
|
11
11
|
} | boolean);
|
|
12
12
|
}
|
|
13
|
-
export declare function parseMixed(nest: (node:
|
|
13
|
+
export declare function parseMixed(nest: (node: SyntaxNodeRef, input: Input) => NestedParse | null): ParseWrapper;
|
package/dist/tree.d.ts
CHANGED
|
@@ -62,6 +62,12 @@ export declare class NodeSet {
|
|
|
62
62
|
constructor(types: readonly NodeType[]);
|
|
63
63
|
extend(...props: NodePropSource[]): NodeSet;
|
|
64
64
|
}
|
|
65
|
+
export declare enum IterMode {
|
|
66
|
+
ExcludeBuffers = 1,
|
|
67
|
+
IncludeAnonymous = 2,
|
|
68
|
+
IgnoreMounts = 4,
|
|
69
|
+
IgnoreOverlays = 8
|
|
70
|
+
}
|
|
65
71
|
export declare class Tree {
|
|
66
72
|
readonly type: NodeType;
|
|
67
73
|
readonly children: readonly (Tree | TreeBuffer)[];
|
|
@@ -69,16 +75,17 @@ export declare class Tree {
|
|
|
69
75
|
readonly length: number;
|
|
70
76
|
constructor(type: NodeType, children: readonly (Tree | TreeBuffer)[], positions: readonly number[], length: number, props?: readonly [NodeProp<any> | number, any][]);
|
|
71
77
|
static empty: Tree;
|
|
72
|
-
cursor(
|
|
73
|
-
|
|
78
|
+
cursor(mode?: IterMode): TreeCursor;
|
|
79
|
+
cursorAt(pos: number, side?: -1 | 0 | 1, mode?: IterMode): TreeCursor;
|
|
74
80
|
get topNode(): SyntaxNode;
|
|
75
81
|
resolve(pos: number, side?: -1 | 0 | 1): SyntaxNode;
|
|
76
82
|
resolveInner(pos: number, side?: -1 | 0 | 1): SyntaxNode;
|
|
77
83
|
iterate(spec: {
|
|
78
|
-
enter(
|
|
79
|
-
leave?(
|
|
84
|
+
enter(node: SyntaxNodeRef): boolean | void;
|
|
85
|
+
leave?(node: SyntaxNodeRef): void;
|
|
80
86
|
from?: number;
|
|
81
87
|
to?: number;
|
|
88
|
+
mode?: IterMode;
|
|
82
89
|
}): void;
|
|
83
90
|
prop<T>(prop: NodeProp<T>): T | undefined;
|
|
84
91
|
get propValues(): readonly [NodeProp<any> | number, any][];
|
|
@@ -113,27 +120,31 @@ export declare class TreeBuffer {
|
|
|
113
120
|
readonly set: NodeSet;
|
|
114
121
|
constructor(buffer: Uint16Array, length: number, set: NodeSet);
|
|
115
122
|
}
|
|
116
|
-
export interface
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
export interface SyntaxNodeRef {
|
|
124
|
+
readonly from: number;
|
|
125
|
+
readonly to: number;
|
|
126
|
+
readonly type: NodeType;
|
|
127
|
+
readonly name: string;
|
|
128
|
+
readonly tree: Tree | null;
|
|
129
|
+
readonly node: SyntaxNode;
|
|
130
|
+
}
|
|
131
|
+
export interface SyntaxNode extends SyntaxNodeRef {
|
|
121
132
|
parent: SyntaxNode | null;
|
|
122
133
|
firstChild: SyntaxNode | null;
|
|
123
134
|
lastChild: SyntaxNode | null;
|
|
124
135
|
childAfter(pos: number): SyntaxNode | null;
|
|
125
136
|
childBefore(pos: number): SyntaxNode | null;
|
|
126
|
-
enter(pos: number, side: -1 | 0 | 1,
|
|
137
|
+
enter(pos: number, side: -1 | 0 | 1, mode?: IterMode): SyntaxNode | null;
|
|
127
138
|
nextSibling: SyntaxNode | null;
|
|
128
139
|
prevSibling: SyntaxNode | null;
|
|
129
|
-
cursor: TreeCursor;
|
|
140
|
+
cursor(mode?: IterMode): TreeCursor;
|
|
130
141
|
resolve(pos: number, side?: -1 | 0 | 1): SyntaxNode;
|
|
131
142
|
resolveInner(pos: number, side?: -1 | 0 | 1): SyntaxNode;
|
|
132
143
|
enterUnfinishedNodesBefore(pos: number): SyntaxNode;
|
|
133
|
-
tree: Tree | null;
|
|
134
144
|
toTree(): Tree;
|
|
135
145
|
getChild(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode | null;
|
|
136
146
|
getChildren(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode[];
|
|
147
|
+
matchContext(context: readonly string[]): boolean;
|
|
137
148
|
}
|
|
138
149
|
declare const enum Side {
|
|
139
150
|
Before = -2,
|
|
@@ -143,31 +154,26 @@ declare const enum Side {
|
|
|
143
154
|
After = 2,
|
|
144
155
|
DontCare = 4
|
|
145
156
|
}
|
|
146
|
-
export declare const enum Mode {
|
|
147
|
-
Full = 1,
|
|
148
|
-
NoEnterBuffer = 2
|
|
149
|
-
}
|
|
150
157
|
export declare class TreeNode implements SyntaxNode {
|
|
151
|
-
readonly
|
|
152
|
-
readonly
|
|
158
|
+
readonly _tree: Tree;
|
|
159
|
+
readonly from: number;
|
|
153
160
|
readonly index: number;
|
|
154
161
|
readonly _parent: TreeNode | null;
|
|
155
|
-
constructor(
|
|
162
|
+
constructor(_tree: Tree, from: number, index: number, _parent: TreeNode | null);
|
|
156
163
|
get type(): NodeType;
|
|
157
164
|
get name(): string;
|
|
158
|
-
get from(): number;
|
|
159
165
|
get to(): number;
|
|
160
|
-
nextChild(i: number, dir: 1 | -1, pos: number, side: Side, mode?:
|
|
166
|
+
nextChild(i: number, dir: 1 | -1, pos: number, side: Side, mode?: IterMode): TreeNode | BufferNode | null;
|
|
161
167
|
get firstChild(): TreeNode | BufferNode;
|
|
162
168
|
get lastChild(): TreeNode | BufferNode;
|
|
163
169
|
childAfter(pos: number): TreeNode | BufferNode;
|
|
164
170
|
childBefore(pos: number): TreeNode | BufferNode;
|
|
165
|
-
enter(pos: number, side: -1 | 0 | 1,
|
|
171
|
+
enter(pos: number, side: -1 | 0 | 1, mode?: number): TreeNode | BufferNode;
|
|
166
172
|
nextSignificantParent(): TreeNode;
|
|
167
173
|
get parent(): TreeNode;
|
|
168
174
|
get nextSibling(): TreeNode | BufferNode;
|
|
169
175
|
get prevSibling(): TreeNode | BufferNode;
|
|
170
|
-
|
|
176
|
+
cursor(mode?: IterMode): TreeCursor;
|
|
171
177
|
get tree(): Tree;
|
|
172
178
|
toTree(): Tree;
|
|
173
179
|
resolve(pos: number, side?: -1 | 0 | 1): SyntaxNode;
|
|
@@ -175,6 +181,8 @@ export declare class TreeNode implements SyntaxNode {
|
|
|
175
181
|
enterUnfinishedNodesBefore(pos: number): SyntaxNode;
|
|
176
182
|
getChild(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode;
|
|
177
183
|
getChildren(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode[];
|
|
184
|
+
get node(): this;
|
|
185
|
+
matchContext(context: readonly string[]): boolean;
|
|
178
186
|
}
|
|
179
187
|
declare class BufferContext {
|
|
180
188
|
readonly parent: TreeNode;
|
|
@@ -197,12 +205,12 @@ declare class BufferNode implements SyntaxNode {
|
|
|
197
205
|
get lastChild(): BufferNode;
|
|
198
206
|
childAfter(pos: number): BufferNode;
|
|
199
207
|
childBefore(pos: number): BufferNode;
|
|
200
|
-
enter(pos: number, side: -1 | 0 | 1,
|
|
208
|
+
enter(pos: number, side: -1 | 0 | 1, mode?: IterMode): BufferNode;
|
|
201
209
|
get parent(): TreeNode | BufferNode;
|
|
202
210
|
externalSibling(dir: 1 | -1): TreeNode | BufferNode;
|
|
203
211
|
get nextSibling(): SyntaxNode | null;
|
|
204
212
|
get prevSibling(): SyntaxNode | null;
|
|
205
|
-
|
|
213
|
+
cursor(mode?: IterMode): TreeCursor;
|
|
206
214
|
get tree(): any;
|
|
207
215
|
toTree(): Tree;
|
|
208
216
|
resolve(pos: number, side?: -1 | 0 | 1): SyntaxNode;
|
|
@@ -210,15 +218,15 @@ declare class BufferNode implements SyntaxNode {
|
|
|
210
218
|
enterUnfinishedNodesBefore(pos: number): SyntaxNode;
|
|
211
219
|
getChild(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode;
|
|
212
220
|
getChildren(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode[];
|
|
221
|
+
get node(): this;
|
|
222
|
+
matchContext(context: readonly string[]): boolean;
|
|
213
223
|
}
|
|
214
|
-
export declare class TreeCursor {
|
|
224
|
+
export declare class TreeCursor implements SyntaxNodeRef {
|
|
215
225
|
type: NodeType;
|
|
216
226
|
get name(): string;
|
|
217
227
|
from: number;
|
|
218
228
|
to: number;
|
|
219
|
-
private buffer;
|
|
220
229
|
private stack;
|
|
221
|
-
private index;
|
|
222
230
|
private bufferNode;
|
|
223
231
|
private yieldNode;
|
|
224
232
|
private yieldBuf;
|
|
@@ -227,7 +235,7 @@ export declare class TreeCursor {
|
|
|
227
235
|
lastChild(): boolean;
|
|
228
236
|
childAfter(pos: number): boolean;
|
|
229
237
|
childBefore(pos: number): boolean;
|
|
230
|
-
enter(pos: number, side: -1 | 0 | 1,
|
|
238
|
+
enter(pos: number, side: -1 | 0 | 1, mode?: IterMode): boolean;
|
|
231
239
|
parent(): boolean;
|
|
232
240
|
nextSibling(): boolean;
|
|
233
241
|
prevSibling(): boolean;
|
|
@@ -238,5 +246,16 @@ export declare class TreeCursor {
|
|
|
238
246
|
moveTo(pos: number, side?: -1 | 0 | 1): this;
|
|
239
247
|
get node(): SyntaxNode;
|
|
240
248
|
get tree(): Tree | null;
|
|
249
|
+
iterate(enter: (node: SyntaxNodeRef) => boolean | void, leave?: (node: SyntaxNodeRef) => void): void;
|
|
250
|
+
matchContext(context: readonly string[]): boolean;
|
|
251
|
+
}
|
|
252
|
+
export declare class NodeWeakMap<T> {
|
|
253
|
+
private map;
|
|
254
|
+
private setBuffer;
|
|
255
|
+
private getBuffer;
|
|
256
|
+
set(node: SyntaxNode, value: T): void;
|
|
257
|
+
get(node: SyntaxNode): T | undefined;
|
|
258
|
+
cursorSet(cursor: TreeCursor, value: T): void;
|
|
259
|
+
cursorGet(cursor: TreeCursor): T | undefined;
|
|
241
260
|
}
|
|
242
261
|
export {};
|