@lezer/common 0.15.12 → 1.0.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 +207 -78
- package/dist/index.d.ts +1 -1
- package/dist/index.es.js +1816 -0
- package/dist/index.js +207 -79
- package/dist/mix.d.ts +3 -3
- package/dist/tree.d.ts +53 -33
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
// FIXME profile adding a per-Tree TreeNode cache, validating it by
|
|
6
6
|
// parent pointer
|
|
7
|
-
/// The default maximum length of a `TreeBuffer` node
|
|
7
|
+
/// The default maximum length of a `TreeBuffer` node.
|
|
8
8
|
const DefaultBufferLength = 1024;
|
|
9
9
|
let nextPropID = 0;
|
|
10
10
|
class Range {
|
|
@@ -67,7 +67,7 @@ NodeProp.contextHash = new NodeProp({ perNode: true });
|
|
|
67
67
|
NodeProp.lookAhead = new NodeProp({ perNode: true });
|
|
68
68
|
/// This per-node prop is used to replace a given node, or part of a
|
|
69
69
|
/// node, with another tree. This is useful to include trees from
|
|
70
|
-
/// different languages.
|
|
70
|
+
/// different languages in mixed-language parsers.
|
|
71
71
|
NodeProp.mounted = new NodeProp({ perNode: true });
|
|
72
72
|
/// A mounted tree, which can be [stored](#common.NodeProp^mounted) on
|
|
73
73
|
/// a tree node to indicate that parts of its content are
|
|
@@ -113,6 +113,7 @@ class NodeType {
|
|
|
113
113
|
this.id = id;
|
|
114
114
|
this.flags = flags;
|
|
115
115
|
}
|
|
116
|
+
/// Define a node type.
|
|
116
117
|
static define(spec) {
|
|
117
118
|
let props = spec.props && spec.props.length ? Object.create(null) : noProps;
|
|
118
119
|
let flags = (spec.top ? 1 /* Top */ : 0) | (spec.skipped ? 2 /* Skipped */ : 0) |
|
|
@@ -194,7 +195,7 @@ class NodeSet {
|
|
|
194
195
|
throw new RangeError("Node type ids should correspond to array positions when creating a node set");
|
|
195
196
|
}
|
|
196
197
|
/// Create a copy of this set with some node properties added. The
|
|
197
|
-
/// arguments to this method
|
|
198
|
+
/// arguments to this method can be created with
|
|
198
199
|
/// [`NodeProp.add`](#common.NodeProp.add).
|
|
199
200
|
extend(...props) {
|
|
200
201
|
let newTypes = [];
|
|
@@ -214,6 +215,28 @@ class NodeSet {
|
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
217
|
const CachedNode = new WeakMap(), CachedInnerNode = new WeakMap();
|
|
218
|
+
/// Options that control iteration. Can be combined with the `|`
|
|
219
|
+
/// operator to enable multiple ones.
|
|
220
|
+
exports.IterMode = void 0;
|
|
221
|
+
(function (IterMode) {
|
|
222
|
+
/// When enabled, iteration will only visit [`Tree`](#common.Tree)
|
|
223
|
+
/// objects, not nodes packed into
|
|
224
|
+
/// [`TreeBuffer`](#common.TreeBuffer)s.
|
|
225
|
+
IterMode[IterMode["ExcludeBuffers"] = 1] = "ExcludeBuffers";
|
|
226
|
+
/// Enable this to make iteration include anonymous nodes (such as
|
|
227
|
+
/// the nodes that wrap repeated grammar constructs into a balanced
|
|
228
|
+
/// tree).
|
|
229
|
+
IterMode[IterMode["IncludeAnonymous"] = 2] = "IncludeAnonymous";
|
|
230
|
+
/// By default, regular [mounted](#common.NodeProp^mounted) nodes
|
|
231
|
+
/// replace their base node in iteration. Enable this to ignore them
|
|
232
|
+
/// instead.
|
|
233
|
+
IterMode[IterMode["IgnoreMounts"] = 4] = "IgnoreMounts";
|
|
234
|
+
/// This option only applies in
|
|
235
|
+
/// [`enter`](#common.SyntaxNode.enter)-style methods. It tells the
|
|
236
|
+
/// library to not enter mounted overlays if one covers the given
|
|
237
|
+
/// position.
|
|
238
|
+
IterMode[IterMode["IgnoreOverlays"] = 8] = "IgnoreOverlays";
|
|
239
|
+
})(exports.IterMode || (exports.IterMode = {}));
|
|
217
240
|
/// A piece of syntax tree. There are two ways to approach these
|
|
218
241
|
/// trees: the way they are actually stored in memory, and the
|
|
219
242
|
/// convenient way.
|
|
@@ -272,25 +295,22 @@ class Tree {
|
|
|
272
295
|
(/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) +
|
|
273
296
|
(children.length ? "(" + children + ")" : "");
|
|
274
297
|
}
|
|
275
|
-
/// Get a [tree cursor](#common.TreeCursor)
|
|
276
|
-
///
|
|
277
|
-
///
|
|
278
|
-
cursor(
|
|
279
|
-
|
|
298
|
+
/// Get a [tree cursor](#common.TreeCursor) positioned at the top of
|
|
299
|
+
/// the tree. Mode can be used to [control](#common.IterMode) which
|
|
300
|
+
/// nodes the cursor visits.
|
|
301
|
+
cursor(mode = 0) {
|
|
302
|
+
return new TreeCursor(this.topNode, mode);
|
|
303
|
+
}
|
|
304
|
+
/// Get a [tree cursor](#common.TreeCursor) pointing into this tree
|
|
305
|
+
/// at the given position and side (see
|
|
306
|
+
/// [`moveTo`](#common.TreeCursor.moveTo).
|
|
307
|
+
cursorAt(pos, side = 0, mode = 0) {
|
|
308
|
+
let scope = CachedNode.get(this) || this.topNode;
|
|
280
309
|
let cursor = new TreeCursor(scope);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
CachedNode.set(this, cursor._tree);
|
|
284
|
-
}
|
|
310
|
+
cursor.moveTo(pos, side);
|
|
311
|
+
CachedNode.set(this, cursor._tree);
|
|
285
312
|
return cursor;
|
|
286
313
|
}
|
|
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
314
|
/// Get a [syntax node](#common.SyntaxNode) object for the top of the
|
|
295
315
|
/// tree.
|
|
296
316
|
get topNode() {
|
|
@@ -323,23 +343,21 @@ class Tree {
|
|
|
323
343
|
/// not have its children iterated over (or `leave` called).
|
|
324
344
|
iterate(spec) {
|
|
325
345
|
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
|
|
346
|
+
for (let c = this.cursor((spec.mode || 0) | exports.IterMode.IncludeAnonymous);;) {
|
|
347
|
+
let entered = false;
|
|
348
|
+
if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c) !== false)) {
|
|
329
349
|
if (c.firstChild())
|
|
330
350
|
continue;
|
|
331
|
-
|
|
332
|
-
mustLeave = true;
|
|
351
|
+
entered = true;
|
|
333
352
|
}
|
|
334
353
|
for (;;) {
|
|
335
|
-
if (
|
|
336
|
-
leave(c
|
|
337
|
-
mustLeave = c.type.isAnonymous;
|
|
354
|
+
if (entered && leave && !c.type.isAnonymous)
|
|
355
|
+
leave(c);
|
|
338
356
|
if (c.nextSibling())
|
|
339
357
|
break;
|
|
340
358
|
if (!c.parent())
|
|
341
359
|
return;
|
|
342
|
-
|
|
360
|
+
entered = true;
|
|
343
361
|
}
|
|
344
362
|
}
|
|
345
363
|
}
|
|
@@ -387,7 +405,7 @@ class FlatBufferCursor {
|
|
|
387
405
|
/// Tree buffers contain (type, start, end, endIndex) quads for each
|
|
388
406
|
/// node. In such a buffer, nodes are stored in prefix order (parents
|
|
389
407
|
/// before children, with the endIndex of the parent indicating which
|
|
390
|
-
/// children belong to it)
|
|
408
|
+
/// children belong to it).
|
|
391
409
|
class TreeBuffer {
|
|
392
410
|
/// Create a tree buffer.
|
|
393
411
|
constructor(
|
|
@@ -490,72 +508,73 @@ function resolveNode(node, pos, side, overlays) {
|
|
|
490
508
|
return node;
|
|
491
509
|
node = parent;
|
|
492
510
|
}
|
|
511
|
+
let mode = overlays ? 0 : exports.IterMode.IgnoreOverlays;
|
|
493
512
|
// Must go up out of overlays when those do not overlap with pos
|
|
494
513
|
if (overlays)
|
|
495
514
|
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,
|
|
515
|
+
if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side, mode)) === null || _a === void 0 ? void 0 : _a.from) != scan.from)
|
|
497
516
|
node = parent;
|
|
498
517
|
}
|
|
499
518
|
for (;;) {
|
|
500
|
-
let inner = node.enter(pos, side,
|
|
519
|
+
let inner = node.enter(pos, side, mode);
|
|
501
520
|
if (!inner)
|
|
502
521
|
return node;
|
|
503
522
|
node = inner;
|
|
504
523
|
}
|
|
505
524
|
}
|
|
506
525
|
class TreeNode {
|
|
507
|
-
constructor(
|
|
526
|
+
constructor(_tree, from,
|
|
508
527
|
// Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
|
|
509
528
|
index, _parent) {
|
|
510
|
-
this.
|
|
511
|
-
this.
|
|
529
|
+
this._tree = _tree;
|
|
530
|
+
this.from = from;
|
|
512
531
|
this.index = index;
|
|
513
532
|
this._parent = _parent;
|
|
514
533
|
}
|
|
515
|
-
get type() { return this.
|
|
516
|
-
get name() { return this.
|
|
517
|
-
get
|
|
518
|
-
get to() { return this._from + this.node.length; }
|
|
534
|
+
get type() { return this._tree.type; }
|
|
535
|
+
get name() { return this._tree.type.name; }
|
|
536
|
+
get to() { return this.from + this._tree.length; }
|
|
519
537
|
nextChild(i, dir, pos, side, mode = 0) {
|
|
520
538
|
for (let parent = this;;) {
|
|
521
|
-
for (let { children, positions } = parent.
|
|
522
|
-
let next = children[i], start = positions[i] + parent.
|
|
539
|
+
for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) {
|
|
540
|
+
let next = children[i], start = positions[i] + parent.from;
|
|
523
541
|
if (!checkSide(side, pos, start, start + next.length))
|
|
524
542
|
continue;
|
|
525
543
|
if (next instanceof TreeBuffer) {
|
|
526
|
-
if (mode &
|
|
544
|
+
if (mode & exports.IterMode.ExcludeBuffers)
|
|
527
545
|
continue;
|
|
528
546
|
let index = next.findChild(0, next.buffer.length, dir, pos - start, side);
|
|
529
547
|
if (index > -1)
|
|
530
548
|
return new BufferNode(new BufferContext(parent, next, i, start), null, index);
|
|
531
549
|
}
|
|
532
|
-
else if ((mode &
|
|
550
|
+
else if ((mode & exports.IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
|
|
533
551
|
let mounted;
|
|
534
|
-
if (!(mode &
|
|
552
|
+
if (!(mode & exports.IterMode.IgnoreMounts) &&
|
|
553
|
+
next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
|
|
535
554
|
return new TreeNode(mounted.tree, start, i, parent);
|
|
536
555
|
let inner = new TreeNode(next, start, i, parent);
|
|
537
|
-
return (mode &
|
|
556
|
+
return (mode & exports.IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
|
|
538
557
|
: inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side);
|
|
539
558
|
}
|
|
540
559
|
}
|
|
541
|
-
if ((mode &
|
|
560
|
+
if ((mode & exports.IterMode.IncludeAnonymous) || !parent.type.isAnonymous)
|
|
542
561
|
return null;
|
|
543
562
|
if (parent.index >= 0)
|
|
544
563
|
i = parent.index + dir;
|
|
545
564
|
else
|
|
546
|
-
i = dir < 0 ? -1 : parent._parent.
|
|
565
|
+
i = dir < 0 ? -1 : parent._parent._tree.children.length;
|
|
547
566
|
parent = parent._parent;
|
|
548
567
|
if (!parent)
|
|
549
568
|
return null;
|
|
550
569
|
}
|
|
551
570
|
}
|
|
552
571
|
get firstChild() { return this.nextChild(0, 1, 0, 4 /* DontCare */); }
|
|
553
|
-
get lastChild() { return this.nextChild(this.
|
|
572
|
+
get lastChild() { return this.nextChild(this._tree.children.length - 1, -1, 0, 4 /* DontCare */); }
|
|
554
573
|
childAfter(pos) { return this.nextChild(0, 1, pos, 2 /* After */); }
|
|
555
|
-
childBefore(pos) { return this.nextChild(this.
|
|
556
|
-
enter(pos, side,
|
|
574
|
+
childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Before */); }
|
|
575
|
+
enter(pos, side, mode = 0) {
|
|
557
576
|
let mounted;
|
|
558
|
-
if (
|
|
577
|
+
if (!(mode & exports.IterMode.IgnoreOverlays) && (mounted = this._tree.prop(NodeProp.mounted)) && mounted.overlay) {
|
|
559
578
|
let rPos = pos - this.from;
|
|
560
579
|
for (let { from, to } of mounted.overlay) {
|
|
561
580
|
if ((side > 0 ? from <= rPos : from < rPos) &&
|
|
@@ -563,7 +582,7 @@ class TreeNode {
|
|
|
563
582
|
return new TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this);
|
|
564
583
|
}
|
|
565
584
|
}
|
|
566
|
-
return this.nextChild(0, 1, pos, side,
|
|
585
|
+
return this.nextChild(0, 1, pos, side, mode);
|
|
567
586
|
}
|
|
568
587
|
nextSignificantParent() {
|
|
569
588
|
let val = this;
|
|
@@ -580,9 +599,9 @@ class TreeNode {
|
|
|
580
599
|
get prevSibling() {
|
|
581
600
|
return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* DontCare */) : null;
|
|
582
601
|
}
|
|
583
|
-
|
|
584
|
-
get tree() { return this.
|
|
585
|
-
toTree() { return this.
|
|
602
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
603
|
+
get tree() { return this._tree; }
|
|
604
|
+
toTree() { return this._tree; }
|
|
586
605
|
resolve(pos, side = 0) {
|
|
587
606
|
return resolveNode(this, pos, side, false);
|
|
588
607
|
}
|
|
@@ -598,10 +617,12 @@ class TreeNode {
|
|
|
598
617
|
return getChildren(this, type, before, after);
|
|
599
618
|
}
|
|
600
619
|
/// @internal
|
|
601
|
-
toString() { return this.
|
|
620
|
+
toString() { return this._tree.toString(); }
|
|
621
|
+
get node() { return this; }
|
|
622
|
+
matchContext(context) { return matchNodeContext(this, context); }
|
|
602
623
|
}
|
|
603
624
|
function getChildren(node, type, before, after) {
|
|
604
|
-
let cur = node.cursor, result = [];
|
|
625
|
+
let cur = node.cursor(), result = [];
|
|
605
626
|
if (!cur.firstChild())
|
|
606
627
|
return result;
|
|
607
628
|
if (before != null)
|
|
@@ -617,6 +638,18 @@ function getChildren(node, type, before, after) {
|
|
|
617
638
|
return after == null ? result : [];
|
|
618
639
|
}
|
|
619
640
|
}
|
|
641
|
+
function matchNodeContext(node, context, i = context.length - 1) {
|
|
642
|
+
for (let p = node.parent; i >= 0; p = p.parent) {
|
|
643
|
+
if (!p)
|
|
644
|
+
return false;
|
|
645
|
+
if (!p.type.isAnonymous) {
|
|
646
|
+
if (context[i] && context[i] != p.name)
|
|
647
|
+
return false;
|
|
648
|
+
i--;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return true;
|
|
652
|
+
}
|
|
620
653
|
class BufferContext {
|
|
621
654
|
constructor(parent, buffer, index, start) {
|
|
622
655
|
this.parent = parent;
|
|
@@ -644,8 +677,8 @@ class BufferNode {
|
|
|
644
677
|
get lastChild() { return this.child(-1, 0, 4 /* DontCare */); }
|
|
645
678
|
childAfter(pos) { return this.child(1, pos, 2 /* After */); }
|
|
646
679
|
childBefore(pos) { return this.child(-1, pos, -2 /* Before */); }
|
|
647
|
-
enter(pos, side,
|
|
648
|
-
if (
|
|
680
|
+
enter(pos, side, mode = 0) {
|
|
681
|
+
if (mode & exports.IterMode.ExcludeBuffers)
|
|
649
682
|
return null;
|
|
650
683
|
let { buffer } = this.context;
|
|
651
684
|
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side);
|
|
@@ -671,7 +704,7 @@ class BufferNode {
|
|
|
671
704
|
return this.externalSibling(-1);
|
|
672
705
|
return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* DontCare */));
|
|
673
706
|
}
|
|
674
|
-
|
|
707
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
675
708
|
get tree() { return null; }
|
|
676
709
|
toTree() {
|
|
677
710
|
let children = [], positions = [];
|
|
@@ -700,6 +733,8 @@ class BufferNode {
|
|
|
700
733
|
getChildren(type, before = null, after = null) {
|
|
701
734
|
return getChildren(this, type, before, after);
|
|
702
735
|
}
|
|
736
|
+
get node() { return this; }
|
|
737
|
+
matchContext(context) { return matchNodeContext(this, context); }
|
|
703
738
|
}
|
|
704
739
|
/// A tree cursor object focuses on a given node in a syntax tree, and
|
|
705
740
|
/// allows you to move to adjacent nodes.
|
|
@@ -709,8 +744,10 @@ class TreeCursor {
|
|
|
709
744
|
/// @internal
|
|
710
745
|
mode = 0) {
|
|
711
746
|
this.mode = mode;
|
|
747
|
+
/// @internal
|
|
712
748
|
this.buffer = null;
|
|
713
749
|
this.stack = [];
|
|
750
|
+
/// @internal
|
|
714
751
|
this.index = 0;
|
|
715
752
|
this.bufferNode = null;
|
|
716
753
|
if (node instanceof TreeNode) {
|
|
@@ -761,7 +798,7 @@ class TreeCursor {
|
|
|
761
798
|
/// @internal
|
|
762
799
|
enterChild(dir, pos, side) {
|
|
763
800
|
if (!this.buffer)
|
|
764
|
-
return this.yield(this._tree.nextChild(dir < 0 ? this._tree.
|
|
801
|
+
return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode));
|
|
765
802
|
let { buffer } = this.buffer;
|
|
766
803
|
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.buffer.start, side);
|
|
767
804
|
if (index < 0)
|
|
@@ -783,18 +820,18 @@ class TreeCursor {
|
|
|
783
820
|
/// will also enter [overlaid](#common.MountedTree.overlay)
|
|
784
821
|
/// [mounted](#common.NodeProp^mounted) trees unless `overlays` is
|
|
785
822
|
/// set to false.
|
|
786
|
-
enter(pos, side,
|
|
823
|
+
enter(pos, side, mode = this.mode) {
|
|
787
824
|
if (!this.buffer)
|
|
788
|
-
return this.yield(this._tree.enter(pos, side,
|
|
789
|
-
return
|
|
825
|
+
return this.yield(this._tree.enter(pos, side, mode));
|
|
826
|
+
return mode & exports.IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side);
|
|
790
827
|
}
|
|
791
828
|
/// Move to the node's parent node, if this isn't the top node.
|
|
792
829
|
parent() {
|
|
793
830
|
if (!this.buffer)
|
|
794
|
-
return this.yieldNode((this.mode &
|
|
831
|
+
return this.yieldNode((this.mode & exports.IterMode.IncludeAnonymous) ? this._tree._parent : this._tree.parent);
|
|
795
832
|
if (this.stack.length)
|
|
796
833
|
return this.yieldBuf(this.stack.pop());
|
|
797
|
-
let parent = (this.mode &
|
|
834
|
+
let parent = (this.mode & exports.IterMode.IncludeAnonymous) ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
|
|
798
835
|
this.buffer = null;
|
|
799
836
|
return this.yieldNode(parent);
|
|
800
837
|
}
|
|
@@ -840,9 +877,12 @@ class TreeCursor {
|
|
|
840
877
|
}
|
|
841
878
|
for (; parent; { index, _parent: parent } = parent) {
|
|
842
879
|
if (index > -1)
|
|
843
|
-
for (let i = index + dir, e = dir < 0 ? -1 : parent.
|
|
844
|
-
let child = parent.
|
|
845
|
-
if ((this.mode &
|
|
880
|
+
for (let i = index + dir, e = dir < 0 ? -1 : parent._tree.children.length; i != e; i += dir) {
|
|
881
|
+
let child = parent._tree.children[i];
|
|
882
|
+
if ((this.mode & exports.IterMode.IncludeAnonymous) ||
|
|
883
|
+
child instanceof TreeBuffer ||
|
|
884
|
+
!child.type.isAnonymous ||
|
|
885
|
+
hasChild(child))
|
|
846
886
|
return false;
|
|
847
887
|
}
|
|
848
888
|
}
|
|
@@ -910,7 +950,55 @@ class TreeCursor {
|
|
|
910
950
|
/// any. Will return null when the node is in a [tree
|
|
911
951
|
/// buffer](#common.TreeBuffer).
|
|
912
952
|
get tree() {
|
|
913
|
-
return this.buffer ? null : this._tree.
|
|
953
|
+
return this.buffer ? null : this._tree._tree;
|
|
954
|
+
}
|
|
955
|
+
/// Iterate over the current node and all its descendants, calling
|
|
956
|
+
/// `enter` when entering a node and `leave`, if given, when leaving
|
|
957
|
+
/// one. When `enter` returns `false`, any children of that node are
|
|
958
|
+
/// skipped, and `leave` isn't called for it.
|
|
959
|
+
iterate(enter, leave) {
|
|
960
|
+
for (let depth = 0;;) {
|
|
961
|
+
let mustLeave = false;
|
|
962
|
+
if (this.type.isAnonymous || enter(this) !== false) {
|
|
963
|
+
if (this.firstChild()) {
|
|
964
|
+
depth++;
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
if (!this.type.isAnonymous)
|
|
968
|
+
mustLeave = true;
|
|
969
|
+
}
|
|
970
|
+
for (;;) {
|
|
971
|
+
if (mustLeave && leave)
|
|
972
|
+
leave(this);
|
|
973
|
+
mustLeave = this.type.isAnonymous;
|
|
974
|
+
if (this.nextSibling())
|
|
975
|
+
break;
|
|
976
|
+
if (!depth)
|
|
977
|
+
return;
|
|
978
|
+
this.parent();
|
|
979
|
+
depth--;
|
|
980
|
+
mustLeave = true;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
/// Test whether the current node matches a given context—a sequence
|
|
985
|
+
/// of direct parent node names. Empty strings in the context array
|
|
986
|
+
/// are treated as wildcards.
|
|
987
|
+
matchContext(context) {
|
|
988
|
+
if (!this.buffer)
|
|
989
|
+
return matchNodeContext(this.node, context);
|
|
990
|
+
let { buffer } = this.buffer, { types } = buffer.set;
|
|
991
|
+
for (let i = context.length - 1, d = this.stack.length - 1; i >= 0; d--) {
|
|
992
|
+
if (d < 0)
|
|
993
|
+
return matchNodeContext(this.node, context, i);
|
|
994
|
+
let type = types[buffer.buffer[this.stack[d]]];
|
|
995
|
+
if (!type.isAnonymous) {
|
|
996
|
+
if (context[i] && context[i] != type.name)
|
|
997
|
+
return false;
|
|
998
|
+
i--;
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
return true;
|
|
914
1002
|
}
|
|
915
1003
|
}
|
|
916
1004
|
function hasChild(tree) {
|
|
@@ -1170,6 +1258,48 @@ mkTree) {
|
|
|
1170
1258
|
divide(children, positions, from, to, 0);
|
|
1171
1259
|
return (mkTop || mkTree)(localChildren, localPositions, length);
|
|
1172
1260
|
}
|
|
1261
|
+
/// Provides a way to associate values with pieces of trees. As long
|
|
1262
|
+
/// as that part of the tree is reused, the associated values can be
|
|
1263
|
+
/// retrieved from an updated tree.
|
|
1264
|
+
class NodeWeakMap {
|
|
1265
|
+
constructor() {
|
|
1266
|
+
this.map = new WeakMap();
|
|
1267
|
+
}
|
|
1268
|
+
setBuffer(buffer, index, value) {
|
|
1269
|
+
let inner = this.map.get(buffer);
|
|
1270
|
+
if (!inner)
|
|
1271
|
+
this.map.set(buffer, inner = new Map);
|
|
1272
|
+
inner.set(index, value);
|
|
1273
|
+
}
|
|
1274
|
+
getBuffer(buffer, index) {
|
|
1275
|
+
let inner = this.map.get(buffer);
|
|
1276
|
+
return inner && inner.get(index);
|
|
1277
|
+
}
|
|
1278
|
+
/// Set the value for this syntax node.
|
|
1279
|
+
set(node, value) {
|
|
1280
|
+
if (node instanceof BufferNode)
|
|
1281
|
+
this.setBuffer(node.context.buffer, node.index, value);
|
|
1282
|
+
else if (node instanceof TreeNode)
|
|
1283
|
+
this.map.set(node.tree, value);
|
|
1284
|
+
}
|
|
1285
|
+
/// Retrieve value for this syntax node, if it exists in the map.
|
|
1286
|
+
get(node) {
|
|
1287
|
+
return node instanceof BufferNode ? this.getBuffer(node.context.buffer, node.index)
|
|
1288
|
+
: node instanceof TreeNode ? this.map.get(node.tree) : undefined;
|
|
1289
|
+
}
|
|
1290
|
+
/// Set the value for the node that a cursor currently points to.
|
|
1291
|
+
cursorSet(cursor, value) {
|
|
1292
|
+
if (cursor.buffer)
|
|
1293
|
+
this.setBuffer(cursor.buffer.buffer, cursor.index, value);
|
|
1294
|
+
else
|
|
1295
|
+
this.map.set(cursor.tree, value);
|
|
1296
|
+
}
|
|
1297
|
+
/// Retrieve the value for the node that a cursor currently points
|
|
1298
|
+
/// to.
|
|
1299
|
+
cursorGet(cursor) {
|
|
1300
|
+
return cursor.buffer ? this.getBuffer(cursor.buffer.buffer, cursor.index) : this.map.get(cursor.tree);
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1173
1303
|
|
|
1174
1304
|
/// Tree fragments are used during [incremental
|
|
1175
1305
|
/// parsing](#common.Parser.startParse) to track parts of old trees
|
|
@@ -1179,7 +1309,10 @@ mkTree) {
|
|
|
1179
1309
|
/// [`applyChanges`](#common.TreeFragment^applyChanges) method to
|
|
1180
1310
|
/// update fragments for document changes.
|
|
1181
1311
|
class TreeFragment {
|
|
1182
|
-
/// Construct a tree fragment.
|
|
1312
|
+
/// Construct a tree fragment. You'll usually want to use
|
|
1313
|
+
/// [`addTree`](#common.TreeFragment^addTree) and
|
|
1314
|
+
/// [`applyChanges`](#common.TreeFragment^applyChanges) instead of
|
|
1315
|
+
/// calling this directly.
|
|
1183
1316
|
constructor(
|
|
1184
1317
|
/// The start of the unchanged range pointed to by this fragment.
|
|
1185
1318
|
/// This refers to an offset in the _updated_ document (as opposed
|
|
@@ -1294,11 +1427,6 @@ class StringInput {
|
|
|
1294
1427
|
/// function, runs the resulting [inner parses](#common.NestedParse),
|
|
1295
1428
|
/// and then [mounts](#common.NodeProp^mounted) their results onto the
|
|
1296
1429
|
/// tree.
|
|
1297
|
-
///
|
|
1298
|
-
/// The nesting function is passed a cursor to provide context for a
|
|
1299
|
-
/// node, but _should not_ move that cursor, only inspect its
|
|
1300
|
-
/// properties and optionally access its
|
|
1301
|
-
/// [node object](#common.TreeCursor.node).
|
|
1302
1430
|
function parseMixed(nest) {
|
|
1303
1431
|
return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges);
|
|
1304
1432
|
}
|
|
@@ -1390,7 +1518,7 @@ class MixedParse {
|
|
|
1390
1518
|
let fragmentCursor = new FragmentCursor(this.fragments);
|
|
1391
1519
|
let overlay = null;
|
|
1392
1520
|
let covered = null;
|
|
1393
|
-
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null),
|
|
1521
|
+
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), exports.IterMode.IncludeAnonymous | exports.IterMode.IgnoreMounts);
|
|
1394
1522
|
scan: for (let nest, isCovered; this.stoppedAt == null || cursor.from < this.stoppedAt;) {
|
|
1395
1523
|
let enter = true, range;
|
|
1396
1524
|
if (fragmentCursor.hasNode(cursor)) {
|
|
@@ -1518,13 +1646,13 @@ class StructureCursor {
|
|
|
1518
1646
|
constructor(root, offset) {
|
|
1519
1647
|
this.offset = offset;
|
|
1520
1648
|
this.done = false;
|
|
1521
|
-
this.cursor = root.
|
|
1649
|
+
this.cursor = root.cursor(exports.IterMode.IncludeAnonymous | exports.IterMode.IgnoreMounts);
|
|
1522
1650
|
}
|
|
1523
1651
|
// Move to the first node (in pre-order) that starts at or after `pos`.
|
|
1524
1652
|
moveTo(pos) {
|
|
1525
1653
|
let { cursor } = this, p = pos - this.offset;
|
|
1526
1654
|
while (!this.done && cursor.from < p) {
|
|
1527
|
-
if (cursor.to >= pos && cursor.enter(p, 1,
|
|
1655
|
+
if (cursor.to >= pos && cursor.enter(p, 1, exports.IterMode.IgnoreOverlays | exports.IterMode.ExcludeBuffers)) ;
|
|
1528
1656
|
else if (!cursor.next(false))
|
|
1529
1657
|
this.done = true;
|
|
1530
1658
|
}
|
|
@@ -1693,6 +1821,7 @@ exports.MountedTree = MountedTree;
|
|
|
1693
1821
|
exports.NodeProp = NodeProp;
|
|
1694
1822
|
exports.NodeSet = NodeSet;
|
|
1695
1823
|
exports.NodeType = NodeType;
|
|
1824
|
+
exports.NodeWeakMap = NodeWeakMap;
|
|
1696
1825
|
exports.Parser = Parser;
|
|
1697
1826
|
exports.Tree = Tree;
|
|
1698
1827
|
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";
|