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

Code before:
    })
  }

  syntaxTreeForPosition (point) {
    if (!this.tree) return this.rootScopeDescriptor
    point = Point.fromObject(point)

    const iterators = []
    this._forEachTreeWithRange(new Range(point, point), tree => {
      const rootStartIndex = tree.rootNode.startIndex
      let node = tree.rootNode.descendantForPosition(point)

      // Don't include anonymous token types like '(' because they prevent scope chains
      // from being parsed as CSS selectors by the `slick` parser. Other css selector
      // parsers like `postcss-selector-parser` do allow arbitrary quoted strings in
      // selectors.
      if (!node.isNamed) node = node.parent
      iterators.push({node, rootStartIndex})
    })

    iterators.sort(compareScopeDescriptorIterators)
    const scopes = []

    for (;;) {
      const {length} = iterators
      if (!length) break
      const iterator = iterators[length - 1]
      scopes.push(iterator.node.type)
      iterator.node = iterator.node.parent
      if (iterator.node) {
        let i = length - 1
        while (i > 0 && compareScopeDescriptorIterators(iterator, iterators[i - 1]) < 0) i--
        if (i < length - 1) iterators.splice(i, 0, iterators.pop())
      } else {
        iterators.pop()
      }
    }

    scopes.push(this.grammar.scopeName)
    return new ScopeDescriptor({scopes: scopes.reverse()})
  }

  scopeDescriptorForPosition (point) {
    const iterator = this.buildHighlightIterator()
    const scopes = []
    for (const scope of iterator.seek(point)) {
      scopes.push(this.grammar.scopeNameForScopeId(scope))
    }
    for (const scope of iterator.getOpenScopeIds()) {
      scopes.push(this.grammar.scopeNameForScopeId(scope))
    }

Review comment (suggestion):
I think this could be simplified a bit now. We don't necessarily need to exclude anonymous nodes like `(` because we're not using the output in `getScopeDescriptor`.

I think something like this should work:

```js
const nodes = []
this._forEachTreeWithRange(new Range(point, point), tree => {
  let node = tree.rootNode.descendantForPosition(point)
  while (node) {
    nodes.push(node)
    node = node.parent
  }
})

// The nodes are mostly already sorted from smallest to largest,
// but for files with multiple syntax trees (e.g. ERB), each tree's
// nodes are separate. Sort the nodes from largest to smallest.
nodes.reverse()
nodes.sort((a, b) =>
  a.startIndex - b.startIndex || b.endIndex - a.endIndex
)

const nodeTypes = nodes.map(node => node.type)
return new ScopeDescriptor({scopes: nodeTypes})
```

Code after:
    })
  }

  syntaxTreeScopeDescriptorForPosition (point) {
    const nodes = []
    point = Point.fromObject(point)
    this._forEachTreeWithRange(new Range(point, point), tree => {
      let node = tree.rootNode.descendantForPosition(point)
      while (node) {
        nodes.push(node)
        node = node.parent
      }
    })

    // The nodes are mostly already sorted from smallest to largest,
    // but for files with multiple syntax trees (e.g. ERB), each tree's
    // nodes are separate. Sort the nodes from largest to smallest.
    nodes.reverse()
    nodes.sort((a, b) =>
      a.startIndex - b.startIndex || b.endIndex - a.endIndex
    )

    const nodeTypes = nodes.map(node => node.type)
    nodeTypes.unshift(this.grammar.scopeName)
    return new ScopeDescriptor({scopes: nodeTypes})
  }

  scopeDescriptorForPosition (point) {
    const iterator = this.buildHighlightIterator()
    const scopes = []
    for (const scope of iterator.seek(point)) {
      scopes.push(this.grammar.scopeNameForScopeId(scope))
    }
    for (const scope of iterator.getOpenScopeIds()) {
      scopes.push(this.grammar.scopeNameForScopeId(scope))
    }
    if (scopes.length === 0 || scopes[0] !== this.grammar.scopeName) {
      scopes.unshift(this.grammar.scopeName)
    }
    return new ScopeDescriptor({scopes})
  }

  tokenForPosition (point) {
    const node = this.getSyntaxNodeAtPosition(point)
    const scopes = this.scopeDescriptorForPosition(point).getScopesArray()
    return new Token({value: node.text, scopes})
  }

  getGrammar () {
    return this.grammar
  }