Repository: atom/atom
File: src/tree-sitter-language-mode.js (JavaScript)

Code before:
      }
    );

    const containingTags = [];
    const containingTagStartIndices = [];
    const targetIndex = this.languageMode.buffer.characterIndexForPosition(
      targetPosition
    );

    this.iterators = [];
    const iterator = this.languageMode.rootLanguageLayer.buildHighlightIterator();
    if (iterator.seek(targetIndex, containingTags, containingTagStartIndices)) {
      this.iterators.push(iterator);
    }
    for (const marker of injectionMarkers) {
      const iterator = marker.languageLayer.buildHighlightIterator();
      if (
        iterator.seek(targetIndex, containingTags, containingTagStartIndices)
      ) {
        this.iterators.push(iterator);
      }
    }
    this.iterators.sort((a, b) => b.compare(a));
    return containingTags;
  }

  moveToSuccessor() {
    let leader = last(this.iterators);
    if (leader.moveToSuccessor()) {
      const leaderIndex = this.iterators.length - 1;
      let i = leaderIndex;
      while (i > 0 && this.iterators[i - 1].compare(leader) < 0) i--;
      if (i < leaderIndex) {
        this.iterators.splice(i, 0, this.iterators.pop());
        this.trackLayerDepth();
      }
    } else {
      this.iterators.pop();
      this.trackLayerDepth();
    }
  }

  trackLayerDepth() {
    let i = this.iterators.length - 1;
    let iterator = this.iterators[i];
    if (!iterator) return;
    const offset = iterator.getOffset();
    if (iterator.languageLayer.isOpaque) {
      this.opaqueLayerDepth = iterator.languageLayer.depth;
    }


Review comment (refactor):
I've also done a refactor which made it easier to implement the new functionality. I've changed the invariant of the `HighlightIterator` a bit. Previously, the the `iterators` array always contained one `HighlightLayerIterator` for *every* `HighlightLayer`. Layer iterators that were no longer active had a `done` flag set to `true`. Now, once a `HighlightLayerIterator` advances to the end of its syntax tree, I remove it from the `iterators` array. This removes the need for the `done` flag.

The reason for this diff is that `LayerIterator.seek` can now return `false`, which means that the iterator has already fallen off the end of its tree. If `seek` returns false, we avoid adding the iterator to the array at all.

Code after:
    const containingTags = [];
    const containingTagStartIndices = [];
    const targetIndex = this.languageMode.buffer.characterIndexForPosition(
      targetPosition
    );

    this.iterators = [];
    const iterator = this.languageMode.rootLanguageLayer.buildHighlightIterator();
    if (iterator.seek(targetIndex, containingTags, containingTagStartIndices)) {
      this.iterators.push(iterator);
    }

    // Populate the iterators array with all of the iterators whose syntax
    // trees span the given position.
    for (const marker of injectionMarkers) {
      const iterator = marker.languageLayer.buildHighlightIterator();
      if (
        iterator.seek(targetIndex, containingTags, containingTagStartIndices)
      ) {
        this.iterators.push(iterator);
      }
    }

    // Sort the iterators so that the last one in the array is the earliest
    // in the document, and represents the current position.
    this.iterators.sort((a, b) => b.compare(a));
    this.detectCoveredScope();

    return containingTags;
  }

  moveToSuccessor() {
    // Advance the earliest layer iterator to its next scope boundary.
    let leader = last(this.iterators);

    // Maintain the sorting of the iterators by their position in the document.
    if (leader.moveToSuccessor()) {
      const leaderIndex = this.iterators.length - 1;
      let i = leaderIndex;
      while (i > 0 && this.iterators[i - 1].compare(leader) < 0) i--;
      if (i < leaderIndex) {
        this.iterators.splice(i, 0, this.iterators.pop());
      }
    } else {
      // If the layer iterator was at the end of its syntax tree, then remove
      // it from the array.
      this.iterators.pop();
    }

    this.detectCoveredScope();
  }