internal/refactor/inline: use refactor.DeleteSpec for imports Now that the inliner has a cursor for the call, it can use refactor.DeleteSpec to delete an import made redundant by inlining, instead of its own hand-written logic. DeleteSpec deletes a non-final spec up to the start of the next one, so it no longer leaves behind a whitespace-only line, which gofmt would turn into a blank line, splitting the import block into two groups. Test expectations are updated accordingly. Change-Id: I6d4decd4a53580953243d066ce4b4a62575dfa7f Reviewed-on: https://go-review.googlesource.com/c/tools/+/846547 Reviewed-by: Hongxiang Jiang <hxjiang@golang.org> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/gopls/internal/test/marker/testdata/codeaction/inline_issue67336.txt b/gopls/internal/test/marker/testdata/codeaction/inline_issue67336.txt index 7ff4d21..5001634 100644 --- a/gopls/internal/test/marker/testdata/codeaction/inline_issue67336.txt +++ b/gopls/internal/test/marker/testdata/codeaction/inline_issue67336.txt
@@ -55,7 +55,6 @@ package c import ( "context" - "example.com/one/more/pkg" pkg0 "example.com/some/other/pkg" "example.com/define/my/typ"
diff --git a/internal/refactor/inline/inline.go b/internal/refactor/inline/inline.go index ac073f9..c5baf15 100644 --- a/internal/refactor/inline/inline.go +++ b/internal/refactor/inline/inline.go
@@ -25,6 +25,7 @@ "golang.org/x/tools/internal/astutil" internalastutil "golang.org/x/tools/internal/astutil" "golang.org/x/tools/internal/astutil/free" + "golang.org/x/tools/internal/moreiters" "golang.org/x/tools/internal/packagepath" "golang.org/x/tools/internal/refactor" "golang.org/x/tools/internal/typeparams" @@ -291,46 +292,9 @@ // remove unneeded imports in this case because it is common // to inlining a call from "dir1/a".F to "dir2/a".F, which // leaves two imports of packages named 'a', both providing a.F. - // - // However, the only two import deletion tools at our disposal - // are astutil.DeleteNamedImport, which mutates the AST, and - // refactor.Delete{Spec,Decl}, which need a Cursor. So we need - // to reinvent the wheel here. + tokFile := caller.Fset.File(caller.file.FileStart) for _, oldImport := range res.oldImports { - spec := oldImport.spec - - // Include adjacent comments. - pos := spec.Pos() - if doc := spec.Doc; doc != nil { - pos = doc.Pos() - } - end := spec.End() - if doc := spec.Comment; doc != nil { - end = doc.End() - } - - // Find the enclosing import decl. - // If it's paren-less, we must delete it too. - for _, decl := range caller.file.Decls { - decl, ok := decl.(*ast.GenDecl) - if !(ok && decl.Tok == token.IMPORT) { - break // stop at first non-import decl - } - if internalastutil.NodeContainsPos(decl, spec.Pos()) && !decl.Rparen.IsValid() { - // Include adjacent comments. - pos = decl.Pos() - if doc := decl.Doc; doc != nil { - pos = doc.Pos() - } - end = decl.End() - break - } - } - - edits = append(edits, refactor.Edit{ - Pos: pos, - End: end, - }) + edits = append(edits, refactor.DeleteSpec(tokFile, oldImport.curSpec)...) } return &Result{ @@ -343,7 +307,7 @@ // An oldImport is an import that will be deleted from the caller file. type oldImport struct { pkgName *types.PkgName - spec *ast.ImportSpec + curSpec inspector.Cursor // cursor for *ast.ImportSpec } // A newImport is an import that will be added to the caller file. @@ -388,7 +352,9 @@ } } - for _, imp := range caller.file.Imports { + curFile, _ := moreiters.First(caller.Call.Enclosing((*ast.File)(nil))) + for curSpec := range curFile.Preorder((*ast.ImportSpec)(nil)) { + imp := curSpec.Node().(*ast.ImportSpec) if pkgName, ok := importedPkgName(caller.Info, imp); ok && pkgName.Name() != "." && pkgName.Name() != "_" { @@ -425,7 +391,7 @@ path := pkgName.Imported().Path() ist.importMap[path] = append(ist.importMap[path], pkgName.Name()) } else { - ist.oldImports = append(ist.oldImports, oldImport{pkgName: pkgName, spec: imp}) + ist.oldImports = append(ist.oldImports, oldImport{pkgName: pkgName, curSpec: curSpec}) } } }
diff --git a/internal/refactor/inline/testdata/import-comments2.txtar b/internal/refactor/inline/testdata/import-comments2.txtar index 4798f8e..ace70fa 100644 --- a/internal/refactor/inline/testdata/import-comments2.txtar +++ b/internal/refactor/inline/testdata/import-comments2.txtar
@@ -54,9 +54,8 @@ import ( "context" "testdata/define/my/typ" - pkg0 "testdata/some/other/pkg" - "testdata/one/more/pkg" + pkg0 "testdata/some/other/pkg" ) const (
diff --git a/internal/refactor/inline/testdata/import-shadow.txtar b/internal/refactor/inline/testdata/import-shadow.txtar index fc50b38..c4ea9a6 100644 --- a/internal/refactor/inline/testdata/import-shadow.txtar +++ b/internal/refactor/inline/testdata/import-shadow.txtar
@@ -39,9 +39,8 @@ package a import ( - log0 "log" - "log" + log0 "log" ) func A() {