smacker / go-tree-sitter

Golang bindings for tree-sitter https://github.com/tree-sitter/tree-sitter
MIT License
447 stars 124 forks source link

Querying does not always work as it should #149

Closed indiejames closed 9 months ago

indiejames commented 9 months ago

I find that queries sometimes work as expected, but sometimes do not. For example in the following code:

package main

import (
    "context"
    "fmt"

    sitter "github.com/smacker/go-tree-sitter"
    "github.com/smacker/go-tree-sitter/golang"
)

var source = []byte(`package main

import "fmt"
// A comment
func main() {
    fmt.Println("Hello, world!")
}`)

func walkTree(node *sitter.Node, code []byte, depth int) {
    count := node.ChildCount()
    var childCount int = int(count)
    var tabs string = ""
    if depth > 0 {
        tabs = "│\n├"
    }
    for i := 0; i < depth; i++ {
        tabs = tabs + "──"
    }
    t := node.Type()
    if t == "\n" {
        t = ""
    }
    parentType := "nil"
    if node.Parent() != nil {
        parentType = node.Parent().Type()
    }
    fmt.Printf("%s Type: %s Parent Type: %s Text: %s\n", tabs, t, parentType, code[node.StartByte():node.EndByte()])
    for i := 0; i < childCount; i++ {
        walkTree(node.Child(i), code, depth+1)
    }
}

func main() {
    prs := sitter.NewParser()
    lng := golang.GetLanguage()
    prs.SetLanguage(lng)
    t, _ := prs.ParseCtx(context.Background(), nil, source)
    q1, _ := sitter.NewQuery([]byte("(comment)"), lng)
    nd := t.RootNode()

    fmt.Println("========= COMMENTS ==========")
    crs := sitter.NewQueryCursor()
    crs.Exec(q1, nd)
    m1, _ := crs.NextMatch()
    fmt.Printf("m1.Captures: %v\n\n", m1.Captures)

    fmt.Println("========= TREE ==========")
    walkTree(nd, source, 0)

}

This tries to query using `(comment)`, then it walks the tree printing out the nodes.

The abridged output is the following:

========= COMMENTS ========== m1.Captures: []

========= TREE ========== Type: source_file Parent Type: nil Text: package main

import "fmt" // A comment func main() { fmt.Println("Hello, world!") } │ ├── Type: package_clause Parent Type: source_file Text: package main │ ├──── Type: package Parent Type: package_clause Text: package │ ├──── Type: package_identifier Parent Type: package_clause Text: main │ ├── Type: Parent Type: source_file Text:

...

├── Type: comment Parent Type: source_file Text: // A comment

...



You can see that the parsing sees the node of type `comment` is there, but the query using `(comment`) doesn't return any captures.

Some of the other queries I have tried work, some do not.

The `(comment)` query is taking from the `.scm` file in the tree sitter queries provided with the helix editor.

Am I doing something wrong, or is this a bug?
indiejames commented 9 months ago

Curious, I find now that if I query with (comment) @comment instead of just (comment) it does work. Apparently the tag is required. I'll close this ticket I guess.