summaryrefslogtreecommitdiff
path: root/src/cmd/gofmt
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gofmt')
-rw-r--r--src/cmd/gofmt/doc.go26
-rw-r--r--src/cmd/gofmt/gofmt.go46
-rw-r--r--src/cmd/gofmt/gofmt_test.go1
-rw-r--r--src/cmd/gofmt/rewrite.go39
-rw-r--r--src/cmd/gofmt/simplify.go4
-rwxr-xr-xsrc/cmd/gofmt/test.sh2
-rw-r--r--src/cmd/gofmt/testdata/rewrite1.golden4
-rw-r--r--src/cmd/gofmt/testdata/rewrite1.input4
-rw-r--r--src/cmd/gofmt/testdata/rewrite2.golden10
-rw-r--r--src/cmd/gofmt/testdata/rewrite2.input10
10 files changed, 122 insertions, 24 deletions
diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go
index e44030eee..1373b2657 100644
--- a/src/cmd/gofmt/doc.go
+++ b/src/cmd/gofmt/doc.go
@@ -8,29 +8,37 @@ Gofmt formats Go programs.
Without an explicit path, it processes the standard input. Given a file,
it operates on that file; given a directory, it operates on all .go files in
that directory, recursively. (Files starting with a period are ignored.)
+By default, gofmt prints the reformatted sources to standard output.
Usage:
gofmt [flags] [path ...]
The flags are:
+ -d
+ Do not print reformatted sources to standard output.
+ If a file's formatting is different than gofmt's, print diffs
+ to standard output.
-l
- just list files whose formatting differs from gofmt's;
- generate no other output unless -w is also set.
+ Do not print reformatted sources to standard output.
+ If a file's formatting is different from gofmt's, print its name
+ to standard output.
-r rule
- apply the rewrite rule to the source before reformatting.
+ Apply the rewrite rule to the source before reformatting.
-s
- try to simplify code (after applying the rewrite rule, if any).
+ Try to simplify code (after applying the rewrite rule, if any).
-w
- if set, overwrite each input file with its output.
+ Do not print reformatted sources to standard output.
+ If a file's formatting is different from gofmt's, overwrite it
+ with gofmt's version.
-comments=true
- print comments; if false, all comments are elided from the output.
+ Print comments; if false, all comments are elided from the output.
-spaces
- align with spaces instead of tabs.
+ Align with spaces instead of tabs.
-tabindent
- indent with tabs independent of -spaces.
+ Indent with tabs independent of -spaces.
-tabwidth=8
- tab width in spaces.
+ Tab width in spaces.
The rewrite rule specified with the -r flag must be a string of the form:
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index ce274aa21..5dd801d90 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -6,6 +6,7 @@ package main
import (
"bytes"
+ "exec"
"flag"
"fmt"
"go/ast"
@@ -28,6 +29,7 @@ var (
write = flag.Bool("w", false, "write result to (source) file instead of stdout")
rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'α[β:len(α)] -> α[β:]')")
simplifyAST = flag.Bool("s", false, "simplify code")
+ doDiff = flag.Bool("d", false, "display diffs instead of rewriting files")
// layout control
comments = flag.Bool("comments", true, "print comments")
@@ -134,9 +136,17 @@ func processFile(filename string, in io.Reader, out io.Writer) os.Error {
return err
}
}
+ if *doDiff {
+ data, err := diff(src, res)
+ if err != nil {
+ return fmt.Errorf("computing diff: %s", err)
+ }
+ fmt.Printf("diff %s gofmt/%s\n", filename, filename)
+ out.Write(data)
+ }
}
- if !*list && !*write {
+ if !*list && !*write && !*doDiff {
_, err = out.Write(res)
}
@@ -230,3 +240,37 @@ func gofmtMain() {
}
}
}
+
+
+func diff(b1, b2 []byte) (data []byte, err os.Error) {
+ f1, err := ioutil.TempFile("", "gofmt")
+ if err != nil {
+ return nil, err
+ }
+ defer os.Remove(f1.Name())
+ defer f1.Close()
+
+ f2, err := ioutil.TempFile("", "gofmt")
+ if err != nil {
+ return nil, err
+ }
+ defer os.Remove(f2.Name())
+ defer f2.Close()
+
+ f1.Write(b1)
+ f2.Write(b2)
+
+ diffcmd, err := exec.LookPath("diff")
+ if err != nil {
+ return nil, err
+ }
+
+ c, err := exec.Run(diffcmd, []string{"diff", "-u", f1.Name(), f2.Name()},
+ nil, "", exec.DevNull, exec.Pipe, exec.MergeWithStdout)
+ if err != nil {
+ return nil, err
+ }
+ defer c.Close()
+
+ return ioutil.ReadAll(c.Stdout)
+}
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index 4ec94e293..a72530307 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -71,6 +71,7 @@ var tests = []struct {
{".", "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"},
}
diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go
index 93643dced..4c24282f3 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -19,6 +19,7 @@ import (
func initRewrite() {
if *rewriteRule == "" {
+ rewrite = nil // disable any previous rewrite
return
}
f := strings.Split(*rewriteRule, "->", -1)
@@ -59,26 +60,34 @@ func dump(msg string, val reflect.Value) {
// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
m := make(map[string]reflect.Value)
- pat := reflect.NewValue(pattern)
- repl := reflect.NewValue(replace)
+ pat := reflect.ValueOf(pattern)
+ repl := reflect.ValueOf(replace)
var f func(val reflect.Value) reflect.Value // f is recursive
f = func(val reflect.Value) reflect.Value {
+ // don't bother if val is invalid to start with
+ if !val.IsValid() {
+ return reflect.Value{}
+ }
for k := range m {
m[k] = reflect.Value{}, false
}
val = apply(f, val)
if match(m, pat, val) {
- val = subst(m, repl, reflect.NewValue(val.Interface().(ast.Node).Pos()))
+ val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos()))
}
return val
}
- return apply(f, reflect.NewValue(p)).Interface().(*ast.File)
+ return apply(f, reflect.ValueOf(p)).Interface().(*ast.File)
}
// setValue is a wrapper for x.SetValue(y); it protects
// the caller from panics if x cannot be changed to y.
func setValue(x, y reflect.Value) {
+ // don't bother if y is invalid to start with
+ if !y.IsValid() {
+ return
+ }
defer func() {
if x := recover(); x != nil {
if s, ok := x.(string); ok && strings.HasPrefix(s, "type mismatch") {
@@ -94,11 +103,13 @@ func setValue(x, y reflect.Value) {
// Values/types for special cases.
var (
- objectPtrNil = reflect.NewValue((*ast.Object)(nil))
+ objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
+ scopePtrNil = reflect.ValueOf((*ast.Scope)(nil))
- identType = reflect.Typeof((*ast.Ident)(nil))
- objectPtrType = reflect.Typeof((*ast.Object)(nil))
- positionType = reflect.Typeof(token.NoPos)
+ identType = reflect.TypeOf((*ast.Ident)(nil))
+ objectPtrType = reflect.TypeOf((*ast.Object)(nil))
+ positionType = reflect.TypeOf(token.NoPos)
+ scopePtrType = reflect.TypeOf((*ast.Scope)(nil))
)
@@ -115,6 +126,12 @@ func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value
return objectPtrNil
}
+ // similarly for scopes: they are likely incorrect after a rewrite;
+ // replace them with nil
+ if val.Type() == scopePtrType {
+ return scopePtrNil
+ }
+
switch v := reflect.Indirect(val); v.Kind() {
case reflect.Slice:
for i := 0; i < v.Len(); i++ {
@@ -259,21 +276,21 @@ func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value)
return v
case reflect.Struct:
- v := reflect.Zero(p.Type())
+ v := reflect.New(p.Type()).Elem()
for i := 0; i < p.NumField(); i++ {
v.Field(i).Set(subst(m, p.Field(i), pos))
}
return v
case reflect.Ptr:
- v := reflect.Zero(p.Type())
+ v := reflect.New(p.Type()).Elem()
if elem := p.Elem(); elem.IsValid() {
v.Set(subst(m, elem, pos).Addr())
}
return v
case reflect.Interface:
- v := reflect.Zero(p.Type())
+ v := reflect.New(p.Type()).Elem()
if elem := p.Elem(); elem.IsValid() {
v.Set(subst(m, elem, pos))
}
diff --git a/src/cmd/gofmt/simplify.go b/src/cmd/gofmt/simplify.go
index bcc67c4a6..40a9f8f17 100644
--- a/src/cmd/gofmt/simplify.go
+++ b/src/cmd/gofmt/simplify.go
@@ -26,7 +26,7 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
}
if eltType != nil {
- typ := reflect.NewValue(eltType)
+ typ := reflect.ValueOf(eltType)
for _, x := range outer.Elts {
// look at value of indexed/named elements
if t, ok := x.(*ast.KeyValueExpr); ok {
@@ -37,7 +37,7 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
// matches the outer literal's element type exactly, the inner
// literal type may be omitted
if inner, ok := x.(*ast.CompositeLit); ok {
- if match(nil, typ, reflect.NewValue(inner.Type)) {
+ if match(nil, typ, reflect.ValueOf(inner.Type)) {
inner.Type = nil
}
}
diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh
index 3340c48f0..99ec76932 100755
--- a/src/cmd/gofmt/test.sh
+++ b/src/cmd/gofmt/test.sh
@@ -36,7 +36,7 @@ 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 | \
+ func3.go | const2.go | char_lit1.go | blank1.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 | \
diff --git a/src/cmd/gofmt/testdata/rewrite1.golden b/src/cmd/gofmt/testdata/rewrite1.golden
index 3f909ff4a..d9beb3705 100644
--- a/src/cmd/gofmt/testdata/rewrite1.golden
+++ b/src/cmd/gofmt/testdata/rewrite1.golden
@@ -1,3 +1,7 @@
+// 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
type Bar int
diff --git a/src/cmd/gofmt/testdata/rewrite1.input b/src/cmd/gofmt/testdata/rewrite1.input
index 1f10e3601..bdb894320 100644
--- a/src/cmd/gofmt/testdata/rewrite1.input
+++ b/src/cmd/gofmt/testdata/rewrite1.input
@@ -1,3 +1,7 @@
+// 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
type Foo int
diff --git a/src/cmd/gofmt/testdata/rewrite2.golden b/src/cmd/gofmt/testdata/rewrite2.golden
new file mode 100644
index 000000000..64c67ffa6
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite2.golden
@@ -0,0 +1,10 @@
+// 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 p
+
+// Slices have nil Len values in the corresponding ast.ArrayType
+// node and reflect.NewValue(slice.Len) is an invalid reflect.Value.
+// The rewriter must not crash in that case. Was issue 1696.
+func f() []bool {}
diff --git a/src/cmd/gofmt/testdata/rewrite2.input b/src/cmd/gofmt/testdata/rewrite2.input
new file mode 100644
index 000000000..21171447a
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite2.input
@@ -0,0 +1,10 @@
+// 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 p
+
+// Slices have nil Len values in the corresponding ast.ArrayType
+// node and reflect.NewValue(slice.Len) is an invalid reflect.Value.
+// The rewriter must not crash in that case. Was issue 1696.
+func f() []int {}