tree-sitter / node-tree-sitter

Node.js bindings for tree-sitter
https://www.npmjs.com/package/tree-sitter
MIT License
649 stars 114 forks source link

'closest' return nothing for `function` type #29

Closed t9md closed 6 years ago

t9md commented 6 years ago

I want to get function SyntaxNode by using closest. But, in the example below, it returns nothing. I could get function body by the manual way. I am also curious how closest treat unnamed node since I want to skip unnamed function node if I don't I get function keyword instead of the node which contains whole function body.

Reproduce

Open atom-editor and enable tree-sitter and place cursor at

class ClassName {
  constructor() {
    'foo'
  }
}

function func() {
  'bar'
}

code to repro

  1. Paste following code on dev-console and call getClosestFunction() by placing cursor at foo and bar.
  2. Observe console.log and see closest fail but closestManual success when the cursor is at bar.
function getClosestFunction() {
  const editor = atom.workspace.getActiveTextEditor()
  const position = editor.getCursorBufferPosition()
  const node = editor.languageMode.getSyntaxNodeAtPosition(position)
  // The names of these nodes will depend on the grammar

  const types = ['function', 'method_definition']
  const functionNodeByClosest = node.closest(types)
  const functionNodeByManual = closestManual(node, types)

  console.log('# try from node', node.text, 'at', position.toString())

  console.log("= by closest");
  if (functionNodeByClosest) {
    console.log(functionNodeByClosest.text)
  }
  console.log("= by manual");
  if (functionNodeByManual) {
    console.log(functionNodeByManual.text)
  }
}

function closestManual(node, types) {
  while (node) {
    if (node.isNamed && types.some(type => type === node.type)) {
      return node
    }

    if (node.parent) {
      node = node.parent
    } else {
      break
    }
  }
}
maxbrunsfeld commented 6 years ago

I am also curious how closest treat unnamed node since I want to skip unnamed function node if I don't I get function keyword instead of the node which contains whole function body.

Yeah, this is exactly the problem. I think that the current implementation is misinterpreting the string function to mean the unnamed "function" node. closest should only look for named nodes, since unnamed nodes can never have children.