diff options
author | Ondřej Surý <ondrej@sury.org> | 2012-04-06 15:14:11 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2012-04-06 15:14:11 +0200 |
commit | 505c19580e0f43fe5224431459cacb7c21edd93d (patch) | |
tree | 79e2634c253d60afc0cc0b2f510dc7dcbb48497b /src/cmd/gofmt | |
parent | 1336a7c91e596c423a49d1194ea42d98bca0d958 (diff) | |
download | golang-505c19580e0f43fe5224431459cacb7c21edd93d.tar.gz |
Imported Upstream version 1upstream/1
Diffstat (limited to 'src/cmd/gofmt')
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 |