OrenIshShalom
OrenIshShalom

Reputation: 7112

abstract syntax tree (AST) scan

I'm trying to extract function calls from go AST:

$ cat main.go
package main
import ("fmt"; "go/ast"; "go/token"; "go/parser"; "io/ioutil")

func CalledFuncs(n ast.Node) bool {
    switch n.(type) {
    case *ast.CallExpr:
        l := ast.CallExpr(n).Lparen
        r := ast.CallExpr(n).Right
        fmt.Printf("call %d( ... %d)\n",l,r)
    }
    return true
}

func main() {
    fset := token.NewFileSet()
    src,_ := ioutil.ReadFile("simple.go")
    f, _ := parser.ParseFile(fset,">>",src,0)
    ast.Inspect(f, CalledFuncs)
}

But the go compiler complains I can't do the casting:

$ go build -o main main.go
# command-line-arguments
./main.go:7:26: cannot convert n (type ast.Node) to type ast.CallExpr
./main.go:8:26: cannot convert n (type ast.Node) to type ast.CallExpr

I'm probably missing something here.

Upvotes: 0

Views: 360

Answers (1)

mkopriva
mkopriva

Reputation: 38223

https://golang.org/ref/spec#Type_switches

The TypeSwitchGuard may include a short variable declaration. When that form is used, the variable is declared at the end of the TypeSwitchCase in the implicit block of each clause. In clauses with a case listing exactly one type, the variable has that type; otherwise, the variable has the type of the expression in the TypeSwitchGuard.

That means that you can do the following:

func CalledFuncs(n ast.Node) bool {
    switch x := n.(type) {
    case *ast.CallExpr:
        l := x.Lparen
        r := x.Rparen
        fmt.Printf("call %d( ... %d)\n", l, r)
    }
    return true
}

Upvotes: 1

Related Questions