mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
parent
bcd6c733b2
commit
d7106f280d
7 changed files with 196 additions and 1 deletions
|
|
@ -9,6 +9,7 @@ GOFILES=\
|
||||||
fix.go\
|
fix.go\
|
||||||
main.go\
|
main.go\
|
||||||
httpserver.go\
|
httpserver.go\
|
||||||
|
procattr.go\
|
||||||
|
|
||||||
include ../../Make.cmd
|
include ../../Make.cmd
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,11 @@ func isName(n ast.Expr, name string) bool {
|
||||||
return id.String() == name
|
return id.String() == name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isCall(t ast.Expr, pkg, name string) bool {
|
||||||
|
call, ok := t.(*ast.CallExpr)
|
||||||
|
return ok && isPkgDot(call.Fun, pkg, name)
|
||||||
|
}
|
||||||
|
|
||||||
func refersTo(n ast.Node, x *ast.Ident) bool {
|
func refersTo(n ast.Node, x *ast.Ident) bool {
|
||||||
id, ok := n.(*ast.Ident)
|
id, ok := n.(*ast.Ident)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
||||||
|
|
@ -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
|
package main
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ func main() {
|
||||||
const (
|
const (
|
||||||
tabWidth = 8
|
tabWidth = 8
|
||||||
parserMode = parser.ParseComments
|
parserMode = parser.ParseComments
|
||||||
printerMode = printer.TabIndent
|
printerMode = printer.TabIndent | printer.UseSpaces
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,12 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"exec"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/printer"
|
"go/printer"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -42,6 +45,7 @@ func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out
|
||||||
if s := buf.String(); in != s {
|
if s := buf.String(); in != s {
|
||||||
t.Errorf("%s: not gofmt-formatted.\n--- %s\n%s\n--- %s | gofmt\n%s",
|
t.Errorf("%s: not gofmt-formatted.\n--- %s\n%s\n--- %s | gofmt\n%s",
|
||||||
desc, desc, in, desc, s)
|
desc, desc, in, desc, s)
|
||||||
|
tdiff(t, in, s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,6 +79,7 @@ func TestRewrite(t *testing.T) {
|
||||||
|
|
||||||
if out != tt.Out {
|
if out != tt.Out {
|
||||||
t.Errorf("%s: incorrect output.\n--- have\n%s\n--- want\n%s", tt.Name, out, tt.Out)
|
t.Errorf("%s: incorrect output.\n--- have\n%s\n--- want\n%s", tt.Name, out, tt.Out)
|
||||||
|
tdiff(t, out, tt.Out)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,6 +102,50 @@ func TestRewrite(t *testing.T) {
|
||||||
if out2 != out {
|
if out2 != out {
|
||||||
t.Errorf("%s: changed output after second round of fixes.\n--- output after first round\n%s\n--- output after second round\n%s",
|
t.Errorf("%s: changed output after second round of fixes.\n--- output after first round\n%s\n--- output after second round\n%s",
|
||||||
tt.Name, out, out2)
|
tt.Name, out, out2)
|
||||||
|
tdiff(t, out, out2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tdiff(t *testing.T, a, b string) {
|
||||||
|
f1, err := ioutil.TempFile("", "gofix")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.Remove(f1.Name())
|
||||||
|
defer f1.Close()
|
||||||
|
|
||||||
|
f2, err := ioutil.TempFile("", "gofix")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.Remove(f2.Name())
|
||||||
|
defer f2.Close()
|
||||||
|
|
||||||
|
f1.Write([]byte(a))
|
||||||
|
f2.Write([]byte(b))
|
||||||
|
|
||||||
|
diffcmd, err := exec.LookPath("diff")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := exec.Run(diffcmd, []string{"diff", f1.Name(), f2.Name()}, nil, "",
|
||||||
|
exec.DevNull, exec.Pipe, exec.MergeWithStdout)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(c.Stdout)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error(string(data))
|
||||||
|
}
|
||||||
|
|
|
||||||
61
src/cmd/gofix/procattr.go
Normal file
61
src/cmd/gofix/procattr.go
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
var procattrFix = fix{
|
||||||
|
"procattr",
|
||||||
|
procattr,
|
||||||
|
`Adapt calls to os.StartProcess to use new ProcAttr type.
|
||||||
|
|
||||||
|
http://codereview.appspot.com/4253052
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
register(httpserverFix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func procattr(f *ast.File) bool {
|
||||||
|
if !imports(f, "os") && !imports(f, "syscall") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed := false
|
||||||
|
rewrite(f, func(n interface{}) {
|
||||||
|
call, ok := n.(*ast.CallExpr)
|
||||||
|
if !ok || len(call.Args) != 5 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var pkg string
|
||||||
|
if isPkgDot(call.Fun, "os", "StartProcess") {
|
||||||
|
pkg = "os"
|
||||||
|
} else if isPkgDot(call.Fun, "syscall", "StartProcess") {
|
||||||
|
pkg = "syscall"
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// os.StartProcess(a, b, c, d, e) -> os.StartProcess(a, b, &os.ProcAttr{Env: c, Dir: d, Files: e})
|
||||||
|
lit := &ast.CompositeLit{Type: ast.NewIdent(pkg + ".ProcAttr")}
|
||||||
|
env, dir, files := call.Args[2], call.Args[3], call.Args[4]
|
||||||
|
if !isName(env, "nil") && !isCall(env, "os", "Environ") {
|
||||||
|
lit.Elts = append(lit.Elts, &ast.KeyValueExpr{Key: ast.NewIdent("Env"), Value: env})
|
||||||
|
}
|
||||||
|
if !isEmptyString(dir) {
|
||||||
|
lit.Elts = append(lit.Elts, &ast.KeyValueExpr{Key: ast.NewIdent("Dir"), Value: dir})
|
||||||
|
}
|
||||||
|
if !isName(files, "nil") {
|
||||||
|
lit.Elts = append(lit.Elts, &ast.KeyValueExpr{Key: ast.NewIdent("Files"), Value: files})
|
||||||
|
}
|
||||||
|
call.Args[2] = &ast.UnaryExpr{Op: token.AND, X: lit}
|
||||||
|
call.Args = call.Args[:3]
|
||||||
|
fixed = true
|
||||||
|
})
|
||||||
|
return fixed
|
||||||
|
}
|
||||||
75
src/cmd/gofix/procattr_test.go
Normal file
75
src/cmd/gofix/procattr_test.go
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
addTestCases(procattrTests)
|
||||||
|
}
|
||||||
|
|
||||||
|
var procattrTests = []testCase{
|
||||||
|
{
|
||||||
|
Name: "procattr.0",
|
||||||
|
Fn: procattr,
|
||||||
|
In: `package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f() {
|
||||||
|
os.StartProcess(a, b, c, d, e)
|
||||||
|
os.StartProcess(a, b, os.Environ(), d, e)
|
||||||
|
os.StartProcess(a, b, nil, d, e)
|
||||||
|
os.StartProcess(a, b, c, "", e)
|
||||||
|
os.StartProcess(a, b, c, d, nil)
|
||||||
|
os.StartProcess(a, b, nil, "", nil)
|
||||||
|
|
||||||
|
os.StartProcess(
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
d,
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
|
syscall.StartProcess(a, b, c, d, e)
|
||||||
|
syscall.StartProcess(a, b, os.Environ(), d, e)
|
||||||
|
syscall.StartProcess(a, b, nil, d, e)
|
||||||
|
syscall.StartProcess(a, b, c, "", e)
|
||||||
|
syscall.StartProcess(a, b, c, d, nil)
|
||||||
|
syscall.StartProcess(a, b, nil, "", nil)
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
Out: `package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f() {
|
||||||
|
os.StartProcess(a, b, &os.ProcAttr{Env: c, Dir: d, Files: e})
|
||||||
|
os.StartProcess(a, b, &os.ProcAttr{Dir: d, Files: e})
|
||||||
|
os.StartProcess(a, b, &os.ProcAttr{Dir: d, Files: e})
|
||||||
|
os.StartProcess(a, b, &os.ProcAttr{Env: c, Files: e})
|
||||||
|
os.StartProcess(a, b, &os.ProcAttr{Env: c, Dir: d})
|
||||||
|
os.StartProcess(a, b, &os.ProcAttr{})
|
||||||
|
|
||||||
|
os.StartProcess(
|
||||||
|
a,
|
||||||
|
b, &os.ProcAttr{Env: c, Dir: d, Files: e},
|
||||||
|
)
|
||||||
|
|
||||||
|
syscall.StartProcess(a, b, &syscall.ProcAttr{Env: c, Dir: d, Files: e})
|
||||||
|
syscall.StartProcess(a, b, &syscall.ProcAttr{Dir: d, Files: e})
|
||||||
|
syscall.StartProcess(a, b, &syscall.ProcAttr{Dir: d, Files: e})
|
||||||
|
syscall.StartProcess(a, b, &syscall.ProcAttr{Env: c, Files: e})
|
||||||
|
syscall.StartProcess(a, b, &syscall.ProcAttr{Env: c, Dir: d})
|
||||||
|
syscall.StartProcess(a, b, &syscall.ProcAttr{})
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue