@lezer/common 0.15.10 → 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 +206 -76
- package/dist/index.d.ts +1 -1
- package/dist/index.js +206 -77
- package/dist/mix.d.ts +3 -3
- package/dist/tree.d.ts +48 -29
- package/package.json +1 -1
- package/dist/composite.d.ts +0 -42
- package/dist/frame.d.ts +0 -25
- package/dist/scaffold.d.ts +0 -25
- package/dist/tree.cjs +0 -1156
- package/dist/tree.cjs.map +0 -1
- package/dist/tree.es.js +0 -1143
- package/dist/tree.es.js.map +0 -1
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)) {
|
|
@@ -1395,7 +1524,7 @@ class MixedParse {
|
|
|
1395
1524
|
if (match)
|
|
1396
1525
|
for (let r of match.mount.overlay) {
|
|
1397
1526
|
let from = r.from + match.pos, to = r.to + match.pos;
|
|
1398
|
-
if (from >= cursor.from && to <= cursor.to)
|
|
1527
|
+
if (from >= cursor.from && to <= cursor.to && !overlay.ranges.some(r => r.from < to && r.to > from))
|
|
1399
1528
|
overlay.ranges.push({ from, to });
|
|
1400
1529
|
}
|
|
1401
1530
|
}
|
|
@@ -1492,20 +1621,20 @@ function materialize(cursor) {
|
|
|
1492
1621
|
let buf = base.children[i], b = buf.buffer;
|
|
1493
1622
|
// Split a level in the buffer, putting the nodes before and after
|
|
1494
1623
|
// the child that contains `node` into new buffers.
|
|
1495
|
-
function split(startI, endI, type, innerOffset) {
|
|
1624
|
+
function split(startI, endI, type, innerOffset, length) {
|
|
1496
1625
|
let i = startI;
|
|
1497
1626
|
while (b[i + 2] + off <= node.from)
|
|
1498
1627
|
i = b[i + 3];
|
|
1499
1628
|
let children = [], positions = [];
|
|
1500
1629
|
sliceBuf(buf, startI, i, children, positions, innerOffset);
|
|
1501
|
-
let
|
|
1502
|
-
|
|
1503
|
-
|
|
1630
|
+
let from = b[i + 1], to = b[i + 2];
|
|
1631
|
+
let isTarget = from + off == node.from && to + off == node.to && b[i] == node.type.id;
|
|
1632
|
+
children.push(isTarget ? node.toTree() : split(i + 4, b[i + 3], buf.set.types[b[i]], from, to - from));
|
|
1633
|
+
positions.push(from - innerOffset);
|
|
1504
1634
|
sliceBuf(buf, b[i + 3], endI, children, positions, innerOffset);
|
|
1505
|
-
|
|
1506
|
-
return new Tree(type, children, positions, positions[last] + children[last].length);
|
|
1635
|
+
return new Tree(type, children, positions, length);
|
|
1507
1636
|
}
|
|
1508
|
-
base.children[i] = split(0, b.length, NodeType.none, 0);
|
|
1637
|
+
base.children[i] = split(0, b.length, NodeType.none, 0, buf.length);
|
|
1509
1638
|
// Move the cursor back to the target node
|
|
1510
1639
|
for (let d = 0; d <= depth; d++)
|
|
1511
1640
|
cursor.childAfter(node.from);
|
|
@@ -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;
|