support type switches with symbolic vars

pull/22/head
Daniel Martí 5 years ago
parent 766bb47b82
commit aba66758ca

@ -2,4 +2,7 @@ module mvdan.cc/garble
go 1.14 go 1.14
require github.com/rogpeppe/go-internal v1.5.0 require (
github.com/rogpeppe/go-internal v1.5.0
golang.org/x/tools v0.0.0-20191206204035-259af5ff87bd
)

@ -1,8 +1,19 @@
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/rogpeppe/go-internal v1.5.0 h1:Usqs0/lDK/NqTkvrmKSwA/3XkZAs7ZAW/eLeQ2MVBTw= github.com/rogpeppe/go-internal v1.5.0 h1:Usqs0/lDK/NqTkvrmKSwA/3XkZAs7ZAW/eLeQ2MVBTw=
github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191206204035-259af5ff87bd h1:Zc7EU2PqpsNeIfOoVA7hvQX4cS3YDJEs5KlfatT3hLo=
golang.org/x/tools v0.0.0-20191206204035-259af5ff87bd/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=

@ -22,6 +22,8 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"strings" "strings"
"golang.org/x/tools/go/ast/astutil"
) )
var flagSet = flag.NewFlagSet("garble", flag.ContinueOnError) var flagSet = flag.NewFlagSet("garble", flag.ContinueOnError)
@ -186,8 +188,9 @@ func transformCompile(args []string) ([]string, error) {
return nil, fmt.Errorf("typecheck error: %v", err) return nil, fmt.Errorf("typecheck error: %v", err)
} }
for i, file := range files { args = flags
file := transformGoFile(file, info) for _, file := range files {
file := transformGo(file, info)
f, err := ioutil.TempFile("", "garble") f, err := ioutil.TempFile("", "garble")
if err != nil { if err != nil {
return nil, err return nil, err
@ -203,9 +206,9 @@ func transformCompile(args []string) ([]string, error) {
deferred = append(deferred, func() error { deferred = append(deferred, func() error {
return os.Remove(f.Name()) return os.Remove(f.Name())
}) })
paths[i] = f.Name() args = append(args, f.Name())
} }
return append(flags, paths...), nil return args, nil
} }
func readBuildIDs(flags []string) error { func readBuildIDs(flags []string) error {
@ -284,12 +287,14 @@ func hashWith(salt, value string) string {
return "z" + sum[:length] return "z" + sum[:length]
} }
// transformGoFile creates a garbled copy of the Go file at path, and returns // transformGo garbles the provided Go syntax node.
// the path to the copy. func transformGo(node ast.Node, info *types.Info) ast.Node {
func transformGoFile(file *ast.File, info *types.Info) *ast.File { pre := func(cursor *astutil.Cursor) bool {
ast.Inspect(file, func(node ast.Node) bool { switch node := cursor.Node().(type) {
switch node := node.(type) {
case *ast.Ident: case *ast.Ident:
if node.Name == "_" {
return true // unnamed remains unnamed
}
obj := info.ObjectOf(node) obj := info.ObjectOf(node)
switch obj.(type) { switch obj.(type) {
case *types.Var: case *types.Var:
@ -300,9 +305,18 @@ func transformGoFile(file *ast.File, info *types.Info) *ast.File {
case "main", "init": case "main", "init":
return true // don't break them return true // don't break them
} }
case nil:
switch cursor.Parent().(type) {
case *ast.AssignStmt:
// symbolic var v in v := expr.(type)
default:
return true
}
default: default:
return true // we only want to rename the above return true // we only want to rename the above
} }
buildID := buildInfo.buildID
if obj != nil {
pkg := obj.Pkg() pkg := obj.Pkg()
if pkg == nil { if pkg == nil {
return true // universe scope return true // universe scope
@ -311,17 +325,16 @@ func transformGoFile(file *ast.File, info *types.Info) *ast.File {
if !strings.Contains(path, ".") { if !strings.Contains(path, ".") {
return true // std isn't transformed return true // std isn't transformed
} }
buildID := buildInfo.buildID
if id := buildInfo.imports[path].buildID; id != "" { if id := buildInfo.imports[path].buildID; id != "" {
buildID = id buildID = id
} }
}
// log.Printf("%#v\n", node.Obj) // log.Printf("%#v\n", node.Obj)
node.Name = hashWith(buildID, node.Name) node.Name = hashWith(buildID, node.Name)
} }
return true return true
}) }
return file return astutil.Apply(node, pre, nil)
} }
func transformLink(args []string) ([]string, error) { func transformLink(args []string) ([]string, error) {

@ -0,0 +1,19 @@
garble build main.go
exec ./main
cmp stderr main.stderr
-- main.go --
package main
var V interface{}
func main() {
switch V := V.(type) {
case int:
var _ int = V
case nil:
println("nil case")
}
}
-- main.stderr --
nil case
Loading…
Cancel
Save