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() {