From e852fdd89f1a2f53b9538a99c21a44a9f199218b Mon Sep 17 00:00:00 2001 From: "David R. Jenni" Date: Thu, 25 Feb 2016 20:09:00 +0100 Subject: [PATCH] go/ast/astutil: add function DeleteNamedImport. DeleteNamedImport deletes the import with a given name and path from a parsed file, if present. imports uses this function to delete named imports. Fixes golang/go#8149. Change-Id: I84539d5627191c45f06db2d008507aee4d3b1eb2 Reviewed-on: https://go-review.googlesource.com/19951 Reviewed-by: Brad Fitzpatrick --- go/ast/astutil/imports.go | 11 +++++++++++ go/ast/astutil/imports_test.go | 32 +++++++++++++++++++++++++++++++- imports/fix.go | 12 ++++++++---- imports/fix_test.go | 21 +++++++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/go/ast/astutil/imports.go b/go/ast/astutil/imports.go index 457cc6b532..c371bc1665 100644 --- a/go/ast/astutil/imports.go +++ b/go/ast/astutil/imports.go @@ -148,6 +148,11 @@ func AddNamedImport(fset *token.FileSet, f *ast.File, name, ipath string) (added // DeleteImport deletes the import path from the file f, if present. func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) { + return DeleteNamedImport(fset, f, "", path) +} + +// DeleteNamedImport deletes the import with the given name and path from the file f, if present. +func DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (deleted bool) { var delspecs []*ast.ImportSpec // Find the import nodes that import path, if any. @@ -160,6 +165,12 @@ func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) for j := 0; j < len(gen.Specs); j++ { spec := gen.Specs[j] impspec := spec.(*ast.ImportSpec) + if impspec.Name == nil && name != "" { + continue + } + if impspec.Name != nil && impspec.Name.Name != name { + continue + } if importPath(impspec) != path { continue } diff --git a/go/ast/astutil/imports_test.go b/go/ast/astutil/imports_test.go index 0a1c7b6597..589a0289b7 100644 --- a/go/ast/astutil/imports_test.go +++ b/go/ast/astutil/imports_test.go @@ -761,6 +761,36 @@ import ( ) `, out: `package main +`, + }, + { + name: "import.18", + renamedPkg: "x", + pkg: "fmt", + in: `package main + +import ( + "fmt" + x "fmt" +) +`, + out: `package main + +import "fmt" +`, + }, + { + name: "import.18", + renamedPkg: "x", + pkg: "fmt", + in: `package main + +import x "fmt" +import y "fmt" +`, + out: `package main + +import y "fmt" `, }, } @@ -768,7 +798,7 @@ import ( func TestDeleteImport(t *testing.T) { for _, test := range deleteTests { file := parse(t, test.name, test.in) - DeleteImport(fset, file, test.pkg) + DeleteNamedImport(fset, file, test.renamedPkg, test.pkg) if got := print(t, test.name, file); got != test.out { t.Errorf("%s:\ngot: %s\nwant: %s", test.name, got, test.out) } diff --git a/imports/fix.go b/imports/fix.go index a201f9efee..4fc50570d7 100644 --- a/imports/fix.go +++ b/imports/fix.go @@ -90,18 +90,22 @@ func fixImports(fset *token.FileSet, f *ast.File, filename string) (added []stri ast.Walk(visitor, f) // Nil out any unused ImportSpecs, to be removed in following passes - unusedImport := map[string]bool{} + unusedImport := map[string]string{} for pkg, is := range decls { if refs[pkg] == nil && pkg != "_" && pkg != "." { - unusedImport[strings.Trim(is.Path.Value, `"`)] = true + name := "" + if is.Name != nil { + name = is.Name.Name + } + unusedImport[strings.Trim(is.Path.Value, `"`)] = name } } - for ipath := range unusedImport { + for ipath, name := range unusedImport { if ipath == "C" { // Don't remove cgo stuff. continue } - astutil.DeleteImport(fset, f, ipath) + astutil.DeleteNamedImport(fset, f, name, ipath) } // Search for imports matching potential package references. diff --git a/imports/fix_test.go b/imports/fix_test.go index 91ce9d4c10..d6852d3f20 100644 --- a/imports/fix_test.go +++ b/imports/fix_test.go @@ -726,6 +726,27 @@ func main() { fmt.Println() } import "fmt" +func main() { fmt.Println() } +`, + }, + + // Unused named import is mistaken for unnamed import + // golang.org/issue/8149 + { + name: "issue 8149", + in: `package main + +import ( + "fmt" + x "fmt" +) + +func main() { fmt.Println() } +`, + out: `package main + +import "fmt" + func main() { fmt.Println() } `, },