summaryrefslogtreecommitdiff
path: root/src/cmd/gofmt
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-04-06 15:14:11 +0200
committerOndřej Surý <ondrej@sury.org>2012-04-06 15:14:11 +0200
commit505c19580e0f43fe5224431459cacb7c21edd93d (patch)
tree79e2634c253d60afc0cc0b2f510dc7dcbb48497b /src/cmd/gofmt
parent1336a7c91e596c423a49d1194ea42d98bca0d958 (diff)
downloadgolang-505c19580e0f43fe5224431459cacb7c21edd93d.tar.gz
Imported Upstream version 1upstream/1
Diffstat (limited to 'src/cmd/gofmt')
-rw-r--r--src/cmd/gofmt/Makefile19
-rw-r--r--src/cmd/gofmt/doc.go12
-rw-r--r--src/cmd/gofmt/gofmt.go194
-rw-r--r--src/cmd/gofmt/gofmt_test.go50
-rw-r--r--src/cmd/gofmt/long_test.go159
-rw-r--r--src/cmd/gofmt/rewrite.go13
-rw-r--r--src/cmd/gofmt/simplify.go18
-rwxr-xr-xsrc/cmd/gofmt/test.sh162
-rw-r--r--src/cmd/gofmt/testdata/comments.golden9
-rw-r--r--src/cmd/gofmt/testdata/comments.input9
-rw-r--r--src/cmd/gofmt/testdata/composites.golden98
-rw-r--r--src/cmd/gofmt/testdata/composites.input98
-rw-r--r--src/cmd/gofmt/testdata/import.golden108
-rw-r--r--src/cmd/gofmt/testdata/import.input108
-rw-r--r--src/cmd/gofmt/testdata/old.golden9
-rw-r--r--src/cmd/gofmt/testdata/old.input8
-rw-r--r--src/cmd/gofmt/testdata/rewrite3.golden12
-rw-r--r--src/cmd/gofmt/testdata/rewrite3.input12
-rw-r--r--src/cmd/gofmt/testdata/rewrite4.golden74
-rw-r--r--src/cmd/gofmt/testdata/rewrite4.input74
-rw-r--r--src/cmd/gofmt/testdata/stdin1.golden3
-rw-r--r--src/cmd/gofmt/testdata/stdin1.golden.gofmt3
-rw-r--r--src/cmd/gofmt/testdata/stdin1.input3
-rw-r--r--src/cmd/gofmt/testdata/stdin1.input.gofmt3
-rw-r--r--src/cmd/gofmt/testdata/stdin2.golden11
-rw-r--r--src/cmd/gofmt/testdata/stdin2.golden.gofmt10
-rw-r--r--src/cmd/gofmt/testdata/stdin2.input11
-rw-r--r--src/cmd/gofmt/testdata/stdin2.input.gofmt11
-rw-r--r--src/cmd/gofmt/testdata/stdin3.golden6
-rw-r--r--src/cmd/gofmt/testdata/stdin3.golden.gofmt7
-rw-r--r--src/cmd/gofmt/testdata/stdin3.input4
-rw-r--r--src/cmd/gofmt/testdata/stdin3.input.gofmt7
-rw-r--r--src/cmd/gofmt/testdata/stdin4.golden3
-rw-r--r--src/cmd/gofmt/testdata/stdin4.golden.gofmt3
-rw-r--r--src/cmd/gofmt/testdata/stdin4.input3
-rw-r--r--src/cmd/gofmt/testdata/stdin4.input.gofmt3
36 files changed, 1086 insertions, 251 deletions
diff --git a/src/cmd/gofmt/Makefile b/src/cmd/gofmt/Makefile
deleted file mode 100644
index dc5b060e6..000000000
--- a/src/cmd/gofmt/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=gofmt
-GOFILES=\
- gofmt.go\
- rewrite.go\
- simplify.go\
-
-include ../../Make.cmd
-
-test: $(TARG)
- ./test.sh
-
-testshort:
- gotest -test.short
diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go
index fca42b76b..65842a3b1 100644
--- a/src/cmd/gofmt/doc.go
+++ b/src/cmd/gofmt/doc.go
@@ -36,10 +36,8 @@ The flags are:
Formatting control flags:
-comments=true
Print comments; if false, all comments are elided from the output.
- -spaces
- Align with spaces instead of tabs.
- -tabindent
- Indent with tabs independent of -spaces.
+ -tabs=true
+ Indent with tabs; if false, spaces are used instead.
-tabwidth=8
Tab width in spaces.
@@ -53,6 +51,12 @@ In the pattern, single-character lowercase identifiers serve as
wildcards matching arbitrary sub-expressions; those expressions
will be substituted for the same identifiers in the replacement.
+When gofmt reads from standard input, it accepts either a full Go program
+or a program fragment. A program fragment must be a syntactically
+valid declaration list, statement list, or expression. When formatting
+such a fragment, gofmt preserves leading indentation as well as leading
+and trailing spaces, so that individual sections of a Go program can be
+formatted by piping them through gofmt.
Examples
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index 975ae6ac6..0bc385b5b 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -6,7 +6,6 @@ package main
import (
"bytes"
- "exec"
"flag"
"fmt"
"go/ast"
@@ -17,6 +16,7 @@ import (
"io"
"io/ioutil"
"os"
+ "os/exec"
"path/filepath"
"runtime/pprof"
"strings"
@@ -26,7 +26,7 @@ var (
// main operation modes
list = flag.Bool("l", false, "list files whose formatting differs from gofmt's")
write = flag.Bool("w", false, "write result to (source) file instead of stdout")
- rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'α[β:len(α)] -> α[β:]')")
+ rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')")
simplifyAST = flag.Bool("s", false, "simplify code")
doDiff = flag.Bool("d", false, "display diffs instead of rewriting files")
allErrors = flag.Bool("e", false, "print all (including spurious) errors")
@@ -34,22 +34,21 @@ var (
// layout control
comments = flag.Bool("comments", true, "print comments")
tabWidth = flag.Int("tabwidth", 8, "tab width")
- tabIndent = flag.Bool("tabindent", true, "indent with tabs independent of -spaces")
- useSpaces = flag.Bool("spaces", true, "align with spaces instead of tabs")
+ tabIndent = flag.Bool("tabs", true, "indent with tabs")
// debugging
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
)
var (
- fset = token.NewFileSet()
+ fileSet = token.NewFileSet() // per process FileSet
exitCode = 0
rewrite func(*ast.File) *ast.File
- parserMode uint
- printerMode uint
+ parserMode parser.Mode
+ printerMode printer.Mode
)
-func report(err os.Error) {
+func report(err error) {
scanner.PrintError(os.Stderr, err)
exitCode = 2
}
@@ -61,7 +60,7 @@ func usage() {
}
func initParserMode() {
- parserMode = uint(0)
+ parserMode = parser.Mode(0)
if *comments {
parserMode |= parser.ParseComments
}
@@ -71,22 +70,20 @@ func initParserMode() {
}
func initPrinterMode() {
- printerMode = uint(0)
+ printerMode = printer.UseSpaces
if *tabIndent {
printerMode |= printer.TabIndent
}
- if *useSpaces {
- printerMode |= printer.UseSpaces
- }
}
-func isGoFile(f *os.FileInfo) bool {
+func isGoFile(f os.FileInfo) bool {
// ignore non-Go files
- return f.IsRegular() && !strings.HasPrefix(f.Name, ".") && strings.HasSuffix(f.Name, ".go")
+ name := f.Name()
+ return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
}
// If in == nil, the source is the contents of the file with the given filename.
-func processFile(filename string, in io.Reader, out io.Writer) os.Error {
+func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error {
if in == nil {
f, err := os.Open(filename)
if err != nil {
@@ -101,25 +98,34 @@ func processFile(filename string, in io.Reader, out io.Writer) os.Error {
return err
}
- file, err := parser.ParseFile(fset, filename, src, parserMode)
+ file, adjust, err := parse(fileSet, filename, src, stdin)
if err != nil {
return err
}
if rewrite != nil {
- file = rewrite(file)
+ if adjust == nil {
+ file = rewrite(file)
+ } else {
+ fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n")
+ }
}
+ ast.SortImports(fileSet, file)
+
if *simplifyAST {
simplify(file)
}
var buf bytes.Buffer
- _, err = (&printer.Config{printerMode, *tabWidth}).Fprint(&buf, fset, file)
+ err = (&printer.Config{Mode: printerMode, Tabwidth: *tabWidth}).Fprint(&buf, fileSet, file)
if err != nil {
return err
}
res := buf.Bytes()
+ if adjust != nil {
+ res = adjust(src, res)
+ }
if !bytes.Equal(src, res) {
// formatting has changed
@@ -149,32 +155,18 @@ func processFile(filename string, in io.Reader, out io.Writer) os.Error {
return err
}
-type fileVisitor chan os.Error
-
-func (v fileVisitor) VisitDir(path string, f *os.FileInfo) bool {
- return true
-}
-
-func (v fileVisitor) VisitFile(path string, f *os.FileInfo) {
- if isGoFile(f) {
- v <- nil // synchronize error handler
- if err := processFile(path, nil, os.Stdout); err != nil {
- v <- err
- }
+func visitFile(path string, f os.FileInfo, err error) error {
+ if err == nil && isGoFile(f) {
+ err = processFile(path, nil, os.Stdout, false)
+ }
+ if err != nil {
+ report(err)
}
+ return nil
}
func walkDir(path string) {
- v := make(fileVisitor)
- go func() {
- filepath.Walk(path, v, v)
- close(v)
- }()
- for err := range v {
- if err != nil {
- report(err)
- }
- }
+ filepath.Walk(path, visitFile)
}
func main() {
@@ -211,7 +203,7 @@ func gofmtMain() {
initRewrite()
if flag.NArg() == 0 {
- if err := processFile("<standard input>", os.Stdin, os.Stdout); err != nil {
+ if err := processFile("<standard input>", os.Stdin, os.Stdout, true); err != nil {
report(err)
}
return
@@ -222,17 +214,17 @@ func gofmtMain() {
switch dir, err := os.Stat(path); {
case err != nil:
report(err)
- case dir.IsRegular():
- if err := processFile(path, nil, os.Stdout); err != nil {
+ case dir.IsDir():
+ walkDir(path)
+ default:
+ if err := processFile(path, nil, os.Stdout, false); err != nil {
report(err)
}
- case dir.IsDirectory():
- walkDir(path)
}
}
}
-func diff(b1, b2 []byte) (data []byte, err os.Error) {
+func diff(b1, b2 []byte) (data []byte, err error) {
f1, err := ioutil.TempFile("", "gofmt")
if err != nil {
return
@@ -259,3 +251,111 @@ func diff(b1, b2 []byte) (data []byte, err os.Error) {
return
}
+
+// parse parses src, which was read from filename,
+// as a Go source file or statement list.
+func parse(fset *token.FileSet, filename string, src []byte, stdin bool) (*ast.File, func(orig, src []byte) []byte, error) {
+ // Try as whole source file.
+ file, err := parser.ParseFile(fset, filename, src, parserMode)
+ if err == nil {
+ return file, nil, nil
+ }
+ // If the error is that the source file didn't begin with a
+ // package line and this is standard input, fall through to
+ // try as a source fragment. Stop and return on any other error.
+ if !stdin || !strings.Contains(err.Error(), "expected 'package'") {
+ return nil, nil, err
+ }
+
+ // If this is a declaration list, make it a source file
+ // by inserting a package clause.
+ // Insert using a ;, not a newline, so that the line numbers
+ // in psrc match the ones in src.
+ psrc := append([]byte("package p;"), src...)
+ file, err = parser.ParseFile(fset, filename, psrc, parserMode)
+ if err == nil {
+ adjust := func(orig, src []byte) []byte {
+ // Remove the package clause.
+ // Gofmt has turned the ; into a \n.
+ src = src[len("package p\n"):]
+ return matchSpace(orig, src)
+ }
+ return file, adjust, nil
+ }
+ // If the error is that the source file didn't begin with a
+ // declaration, fall through to try as a statement list.
+ // Stop and return on any other error.
+ if !strings.Contains(err.Error(), "expected declaration") {
+ return nil, nil, err
+ }
+
+ // If this is a statement list, make it a source file
+ // by inserting a package clause and turning the list
+ // into a function body. This handles expressions too.
+ // Insert using a ;, not a newline, so that the line numbers
+ // in fsrc match the ones in src.
+ fsrc := append(append([]byte("package p; func _() {"), src...), '}')
+ file, err = parser.ParseFile(fset, filename, fsrc, parserMode)
+ if err == nil {
+ adjust := func(orig, src []byte) []byte {
+ // Remove the wrapping.
+ // Gofmt has turned the ; into a \n\n.
+ src = src[len("package p\n\nfunc _() {"):]
+ src = src[:len(src)-len("}\n")]
+ // Gofmt has also indented the function body one level.
+ // Remove that indent.
+ src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1)
+ return matchSpace(orig, src)
+ }
+ return file, adjust, nil
+ }
+
+ // Failed, and out of options.
+ return nil, nil, err
+}
+
+func cutSpace(b []byte) (before, middle, after []byte) {
+ i := 0
+ for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\n') {
+ i++
+ }
+ j := len(b)
+ for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') {
+ j--
+ }
+ if i <= j {
+ return b[:i], b[i:j], b[j:]
+ }
+ return nil, nil, b[j:]
+}
+
+// matchSpace reformats src to use the same space context as orig.
+// 1) If orig begins with blank lines, matchSpace inserts them at the beginning of src.
+// 2) matchSpace copies the indentation of the first non-blank line in orig
+// to every non-blank line in src.
+// 3) matchSpace copies the trailing space from orig and uses it in place
+// of src's trailing space.
+func matchSpace(orig []byte, src []byte) []byte {
+ before, _, after := cutSpace(orig)
+ i := bytes.LastIndex(before, []byte{'\n'})
+ before, indent := before[:i+1], before[i+1:]
+
+ _, src, _ = cutSpace(src)
+
+ var b bytes.Buffer
+ b.Write(before)
+ for len(src) > 0 {
+ line := src
+ if i := bytes.IndexByte(line, '\n'); i >= 0 {
+ line, src = line[:i+1], line[i+1:]
+ } else {
+ src = nil
+ }
+ if len(line) > 0 && line[0] != '\n' { // not blank
+ b.Write(indent)
+ }
+ b.Write(line)
+ }
+ b.Write(after)
+ return b.Bytes()
+}
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index 2e35ce9a4..4b2805009 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -12,13 +12,11 @@ import (
"testing"
)
-func runTest(t *testing.T, dirname, in, out, flags string) {
- in = filepath.Join(dirname, in)
- out = filepath.Join(dirname, out)
-
+func runTest(t *testing.T, in, out, flags string) {
// process flags
*simplifyAST = false
*rewriteRule = ""
+ stdin := false
for _, flag := range strings.Split(flags, " ") {
elts := strings.SplitN(flag, "=", 2)
name := elts[0]
@@ -33,6 +31,9 @@ func runTest(t *testing.T, dirname, in, out, flags string) {
*rewriteRule = value
case "-s":
*simplifyAST = true
+ case "-stdin":
+ // fake flag - pretend input is from stdin
+ stdin = true
default:
t.Errorf("unrecognized flag name: %s", name)
}
@@ -43,7 +44,7 @@ func runTest(t *testing.T, dirname, in, out, flags string) {
initRewrite()
var buf bytes.Buffer
- err := processFile(in, nil, &buf)
+ err := processFile(in, nil, &buf, stdin)
if err != nil {
t.Error(err)
return
@@ -57,23 +58,48 @@ func runTest(t *testing.T, dirname, in, out, flags string) {
if got := buf.Bytes(); bytes.Compare(got, expected) != 0 {
t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in)
+ d, err := diff(expected, got)
+ if err == nil {
+ t.Errorf("%s", d)
+ }
ioutil.WriteFile(in+".gofmt", got, 0666)
}
}
// TODO(gri) Add more test cases!
var tests = []struct {
- dirname, in, out, flags string
+ in, flags string
}{
- {".", "gofmt.go", "gofmt.go", ""},
- {".", "gofmt_test.go", "gofmt_test.go", ""},
- {"testdata", "composites.input", "composites.golden", "-s"},
- {"testdata", "rewrite1.input", "rewrite1.golden", "-r=Foo->Bar"},
- {"testdata", "rewrite2.input", "rewrite2.golden", "-r=int->bool"},
+ {"gofmt.go", ""},
+ {"gofmt_test.go", ""},
+ {"testdata/composites.input", "-s"},
+ {"testdata/old.input", ""},
+ {"testdata/rewrite1.input", "-r=Foo->Bar"},
+ {"testdata/rewrite2.input", "-r=int->bool"},
+ {"testdata/rewrite3.input", "-r=x->x"},
+ {"testdata/rewrite4.input", "-r=(x)->x"},
+ {"testdata/stdin*.input", "-stdin"},
+ {"testdata/comments.input", ""},
+ {"testdata/import.input", ""},
}
func TestRewrite(t *testing.T) {
for _, test := range tests {
- runTest(t, test.dirname, test.in, test.out, test.flags)
+ match, err := filepath.Glob(test.in)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ for _, in := range match {
+ out := in
+ if strings.HasSuffix(in, ".input") {
+ out = in[:len(in)-len(".input")] + ".golden"
+ }
+ runTest(t, in, out, test.flags)
+ if in != out {
+ // Check idempotence.
+ runTest(t, out, out, test.flags)
+ }
+ }
}
}
diff --git a/src/cmd/gofmt/long_test.go b/src/cmd/gofmt/long_test.go
new file mode 100644
index 000000000..edbce606a
--- /dev/null
+++ b/src/cmd/gofmt/long_test.go
@@ -0,0 +1,159 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test applies gofmt to all Go files under -root.
+// To test specific files provide a list of comma-separated
+// filenames via the -files flag: go test -files=gofmt.go .
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/printer"
+ "go/token"
+ "io"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "testing"
+)
+
+var (
+ root = flag.String("root", runtime.GOROOT(), "test root directory")
+ files = flag.String("files", "", "comma-separated list of files to test")
+ ngo = flag.Int("n", runtime.NumCPU(), "number of goroutines used")
+ verbose = flag.Bool("verbose", false, "verbose mode")
+ nfiles int // number of files processed
+)
+
+func gofmt(fset *token.FileSet, filename string, src *bytes.Buffer) error {
+ f, _, err := parse(fset, filename, src.Bytes(), false)
+ if err != nil {
+ return err
+ }
+ ast.SortImports(fset, f)
+ src.Reset()
+ return (&printer.Config{Mode: printerMode, Tabwidth: *tabWidth}).Fprint(src, fset, f)
+}
+
+func testFile(t *testing.T, b1, b2 *bytes.Buffer, filename string) {
+ // open file
+ f, err := os.Open(filename)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ // read file
+ b1.Reset()
+ _, err = io.Copy(b1, f)
+ f.Close()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ // exclude files w/ syntax errors (typically test cases)
+ fset := token.NewFileSet()
+ if _, _, err = parse(fset, filename, b1.Bytes(), false); err != nil {
+ if *verbose {
+ fmt.Fprintf(os.Stderr, "ignoring %s\n", err)
+ }
+ return
+ }
+
+ // gofmt file
+ if err = gofmt(fset, filename, b1); err != nil {
+ t.Errorf("1st gofmt failed: %v", err)
+ return
+ }
+
+ // make a copy of the result
+ b2.Reset()
+ b2.Write(b1.Bytes())
+
+ // gofmt result again
+ if err = gofmt(fset, filename, b2); err != nil {
+ t.Errorf("2nd gofmt failed: %v", err)
+ return
+ }
+
+ // the first and 2nd result should be identical
+ if bytes.Compare(b1.Bytes(), b2.Bytes()) != 0 {
+ t.Errorf("gofmt %s not idempotent", filename)
+ }
+}
+
+func testFiles(t *testing.T, filenames <-chan string, done chan<- int) {
+ b1 := new(bytes.Buffer)
+ b2 := new(bytes.Buffer)
+ for filename := range filenames {
+ testFile(t, b1, b2, filename)
+ }
+ done <- 0
+}
+
+func genFilenames(t *testing.T, filenames chan<- string) {
+ defer close(filenames)
+
+ handleFile := func(filename string, fi os.FileInfo, err error) error {
+ if err != nil {
+ t.Error(err)
+ return nil
+ }
+ if isGoFile(fi) {
+ filenames <- filename
+ nfiles++
+ }
+ return nil
+ }
+
+ // test Go files provided via -files, if any
+ if *files != "" {
+ for _, filename := range strings.Split(*files, ",") {
+ fi, err := os.Stat(filename)
+ handleFile(filename, fi, err)
+ }
+ return // ignore files under -root
+ }
+
+ // otherwise, test all Go files under *root
+ filepath.Walk(*root, handleFile)
+}
+
+func TestAll(t *testing.T) {
+ if testing.Short() {
+ return
+ }
+
+ if *ngo < 1 {
+ *ngo = 1 // make sure test is run
+ }
+ if *verbose {
+ fmt.Printf("running test using %d goroutines\n", *ngo)
+ }
+
+ // generate filenames
+ filenames := make(chan string, 32)
+ go genFilenames(t, filenames)
+
+ // launch test goroutines
+ done := make(chan int)
+ for i := 0; i < *ngo; i++ {
+ go testFiles(t, filenames, done)
+ }
+
+ // wait for all test goroutines to complete
+ for i := 0; i < *ngo; i++ {
+ <-done
+ }
+
+ if *verbose {
+ fmt.Printf("processed %d files\n", nfiles)
+ }
+}
diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go
index 3d74dea0f..3c7861f0d 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -13,7 +13,7 @@ import (
"reflect"
"strings"
"unicode"
- "utf8"
+ "unicode/utf8"
)
func initRewrite() {
@@ -36,7 +36,7 @@ func initRewrite() {
// but there are problems with preserving formatting and also
// with what a wildcard for a statement looks like.
func parseExpr(s string, what string) ast.Expr {
- x, err := parser.ParseExpr(fset, "input", s)
+ x, err := parser.ParseExpr(s)
if err != nil {
fmt.Fprintf(os.Stderr, "parsing %s %s: %s\n", what, s, err)
os.Exit(2)
@@ -65,7 +65,7 @@ func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
return reflect.Value{}
}
for k := range m {
- m[k] = reflect.Value{}, false
+ delete(m, k)
}
val = apply(f, val)
if match(m, pat, val) {
@@ -85,7 +85,8 @@ func setValue(x, y reflect.Value) {
}
defer func() {
if x := recover(); x != nil {
- if s, ok := x.(string); ok && strings.HasPrefix(s, "type mismatch") {
+ if s, ok := x.(string); ok &&
+ (strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
// x cannot be set to y - ignore this rewrite
return
}
@@ -158,8 +159,8 @@ func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
if m != nil && pattern.IsValid() && pattern.Type() == identType {
name := pattern.Interface().(*ast.Ident).Name
if isWildcard(name) && val.IsValid() {
- // wildcards only match expressions
- if _, ok := val.Interface().(ast.Expr); ok {
+ // wildcards only match valid (non-nil) expressions.
+ if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() {
if old, ok := m[name]; ok {
return match(nil, old, val)
}
diff --git a/src/cmd/gofmt/simplify.go b/src/cmd/gofmt/simplify.go
index d9afc0e7b..470c00625 100644
--- a/src/cmd/gofmt/simplify.go
+++ b/src/cmd/gofmt/simplify.go
@@ -6,6 +6,7 @@ package main
import (
"go/ast"
+ "go/token"
"reflect"
)
@@ -26,10 +27,12 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
if eltType != nil {
typ := reflect.ValueOf(eltType)
- for _, x := range outer.Elts {
+ for i, x := range outer.Elts {
+ px := &outer.Elts[i]
// look at value of indexed/named elements
if t, ok := x.(*ast.KeyValueExpr); ok {
x = t.Value
+ px = &t.Value
}
simplify(x)
// if the element is a composite literal and its literal type
@@ -40,6 +43,19 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
inner.Type = nil
}
}
+ // if the outer literal's element type is a pointer type *T
+ // and the element is & of a composite literal of type T,
+ // the inner &T may be omitted.
+ if ptr, ok := eltType.(*ast.StarExpr); ok {
+ if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND {
+ if inner, ok := addr.X.(*ast.CompositeLit); ok {
+ if match(nil, reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) {
+ inner.Type = nil // drop T
+ *px = inner // drop &
+ }
+ }
+ }
+ }
}
// node was simplified - stop walk (there are no subnodes to simplify)
diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh
deleted file mode 100755
index 063a0727f..000000000
--- a/src/cmd/gofmt/test.sh
+++ /dev/null
@@ -1,162 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-eval $(gomake --no-print-directory -f ../../Make.inc go-env)
-if [ -z "$O" ]; then
- echo 'missing $O - maybe no Make.$GOARCH?' 1>&2
- exit 1
-fi
-
-CMD="./gofmt"
-TMP1=test_tmp1.go
-TMP2=test_tmp2.go
-TMP3=test_tmp3.go
-COUNT=0
-
-count() {
- #echo $1
- let COUNT=$COUNT+1
- let M=$COUNT%10
- if [ $M == 0 ]; then
- echo -n "."
- fi
-}
-
-
-error() {
- echo $1
- exit 1
-}
-
-
-# apply to one file
-apply1() {
- # the following files are skipped because they are test cases
- # for syntax errors and thus won't parse in the first place:
- case `basename "$F"` in
- func3.go | const2.go | char_lit1.go | blank1.go | ddd1.go | \
- bug014.go | bug050.go | bug068.go | bug083.go | bug088.go | \
- bug106.go | bug121.go | bug125.go | bug133.go | bug160.go | \
- bug163.go | bug166.go | bug169.go | bug217.go | bug222.go | \
- bug226.go | bug228.go | bug248.go | bug274.go | bug280.go | \
- bug282.go | bug287.go | bug298.go | bug299.go | bug300.go | \
- bug302.go | bug306.go | bug322.go | bug324.go | bug335.go | \
- bug340.go | bug349.go | bug351.go | bug358.go ) return ;;
- esac
- # the following directories are skipped because they contain test
- # cases for syntax errors and thus won't parse in the first place:
- case `dirname "$F"` in
- $GOROOT/test/syntax ) return ;;
- esac
- #echo $1 $2
- "$1" "$2"; count "$F"
-}
-
-
-# apply to local files
-applydot() {
- for F in `find . -name "*.go" | grep -v "._"`; do
- apply1 "$1" $F
- done
-}
-
-
-# apply to all .go files we can find
-apply() {
- for F in `find "$GOROOT" -name "*.go" | grep -v "._"`; do
- apply1 "$1" $F
- done
-}
-
-
-cleanup() {
- rm -f $TMP1 $TMP2 $TMP3
-}
-
-
-silent() {
- cleanup
- $CMD "$1" > /dev/null 2> $TMP1
- if [ $? != 0 ]; then
- cat $TMP1
- error "Error (silent mode test): test.sh $1"
- fi
-}
-
-
-idempotent() {
- cleanup
- $CMD "$1" > $TMP1
- if [ $? != 0 ]; then
- error "Error (step 1 of idempotency test): test.sh $1"
- fi
-
- $CMD $TMP1 > $TMP2
- if [ $? != 0 ]; then
- error "Error (step 2 of idempotency test): test.sh $1"
- fi
-
- $CMD $TMP2 > $TMP3
- if [ $? != 0 ]; then
- error "Error (step 3 of idempotency test): test.sh $1"
- fi
-
- cmp -s $TMP2 $TMP3
- if [ $? != 0 ]; then
- diff $TMP2 $TMP3
- error "Error (step 4 of idempotency test): test.sh $1"
- fi
-}
-
-
-valid() {
- cleanup
- $CMD "$1" > $TMP1
- if [ $? != 0 ]; then
- error "Error (step 1 of validity test): test.sh $1"
- fi
-
- $GC -o /dev/null $TMP1
- if [ $? != 0 ]; then
- error "Error (step 2 of validity test): test.sh $1"
- fi
-}
-
-
-runtest() {
- #echo "Testing silent mode"
- cleanup
- "$1" silent "$2"
-
- #echo "Testing idempotency"
- cleanup
- "$1" idempotent "$2"
-}
-
-
-runtests() {
- if [ $# = 0 ]; then
- runtest apply
- # verify the pretty-printed files can be compiled with $GC again
- # do it in local directory only because of the prerequisites required
- #echo "Testing validity"
- # Disabled for now due to dependency problems
- # cleanup
- # applydot valid
- else
- for F in "$@"; do
- runtest apply1 "$F"
- done
- fi
-}
-
-
-# run over all .go files
-runtests "$@"
-cleanup
-
-# done
-echo
-echo "PASSED ($COUNT tests)"
diff --git a/src/cmd/gofmt/testdata/comments.golden b/src/cmd/gofmt/testdata/comments.golden
new file mode 100644
index 000000000..ad6bcafaf
--- /dev/null
+++ b/src/cmd/gofmt/testdata/comments.golden
@@ -0,0 +1,9 @@
+package main
+
+func main() {}
+
+// comment here
+
+func f() {}
+
+//line foo.go:1
diff --git a/src/cmd/gofmt/testdata/comments.input b/src/cmd/gofmt/testdata/comments.input
new file mode 100644
index 000000000..ad6bcafaf
--- /dev/null
+++ b/src/cmd/gofmt/testdata/comments.input
@@ -0,0 +1,9 @@
+package main
+
+func main() {}
+
+// comment here
+
+func f() {}
+
+//line foo.go:1
diff --git a/src/cmd/gofmt/testdata/composites.golden b/src/cmd/gofmt/testdata/composites.golden
index 1fd5847c1..b2825e732 100644
--- a/src/cmd/gofmt/testdata/composites.golden
+++ b/src/cmd/gofmt/testdata/composites.golden
@@ -102,3 +102,101 @@ var pieces4 = []Piece{
{2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
{3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
}
+
+var _ = [42]*T{
+ {},
+ {1, 2},
+ {3, 4},
+}
+
+var _ = [...]*T{
+ {},
+ {1, 2},
+ {3, 4},
+}
+
+var _ = []*T{
+ {},
+ {1, 2},
+ {3, 4},
+}
+
+var _ = []*T{
+ {},
+ 10: {1, 2},
+ 20: {3, 4},
+}
+
+var _ = []*struct {
+ x, y int
+}{
+ {},
+ 10: {1, 2},
+ 20: {3, 4},
+}
+
+var _ = []interface{}{
+ &T{},
+ 10: &T{1, 2},
+ 20: &T{3, 4},
+}
+
+var _ = []*[]int{
+ {},
+ {1, 2},
+ {3, 4},
+}
+
+var _ = []*[]int{
+ (&[]int{}),
+ (&[]int{1, 2}),
+ {3, 4},
+}
+
+var _ = []*[]*[]int{
+ {},
+ {
+ {},
+ {0, 1, 2, 3},
+ {4, 5},
+ },
+}
+
+var _ = map[string]*T{
+ "foo": {},
+ "bar": {1, 2},
+ "bal": {3, 4},
+}
+
+var _ = map[string]*struct {
+ x, y int
+}{
+ "foo": {},
+ "bar": {1, 2},
+ "bal": {3, 4},
+}
+
+var _ = map[string]interface{}{
+ "foo": &T{},
+ "bar": &T{1, 2},
+ "bal": &T{3, 4},
+}
+
+var _ = map[string]*[]int{
+ "foo": {},
+ "bar": {1, 2},
+ "bal": {3, 4},
+}
+
+var _ = map[string]*[]int{
+ "foo": (&[]int{}),
+ "bar": (&[]int{1, 2}),
+ "bal": {3, 4},
+}
+
+var pieces4 = []*Piece{
+ {0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
+ {1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
+ {2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
+ {3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
+}
diff --git a/src/cmd/gofmt/testdata/composites.input b/src/cmd/gofmt/testdata/composites.input
index 15afd9e5c..7210dafc9 100644
--- a/src/cmd/gofmt/testdata/composites.input
+++ b/src/cmd/gofmt/testdata/composites.input
@@ -102,3 +102,101 @@ var pieces4 = []Piece{
Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
}
+
+var _ = [42]*T{
+ &T{},
+ &T{1, 2},
+ &T{3, 4},
+}
+
+var _ = [...]*T{
+ &T{},
+ &T{1, 2},
+ &T{3, 4},
+}
+
+var _ = []*T{
+ &T{},
+ &T{1, 2},
+ &T{3, 4},
+}
+
+var _ = []*T{
+ &T{},
+ 10: &T{1, 2},
+ 20: &T{3, 4},
+}
+
+var _ = []*struct {
+ x, y int
+}{
+ &struct{ x, y int }{},
+ 10: &struct{ x, y int }{1, 2},
+ 20: &struct{ x, y int }{3, 4},
+}
+
+var _ = []interface{}{
+ &T{},
+ 10: &T{1, 2},
+ 20: &T{3, 4},
+}
+
+var _ = []*[]int{
+ &[]int{},
+ &[]int{1, 2},
+ &[]int{3, 4},
+}
+
+var _ = []*[]int{
+ (&[]int{}),
+ (&[]int{1, 2}),
+ &[]int{3, 4},
+}
+
+var _ = []*[]*[]int{
+ &[]*[]int{},
+ &[]*[]int{
+ &[]int{},
+ &[]int{0, 1, 2, 3},
+ &[]int{4, 5},
+ },
+}
+
+var _ = map[string]*T{
+ "foo": &T{},
+ "bar": &T{1, 2},
+ "bal": &T{3, 4},
+}
+
+var _ = map[string]*struct {
+ x, y int
+}{
+ "foo": &struct{ x, y int }{},
+ "bar": &struct{ x, y int }{1, 2},
+ "bal": &struct{ x, y int }{3, 4},
+}
+
+var _ = map[string]interface{}{
+ "foo": &T{},
+ "bar": &T{1, 2},
+ "bal": &T{3, 4},
+}
+
+var _ = map[string]*[]int{
+ "foo": &[]int{},
+ "bar": &[]int{1, 2},
+ "bal": &[]int{3, 4},
+}
+
+var _ = map[string]*[]int{
+ "foo": (&[]int{}),
+ "bar": (&[]int{1, 2}),
+ "bal": &[]int{3, 4},
+}
+
+var pieces4 = []*Piece{
+ &Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
+ &Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
+ &Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
+ &Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
+}
diff --git a/src/cmd/gofmt/testdata/import.golden b/src/cmd/gofmt/testdata/import.golden
new file mode 100644
index 000000000..e8ee44988
--- /dev/null
+++ b/src/cmd/gofmt/testdata/import.golden
@@ -0,0 +1,108 @@
+package main
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math"
+)
+
+import (
+ "fmt"
+
+ "math"
+
+ "log"
+
+ "errors"
+
+ "io"
+)
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math"
+
+ "fmt"
+
+ "math"
+
+ "log"
+
+ "errors"
+
+ "io"
+)
+
+import (
+ // a block with comments
+ "errors"
+ "fmt" // for Printf
+ "io" // for Reader
+ "log" // for Fatal
+ "math"
+)
+
+import (
+ "fmt" // for Printf
+
+ "math"
+
+ "log" // for Fatal
+
+ "errors"
+
+ "io" // for Reader
+)
+
+import (
+ // for Printf
+ "fmt"
+
+ "math"
+
+ // for Fatal
+ "log"
+
+ "errors"
+
+ // for Reader
+ "io"
+)
+
+import (
+ "errors"
+ "fmt" // for Printf
+ "io" // for Reader
+ "log" // for Fatal
+ "math"
+
+ "fmt" // for Printf
+
+ "math"
+
+ "log" // for Fatal
+
+ "errors"
+
+ "io" // for Reader
+)
+
+import (
+ "fmt" // for Printf
+
+ "errors"
+ "io" // for Reader
+ "log" // for Fatal
+ "math"
+
+ "errors"
+ "fmt" // for Printf
+ "io" // for Reader
+ "log" // for Fatal
+ "math"
+)
diff --git a/src/cmd/gofmt/testdata/import.input b/src/cmd/gofmt/testdata/import.input
new file mode 100644
index 000000000..cc36c3e01
--- /dev/null
+++ b/src/cmd/gofmt/testdata/import.input
@@ -0,0 +1,108 @@
+package main
+
+import (
+ "fmt"
+ "math"
+ "log"
+ "errors"
+ "io"
+)
+
+import (
+ "fmt"
+
+ "math"
+
+ "log"
+
+ "errors"
+
+ "io"
+)
+
+import (
+ "fmt"
+ "math"
+ "log"
+ "errors"
+ "io"
+
+ "fmt"
+
+ "math"
+
+ "log"
+
+ "errors"
+
+ "io"
+)
+
+import (
+ // a block with comments
+ "fmt" // for Printf
+ "math"
+ "log" // for Fatal
+ "errors"
+ "io" // for Reader
+)
+
+import (
+ "fmt" // for Printf
+
+ "math"
+
+ "log" // for Fatal
+
+ "errors"
+
+ "io" // for Reader
+)
+
+import (
+ // for Printf
+ "fmt"
+
+ "math"
+
+ // for Fatal
+ "log"
+
+ "errors"
+
+ // for Reader
+ "io"
+)
+
+import (
+ "fmt" // for Printf
+ "math"
+ "log" // for Fatal
+ "errors"
+ "io" // for Reader
+
+ "fmt" // for Printf
+
+ "math"
+
+ "log" // for Fatal
+
+ "errors"
+
+ "io" // for Reader
+)
+
+import (
+ "fmt" // for Printf
+
+ "math"
+ "log" // for Fatal
+ "errors"
+ "io" // for Reader
+
+ "fmt" // for Printf
+ "math"
+ "log" // for Fatal
+ "errors"
+ "io" // for Reader
+)
diff --git a/src/cmd/gofmt/testdata/old.golden b/src/cmd/gofmt/testdata/old.golden
new file mode 100644
index 000000000..95a0b72a0
--- /dev/null
+++ b/src/cmd/gofmt/testdata/old.golden
@@ -0,0 +1,9 @@
+package P
+
+func f() {
+ if x {
+ y
+ } else {
+ z
+ }
+}
diff --git a/src/cmd/gofmt/testdata/old.input b/src/cmd/gofmt/testdata/old.input
new file mode 100644
index 000000000..e24eed215
--- /dev/null
+++ b/src/cmd/gofmt/testdata/old.input
@@ -0,0 +1,8 @@
+package P
+
+func f() {
+ if x {
+ y
+ } else
+ z
+}
diff --git a/src/cmd/gofmt/testdata/rewrite3.golden b/src/cmd/gofmt/testdata/rewrite3.golden
new file mode 100644
index 000000000..0d16d1601
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite3.golden
@@ -0,0 +1,12 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Field tags are *ast.BasicLit nodes that are nil when the tag is
+// absent. These nil nodes must not be mistaken for expressions,
+// the rewriter should not try to dereference them. Was issue 2410.
+type Foo struct {
+ Field int
+}
diff --git a/src/cmd/gofmt/testdata/rewrite3.input b/src/cmd/gofmt/testdata/rewrite3.input
new file mode 100644
index 000000000..0d16d1601
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite3.input
@@ -0,0 +1,12 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Field tags are *ast.BasicLit nodes that are nil when the tag is
+// absent. These nil nodes must not be mistaken for expressions,
+// the rewriter should not try to dereference them. Was issue 2410.
+type Foo struct {
+ Field int
+}
diff --git a/src/cmd/gofmt/testdata/rewrite4.golden b/src/cmd/gofmt/testdata/rewrite4.golden
new file mode 100644
index 000000000..8dfc81a07
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite4.golden
@@ -0,0 +1,74 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Rewriting of parenthesized expressions (x) -> x
+// must not drop parentheses if that would lead to
+// wrong association of the operands.
+// Was issue 1847.
+
+package main
+
+// From example 1 of issue 1847.
+func _() {
+ var t = (&T{1000}).Id()
+}
+
+// From example 2 of issue 1847.
+func _() {
+ fmt.Println((*xpp).a)
+}
+
+// Some more test cases.
+func _() {
+ _ = (-x).f
+ _ = (*x).f
+ _ = (&x).f
+ _ = (!x).f
+ _ = -x.f
+ _ = *x.f
+ _ = &x.f
+ _ = !x.f
+ (-x).f()
+ (*x).f()
+ (&x).f()
+ (!x).f()
+ _ = -x.f()
+ _ = *x.f()
+ _ = &x.f()
+ _ = !x.f()
+
+ _ = (-x).f
+ _ = (*x).f
+ _ = (&x).f
+ _ = (!x).f
+ _ = -x.f
+ _ = *x.f
+ _ = &x.f
+ _ = !x.f
+ (-x).f()
+ (*x).f()
+ (&x).f()
+ (!x).f()
+ _ = -x.f()
+ _ = *x.f()
+ _ = &x.f()
+ _ = !x.f()
+
+ _ = -x.f
+ _ = *x.f
+ _ = &x.f
+ _ = !x.f
+ _ = -x.f
+ _ = *x.f
+ _ = &x.f
+ _ = !x.f
+ _ = -x.f()
+ _ = *x.f()
+ _ = &x.f()
+ _ = !x.f()
+ _ = -x.f()
+ _ = *x.f()
+ _ = &x.f()
+ _ = !x.f()
+}
diff --git a/src/cmd/gofmt/testdata/rewrite4.input b/src/cmd/gofmt/testdata/rewrite4.input
new file mode 100644
index 000000000..164cc0451
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite4.input
@@ -0,0 +1,74 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Rewriting of parenthesized expressions (x) -> x
+// must not drop parentheses if that would lead to
+// wrong association of the operands.
+// Was issue 1847.
+
+package main
+
+// From example 1 of issue 1847.
+func _() {
+ var t = (&T{1000}).Id()
+}
+
+// From example 2 of issue 1847.
+func _() {
+ fmt.Println((*xpp).a)
+}
+
+// Some more test cases.
+func _() {
+ _ = (-x).f
+ _ = (*x).f
+ _ = (&x).f
+ _ = (!x).f
+ _ = (-x.f)
+ _ = (*x.f)
+ _ = (&x.f)
+ _ = (!x.f)
+ (-x).f()
+ (*x).f()
+ (&x).f()
+ (!x).f()
+ _ = (-x.f())
+ _ = (*x.f())
+ _ = (&x.f())
+ _ = (!x.f())
+
+ _ = ((-x)).f
+ _ = ((*x)).f
+ _ = ((&x)).f
+ _ = ((!x)).f
+ _ = ((-x.f))
+ _ = ((*x.f))
+ _ = ((&x.f))
+ _ = ((!x.f))
+ ((-x)).f()
+ ((*x)).f()
+ ((&x)).f()
+ ((!x)).f()
+ _ = ((-x.f()))
+ _ = ((*x.f()))
+ _ = ((&x.f()))
+ _ = ((!x.f()))
+
+ _ = -(x).f
+ _ = *(x).f
+ _ = &(x).f
+ _ = !(x).f
+ _ = -x.f
+ _ = *x.f
+ _ = &x.f
+ _ = !x.f
+ _ = -(x).f()
+ _ = *(x).f()
+ _ = &(x).f()
+ _ = !(x).f()
+ _ = -x.f()
+ _ = *x.f()
+ _ = &x.f()
+ _ = !x.f()
+}
diff --git a/src/cmd/gofmt/testdata/stdin1.golden b/src/cmd/gofmt/testdata/stdin1.golden
new file mode 100644
index 000000000..ff8b0b7ab
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin1.golden
@@ -0,0 +1,3 @@
+ if x {
+ y
+ }
diff --git a/src/cmd/gofmt/testdata/stdin1.golden.gofmt b/src/cmd/gofmt/testdata/stdin1.golden.gofmt
new file mode 100644
index 000000000..1f888877d
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin1.golden.gofmt
@@ -0,0 +1,3 @@
+ if x {
+ y
+}
diff --git a/src/cmd/gofmt/testdata/stdin1.input b/src/cmd/gofmt/testdata/stdin1.input
new file mode 100644
index 000000000..ff8b0b7ab
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin1.input
@@ -0,0 +1,3 @@
+ if x {
+ y
+ }
diff --git a/src/cmd/gofmt/testdata/stdin1.input.gofmt b/src/cmd/gofmt/testdata/stdin1.input.gofmt
new file mode 100644
index 000000000..1f888877d
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin1.input.gofmt
@@ -0,0 +1,3 @@
+ if x {
+ y
+}
diff --git a/src/cmd/gofmt/testdata/stdin2.golden b/src/cmd/gofmt/testdata/stdin2.golden
new file mode 100644
index 000000000..7eb1b54fe
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin2.golden
@@ -0,0 +1,11 @@
+
+
+var x int
+
+func f() {
+ y := z
+ /* this is a comment */
+ // this is a comment too
+}
+
+
diff --git a/src/cmd/gofmt/testdata/stdin2.golden.gofmt b/src/cmd/gofmt/testdata/stdin2.golden.gofmt
new file mode 100644
index 000000000..85e800300
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin2.golden.gofmt
@@ -0,0 +1,10 @@
+
+
+
+var x int
+
+func f() {
+ y := z
+}
+
+
diff --git a/src/cmd/gofmt/testdata/stdin2.input b/src/cmd/gofmt/testdata/stdin2.input
new file mode 100644
index 000000000..99defd2d1
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin2.input
@@ -0,0 +1,11 @@
+
+
+var x int
+
+
+func f() { y := z
+ /* this is a comment */
+ // this is a comment too
+}
+
+
diff --git a/src/cmd/gofmt/testdata/stdin2.input.gofmt b/src/cmd/gofmt/testdata/stdin2.input.gofmt
new file mode 100644
index 000000000..7eb1b54fe
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin2.input.gofmt
@@ -0,0 +1,11 @@
+
+
+var x int
+
+func f() {
+ y := z
+ /* this is a comment */
+ // this is a comment too
+}
+
+
diff --git a/src/cmd/gofmt/testdata/stdin3.golden b/src/cmd/gofmt/testdata/stdin3.golden
new file mode 100644
index 000000000..1bf2f5a48
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin3.golden
@@ -0,0 +1,6 @@
+
+ /* note: no newline at end of file */
+ for i := 0; i < 10; i++ {
+ s += i
+ }
+ \ No newline at end of file
diff --git a/src/cmd/gofmt/testdata/stdin3.golden.gofmt b/src/cmd/gofmt/testdata/stdin3.golden.gofmt
new file mode 100644
index 000000000..b4d1d4663
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin3.golden.gofmt
@@ -0,0 +1,7 @@
+
+
+ /* note: no newline at end of file */
+ for i := 0; i < 10; i++ {
+ s += i
+ }
+ \ No newline at end of file
diff --git a/src/cmd/gofmt/testdata/stdin3.input b/src/cmd/gofmt/testdata/stdin3.input
new file mode 100644
index 000000000..d963bd0d2
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin3.input
@@ -0,0 +1,4 @@
+
+ /* note: no newline at end of file */
+ for i := 0; i < 10; i++ { s += i }
+ \ No newline at end of file
diff --git a/src/cmd/gofmt/testdata/stdin3.input.gofmt b/src/cmd/gofmt/testdata/stdin3.input.gofmt
new file mode 100644
index 000000000..b4d1d4663
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin3.input.gofmt
@@ -0,0 +1,7 @@
+
+
+ /* note: no newline at end of file */
+ for i := 0; i < 10; i++ {
+ s += i
+ }
+ \ No newline at end of file
diff --git a/src/cmd/gofmt/testdata/stdin4.golden b/src/cmd/gofmt/testdata/stdin4.golden
new file mode 100644
index 000000000..5f7343551
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin4.golden
@@ -0,0 +1,3 @@
+ // comment
+
+ i := 0
diff --git a/src/cmd/gofmt/testdata/stdin4.golden.gofmt b/src/cmd/gofmt/testdata/stdin4.golden.gofmt
new file mode 100644
index 000000000..5f7343551
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin4.golden.gofmt
@@ -0,0 +1,3 @@
+ // comment
+
+ i := 0
diff --git a/src/cmd/gofmt/testdata/stdin4.input b/src/cmd/gofmt/testdata/stdin4.input
new file mode 100644
index 000000000..f02a54fb1
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin4.input
@@ -0,0 +1,3 @@
+ // comment
+
+ i := 0
diff --git a/src/cmd/gofmt/testdata/stdin4.input.gofmt b/src/cmd/gofmt/testdata/stdin4.input.gofmt
new file mode 100644
index 000000000..5f7343551
--- /dev/null
+++ b/src/cmd/gofmt/testdata/stdin4.input.gofmt
@@ -0,0 +1,3 @@
+ // comment
+
+ i := 0