使用ast包删除未使用的进口商品?

时间:2019-04-12 05:51:54

标签: go abstract-syntax-tree

在解析了文件并删除了一些功能之后,是否有可能在写入新文件之前也删除所有当前未使用的导入文件?

1 个答案:

答案 0 :(得分:0)

我最近在编写代码生成器工具时需要类似的东西。这是我的解决方案的概述:

  • golang.org/x/tools/imports导出函数Process,该函数将获取Go源文件(作为[]byte),并自动“修复”导入:删除未使用的导入,并添加在其中引用的未列出的导入源文件。 goimports命令基于此。
  • 在编辑AST(例如删除一些功能)之后,我首先使用go/format将AST打印到Go源文件字符串中。请注意,这不会写入磁盘文件。它会在内存中生成AST的字符串形式。
  • 接下来,我使用imports.Process“修复”文件的导入。重要的是,将Go源文件的真实文件路径传递到Process,即使磁盘上尚不存在该路径。调用的结果是一个“固定的” Go源文件,为[]byte“字符串”;即删除所有未使用的进口商品。
  • 现在,我对原始AST和此“固定”源文件的导入执行“差异”。为了进行比较,比较AST更加容易,因此我首先使用go/parser在“固定”源文件上使用parser.ParseFile。我使用Go源文件的真实文件路径,并在调用token.NewFileSet()时使用空的ParseFile。同样,Go源文件也不必在磁盘上存在。
  • AST差异仅比较两个文件根AST节点之间的[]*ast.ImportSpec切片(字段ast.File.Imports)。 (我的实现使用map首先为每个[]*ast.ImportSpec编制索引,从而更容易进行交叉检查,而无需双重嵌套循环。)
  • 最后,现在我有了一个已被删除(未使用)的*ast.ImportSpec列表,我使用golang.org/x/tools/go/ast/astutil重写了原始AST,并使用光标删除了这些已知的*ast.ImportSpec节点。

顺便说一句:以上has an "internal" package所引用的imports包将提供一个FixImports函数,该函数本质上提供了上面手动得出的原始“ diff”。不幸的是,因为它被标记为内部,所以我们无法使用它。