When I parse go source file with the parser
package, the package xxx
statement was considered as a normal *ast.Ident
. Is there any way to distinguish it from other declarations? Or gracefully ignore the package statement while parsing?
func walk(node ast.Node) bool {
switch n := node.(type) {
case *ast.File:
return true
case *ast.Ident:
// I want to check whether it is a package statement
case *ast.GenDecl:
return true
case *ast.TypeSpec:
return true
case *ast.StructType:
return true
case *ast.FieldList:
return true
case *ast.Field:
if len(n.Names) > 0 {
fmt.Println(n.Names[0].String())
}
default:
fmt.Printf("%T
", node)
}
return false
}
func parseFile(filename string) error {
fs := token.NewFileSet()
f, err := parser.ParseFile(fs, filename, nil, parser.ParseComments)
if err != nil {
return err
}
ast.Inspect(f, walk)
return nil
}
To skip over the package identifier, the application must write the code to iterate over the *ast.File children and skip the package identifier in that code:
func walk(node ast.Node) bool {
switch n := node.(type) {
case *ast.File:
walkFileNoPackageName(n)
// Return false to prevent caller from also
// walking children of n.
return false
... other cases as in question
func walkFileNoPackageName(n *ast.File) {
if n.Doc != nil {
ast.Inspect(n.Doc, walk)
}
// ast.Inspect(n.Name, walk) Skip over name
for _, x := range n.Decls {
ast.Inspect(x, walk)
}
}
If you are only interested in package-level declarations in the file, then start the inspection from those declarations:
f, err := parser.ParseFile(fs, filename, nil, parser.ParseComments)
if err != nil {
return err
}
for _, n := range f.Decls {
ast.Inspect(n, walk)
}
Use the walk
function from the question as is.