imports: Process should accept nil src

The comment of Process() implies src can be nil, but it didn't handle
nil src correctly before because parse() doesn't expect nil src.
Passing []byte(nil) to parser.ParseFile() results in error and parse()
tries to parse again by modifying src if src is statement list.

This problem isn't related with cmd/goimports because goimports doesn't
pass []byte(nil) to Process() as src.

Fixes golang/go#19676

Change-Id: Idbaa6646c3907690763eabc798860c56bb9963d4
Reviewed-on: https://go-review.googlesource.com/38613
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
haya14busa 2017-03-24 14:58:37 +09:00 committed by Brad Fitzpatrick
parent dc06d3e643
commit 1c0c7a8cce
2 changed files with 74 additions and 0 deletions

View File

@ -936,6 +936,72 @@ func TestFixImports(t *testing.T) {
} }
} }
func TestProcess_nil_src(t *testing.T) {
dir, err := ioutil.TempDir("", "goimports-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
tests := []struct {
name string
in, out string
}{
{
name: "nil-src",
in: `package foo
func bar() {
fmt.Println("hi")
}
`,
out: `package foo
import "fmt"
func bar() {
fmt.Println("hi")
}
`,
},
{
name: "missing package",
in: `
func bar() {
fmt.Println("hi")
}
`,
out: `
import "fmt"
func bar() {
fmt.Println("hi")
}
`,
},
}
options := &Options{
TabWidth: 8,
TabIndent: true,
Comments: true,
Fragment: true,
}
for _, tt := range tests {
filename := filepath.Join(dir, tt.name+".go")
if err := ioutil.WriteFile(filename, []byte(tt.in), 0666); err != nil {
t.Fatal(err)
}
buf, err := Process(filename, nil, options)
if err != nil {
t.Errorf("error on %q: %v", tt.name, err)
continue
}
if got := string(buf); got != tt.out {
t.Errorf("results diff on %q\nGOT:\n%s\nWANT:\n%s\n", tt.name, got, tt.out)
}
}
}
// Test support for packages in GOPATH that are actually symlinks. // Test support for packages in GOPATH that are actually symlinks.
// Also test that a symlink loop does not block the process. // Also test that a symlink loop does not block the process.
func TestImportSymlinks(t *testing.T) { func TestImportSymlinks(t *testing.T) {

View File

@ -18,6 +18,7 @@ import (
"go/printer" "go/printer"
"go/token" "go/token"
"io" "io"
"io/ioutil"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -47,6 +48,13 @@ func Process(filename string, src []byte, opt *Options) ([]byte, error) {
if opt == nil { if opt == nil {
opt = &Options{Comments: true, TabIndent: true, TabWidth: 8} opt = &Options{Comments: true, TabIndent: true, TabWidth: 8}
} }
if src == nil {
b, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
src = b
}
fileSet := token.NewFileSet() fileSet := token.NewFileSet()
file, adjust, err := parse(fileSet, filename, src, opt) file, adjust, err := parse(fileSet, filename, src, opt)