Repository: mvdan/gofumpt
Pull request #165 (2021-11-10 04:05:45)

isCgoImport accounts for back-quoted import string


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a71c72..f57e561 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
 # Changelog
 
-## [0.2.0] - 2021-11-??
+## [0.2.0] - 2021-11-10
 
 This is gofumpt's second major release, based on Go 1.17's gofmt.
 The jump from Go 1.15's gofmt should bring a mild speed-up,
diff --git a/format/format.go b/format/format.go
index 012b602..d94c471 100644
--- a/format/format.go
+++ b/format/format.go
@@ -50,6 +50,11 @@ type Options struct {
 // source file.
 func Source(src []byte, opts Options) ([]byte, error) {
 	fset := token.NewFileSet()
+
+	// Ensure our parsed files never start with base 1,
+	// to ensure that using token.NoPos+1 will panic.
+	fset.AddFile("gofumpt_base.go", 1, 10)
+
 	file, err := parser.ParseFile(fset, "", src, parser.ParseComments)
 	if err != nil {
 		return nil, err
@@ -553,10 +558,14 @@ func (f *fumpter) applyPre(c *astutil.Cursor) {
 				// The body is preceded by a multi-line function
 				// signature, we move the `) {` to avoid the empty line.
 				switch {
-				case isThereAnEmptyLine && sign.Results != nil && !resultClosingIsFirstCharOnEndLine:
+				case isThereAnEmptyLine && sign.Results != nil &&
+					!resultClosingIsFirstCharOnEndLine &&
+					sign.Results.Closing.IsValid(): // there may be no ")"
 					sign.Results.Closing += 1
 					f.addNewline(sign.Results.Closing)
-				case isThereAnEmptyLine && sign.Params != nil && !paramClosingIsFirstCharOnEndLine:
+
+				case isThereAnEmptyLine && sign.Params != nil &&
+					!paramClosingIsFirstCharOnEndLine:
 					sign.Params.Closing += 1
 					f.addNewline(sign.Params.Closing)
 				}
@@ -824,13 +833,21 @@ func identEqual(expr ast.Expr, name string) bool {
 //
 //   import "C"
 //
+// or the equivalent:
+//
+//   import `C`
+//
 // Note that parentheses do not affect the result.
 func isCgoImport(decl *ast.GenDecl) bool {
 	if decl.Tok != token.IMPORT || len(decl.Specs) != 1 {
 		return false
 	}
 	spec := decl.Specs[0].(*ast.ImportSpec)
-	return spec.Path.Value == `"C"`
+	v, err := strconv.Unquote(spec.Path.Value)
+	if err != nil {
+		panic(err) // should never error
+	}
+	return v == "C"
 }
 
 // joinStdImports ensures that all standard library imports are together and at
diff --git a/gofmt.go b/gofmt.go
index eedb60a..58a63e6 100644
--- a/gofmt.go
+++ b/gofmt.go
@@ -197,6 +197,10 @@ func main() {
 }
 
 func gofumptMain() {
+	// Ensure our parsed files never start with base 1,
+	// to ensure that using token.NoPos+1 will panic.
+	fileSet.AddFile("gofumpt_base.go", 1, 10)
+
 	flag.Usage = usage
 	flag.Parse()
 


Test patch:
diff --git a/testdata/scripts/cgo.txt b/testdata/scripts/cgo.txt
index 672c5f7..89f8087 100644
--- a/testdata/scripts/cgo.txt
+++ b/testdata/scripts/cgo.txt
@@ -10,18 +10,36 @@ package p
 import "C"
 import "os"
 
+import `C`
+import "os"
+
 import "C"
 import (
 	"io"
 	"utf8"
 )
 
+import `C`
+import (
+	"io"
+	"utf8"
+)
+
 -- foo.go.golden --
 package p
 
 import "C"
 import "os"
 
+import "C"
+import "os"
+
+import "C"
+import (
+	"io"
+	"utf8"
+)
+
 import "C"
 import (
 	"io"
diff --git a/testdata/scripts/func-newlines.txt b/testdata/scripts/func-newlines.txt
index 1b15615..caa0ce1 100644
--- a/testdata/scripts/func-newlines.txt
+++ b/testdata/scripts/func-newlines.txt
@@ -249,6 +249,15 @@ func multilineParamsWithoutEmptyLineWithComment(p1 string,
 	// comment
 	println("body")
 }
+
+// Same as the others above, but with a single result parameter without
+// parentheses. This used to cause token.File.Offset crashes.
+func f(p1 string,
+	p2 string) int {
+
+	println("body")
+	return 0
+}
 -- foo.go.golden --
 package p
 
@@ -449,3 +458,12 @@ func multilineParamsWithoutEmptyLineWithComment(p1 string,
 	// comment
 	println("body")
 }
+
+// Same as the others above, but with a single result parameter without
+// parentheses. This used to cause token.File.Offset crashes.
+func f(p1 string,
+	p2 string,
+) int {
+	println("body")
+	return 0
+}