@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 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) rooted at this tree. When
276
- /// `pos` is given, the cursor is [moved](#common.TreeCursor.moveTo)
277
- /// to the given position and side.
278
- cursor(pos, side = 0) {
279
- let scope = (pos != null && CachedNode.get(this)) || this.topNode;
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
- if (pos != null) {
282
- cursor.moveTo(pos, side);
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(), get = () => c.node;;) {
327
- let mustLeave = false;
328
- if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c.type, c.from, c.to, get) !== false)) {
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
- if (!c.type.isAnonymous)
332
- mustLeave = true;
350
+ entered = true;
333
351
  }
334
352
  for (;;) {
335
- if (mustLeave && leave)
336
- leave(c.type, c.from, c.to, get);
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
- mustLeave = true;
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, true)) === null || _a === void 0 ? void 0 : _a.from) != scan.from)
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, overlays);
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(node, _from,
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.node = node;
511
- this._from = _from;
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.node.type; }
516
- get name() { return this.node.type.name; }
517
- get from() { return this._from; }
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.node, e = dir > 0 ? children.length : -1; i != e; i += dir) {
522
- let next = children[i], start = positions[i] + parent._from;
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 & 2 /* NoEnterBuffer */)
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 & 1 /* Full */) || (!next.type.isAnonymous || hasChild(next))) {
549
+ else if ((mode & exports.IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
533
550
  let mounted;
534
- if (!(mode & 1 /* Full */) && next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
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 & 1 /* Full */) || !inner.type.isAnonymous ? inner
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 & 1 /* Full */) || !parent.type.isAnonymous)
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.node.children.length;
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.node.children.length - 1, -1, 0, 4 /* DontCare */); }
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.node.children.length - 1, -1, pos, -2 /* Before */); }
556
- enter(pos, side, overlays = true, buffers = true) {
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 (overlays && (mounted = this.node.prop(NodeProp.mounted)) && mounted.overlay) {
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, buffers ? 0 : 2 /* NoEnterBuffer */);
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
- get cursor() { return new TreeCursor(this); }
584
- get tree() { return this.node; }
585
- toTree() { return this.node; }
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.node.toString(); }
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, overlays, buffers = true) {
648
- if (!buffers)
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
- get cursor() { return new TreeCursor(this); }
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.node.children.length - 1 : 0, dir, pos, side, this.mode));
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, overlays = true, buffers = true) {
822
+ enter(pos, side, mode = this.mode) {
787
823
  if (!this.buffer)
788
- return this.yield(this._tree.enter(pos, side, overlays && !(this.mode & 1 /* Full */), buffers));
789
- return buffers ? this.enterChild(1, pos, side) : false;
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 & 1 /* Full */) ? this._tree._parent : this._tree.parent);
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 & 1 /* Full */) ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
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.node.children.length; i != e; i += dir) {
844
- let child = parent.node.children[i];
845
- if ((this.mode & 1 /* Full */) || child instanceof TreeBuffer || !child.type.isAnonymous || hasChild(child))
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.node;
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), 1 /* Full */);
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.fullCursor();
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, false, false)) ;
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) rooted at this tree. When
272
- /// `pos` is given, the cursor is [moved](#common.TreeCursor.moveTo)
273
- /// to the given position and side.
274
- cursor(pos, side = 0) {
275
- let scope = (pos != null && CachedNode.get(this)) || this.topNode;
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
- if (pos != null) {
278
- cursor.moveTo(pos, side);
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(), get = () => c.node;;) {
323
- let mustLeave = false;
324
- if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c.type, c.from, c.to, get) !== false)) {
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
- if (!c.type.isAnonymous)
328
- mustLeave = true;
346
+ entered = true;
329
347
  }
