Search code examples
goabstract-syntax-treego-toolchain

How to retrieve parent node from child node in golang ast traversal?


Here is test file

func demo()  {
    name:=xxx()
    fmt.Println(name)
}

And my ast traversal code

ast.Inspect(f, func(node ast.Node) bool {
    assign, ok := node.(*ast.AssignStmt) // find -> name:=xxx()
    if !ok {
        return true
    }
    if assign == nil {
        return true
    }
    var expr = assign.Lhs[0]
    fmt.Println(expr) // find -> name
    fmt.Println(nodeString(assign,pass.Fset))
    return true
})

I find I have to travel ast from up to down like this. Find AssignStmt and then get AssignStmt->Lhs

But I need to find ast.Ident(name) first and then to find whether its parent is AssignStmt in some cases.

I am not sure is it possible that I can go from bottom to top.


Solution

  • Manage a stack of ancestor nodes as the inspector is called:

    var stack []ast.Node
    ast.Inspect(f, func(n ast.Node) bool {
    
        // Look for the identifier.
    
        if n, ok := n.(*ast.Ident); ok {
            if n.Name == "name" {
    
                // Parent is stack[len(stack)-1]
    
                fmt.Println("found name")
                for _, n := range stack {
                    fmt.Printf("%T\n", n)
                }
            }
        }
    
        // Manage the stack. Inspect calls a function like this:
        //   f(node)
        //   for each child {
        //      f(child) // and recursively for child's children
        //   }
        //   f(nil)
        if n == nil {
            // Done with node's children. Pop.
            stack = stack[:len(stack)-1]
        } else {
            // Push the current node for children.
            stack = append(stack, n)
        }
    
        return true
    })
    

    Run it on the playground.