dongwu3596 2019-05-20 03:06
浏览 28

通过解析器包解析源文件时,如何优雅地跳过包标识?

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
}
  • 写回答

1条回答 默认 最新

  • doumen6532 2019-05-20 05:20
    关注

    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)
        }
    }
    

    Run it on the playground.

    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.

    Run it on the playground.

    评论

报告相同问题?

悬赏问题

  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法