summaryrefslogtreecommitdiff
path: root/src/cmd/gofix/procattr.go
blob: 0e2190b1f4c95e3dfb5456f141b3897d8a5ae377 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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(procattrFix)
}

func procattr(f *ast.File) bool {
	if !imports(f, "os") && !imports(f, "syscall") {
		return false
	}

	fixed := false
	walk(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
}