330
348
  for (;;) {
331
- if (mustLeave && leave)
332
- leave(c.type, c.from, c.to, get);
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
- mustLeave = true;
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, true)) === null || _a === void 0 ? void 0 : _a.from) != scan.from)
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, overlays);
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(node, _from,
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.node = node;
507
- this._from = _from;
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.node.type; }
512
- get name() { return this.node.type.name; }
513
- get from() { return this._from; }
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.node, e = dir > 0 ? children.length : -1; i != e; i += dir) {
518
- let next = children[i], start = positions[i] + parent._from;
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 & 2 /* NoEnterBuffer */)
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 & 1 /* Full */) || (!next.type.isAnonymous || hasChild(next))) {
545
+ else if ((mode & IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
529
546
  let mounted;
530
- if (!(mode & 1 /* Full */) && next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
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 & 1 /* Full */) || !inner.type.isAnonymous ? inner
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 & 1 /* Full */) || !parent.type.isAnonymous)
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.node.children.length;
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.node.children.length - 1, -1, 0, 4 /* DontCare */); }
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.node.children.length - 1, -1, pos, -2 /* Before */); }
552
- enter(pos, side, overlays = true, buffers = true) {
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 (overlays && (mounted = this.node.prop(NodeProp.mounted)) && mounted.overlay) {
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, buffers ? 0 : 2 /* NoEnterBuffer */);
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
- get cursor() { return new TreeCursor(this); }
580
- get tree() { return this.node; }
581
- toTree() { return this.node; }
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.node.toString(); }
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, overlays, buffers = true) {
644
- if (!buffers)
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
- get cursor() { return new TreeCursor(this); }
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.node.children.length - 1 : 0, dir, pos, side, this.mode));
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, overlays = true, buffers = true) {
818
+ enter(pos, side, mode = this.mode) {
783
819
  if (!this.buffer)
784
- return this.yield(this._tree.enter(pos, side, overlays && !(this.mode & 1 /* Full */), buffers));
785
- return buffers ? this.enterChild(1, pos, side) : false;
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 & 1 /* Full */) ? this._tree._parent : this._tree.parent);
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 & 1 /* Full */) ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
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.node.children.length; i != e; i += dir) {
840
- let child = parent.node.children[i];
841
- if ((this.mode & 1 /* Full */) || child instanceof TreeBuffer || !child.type.isAnonymous || hasChild(child))
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.node;
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), 1 /* Full */);
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.fullCursor();
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, false, false)) ;
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 { TreeCursor } from "./tree";
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: TreeCursor) => {
8
+ }[] | ((node: SyntaxNodeRef) => {
9
9
  from: number;
10
10
  to: number;
11
11
  } | boolean);
12
12
  }
13
- export declare function parseMixed(nest: (node: TreeCursor, input: Input) => NestedParse | null): ParseWrapper;
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(pos?: number, side?: -1 | 0 | 1): TreeCursor;
73
- fullCursor(): TreeCursor;
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(type: NodeType, from: number, to: number, get: () => SyntaxNode): false | void;
79
- leave?(type: NodeType, from: number, to: number, get: () => SyntaxNode): void;
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 SyntaxNode {
117
- type: NodeType;
118
- name: string;
119
- from: number;
120
- to: number;
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, overlays?: boolean, buffers?: boolean): SyntaxNode | null;
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 node: Tree;
152
- readonly _from: number;
158
+ readonly _tree: Tree;
159
+ readonly from: number;
153
160
  readonly index: number;
154
161
  readonly _parent: TreeNode | null;
155
- constructor(node: Tree, _from: number, index: number, _parent: TreeNode | null);
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?: Mode): TreeNode | BufferNode | null;
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, overlays?: boolean, buffers?: boolean): TreeNode | BufferNode;
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
- get cursor(): TreeCursor;
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, overlays?: boolean, buffers?: boolean): BufferNode;
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
- get cursor(): TreeCursor;
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, overlays?: boolean, buffers?: boolean): boolean;
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 {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lezer/common",
3
- "version": "0.15.12",
3
+ "version": "0.16.0",
4
4
  "description": "Syntax tree data structure and parser interfaces for the lezer parser",
5
5
  "main": "dist/index.cjs",
6
6
  "type": "module",