From 1b75f346bea1bf65f9f1d1427d7b4273677c2565 Mon Sep 17 00:00:00 2001 From: lu4p Date: Thu, 28 May 2020 19:19:57 +0200 Subject: [PATCH] Add ability to exclude identifiers fixes #15 --- main.go | 49 ++++++++++++++++++++++++++++++++++-- testdata/scripts/imports.txt | 12 +++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 5e9f950..3e61be9 100644 --- a/main.go +++ b/main.go @@ -319,6 +319,9 @@ func transformCompile(args []string) ([]string, error) { flags = flagSetValue(flags, "-trimpath", tempDir+"=>;"+trimpath) // log.Println(flags) args = flags + + blacklist := buildBlacklist(files, info) + // TODO: randomize the order and names of the files for i, file := range files { origName := filepath.Base(filepath.Clean(paths[i])) @@ -330,7 +333,7 @@ func transformCompile(args []string) ([]string, error) { // messy. name = "_cgo_" + name default: - file = transformGo(file, info) + file = transformGo(file, info, blacklist) } tempFile := filepath.Join(tempDir, name) f, err := os.Create(tempFile) @@ -444,8 +447,43 @@ func hashWith(salt, value string) string { return "z" + sum[:length] } +func buildBlacklist(files []*ast.File, info *types.Info) (blacklist []types.Object) { + pre := func(node ast.Node) bool { + nodeExpr, ok := node.(*ast.CallExpr) + if !ok { + return true + } + + exprFunc, ok := nodeExpr.Fun.(*ast.SelectorExpr) + if !ok { + return true + } + + exprFuncType := info.ObjectOf(exprFunc.Sel) + + if exprFuncType.Pkg().Path() == "reflect" && (exprFuncType.Name() == "TypeOf" || exprFuncType.Name() == "ValueOf") { + for _, arg := range nodeExpr.Args { + if expr, ok := arg.(*ast.CallExpr); ok { + if f, ok := expr.Fun.(*ast.Ident); ok { + blacklistItem := info.ObjectOf(f) + blacklist = append(blacklist, blacklistItem) + } + } + } + } + + return true + } + + for _, file := range files { + ast.Inspect(file, pre) + } + + return blacklist +} + // transformGo garbles the provided Go syntax node. -func transformGo(file *ast.File, info *types.Info) *ast.File { +func transformGo(file *ast.File, info *types.Info, blacklist []types.Object) *ast.File { // Remove all comments, minus the "//go:" compiler directives. // The final binary should still not contain comment text, but removing // it helps ensure that (and makes position info less predictable). @@ -497,6 +535,13 @@ func transformGo(file *ast.File, info *types.Info) *ast.File { // about other -buildmode options? return true // could be a Go plugin API } + + for _, item := range blacklist { + if item.Pkg().Path() == obj.Pkg().Path() && item.Name() == obj.Name() { + return true + } + } + // log.Printf("%#v %T", node, obj) switch x := obj.(type) { case *types.Var: diff --git a/testdata/scripts/imports.txt b/testdata/scripts/imports.txt index 04b82d4..0d95cd6 100644 --- a/testdata/scripts/imports.txt +++ b/testdata/scripts/imports.txt @@ -3,6 +3,7 @@ exec ./main cmp stdout main.stdout ! binsubstr main$exe 'ImportedVar' 'ImportedConst' 'ImportedFunc' 'ImportedType' 'main.go' 'imported.go' +binsubstr main$exe 'ImportedAPI' [short] stop # checking that the build is reproducible is slow @@ -23,6 +24,7 @@ package main import ( "fmt" + "reflect" _ "unsafe" "test/main/imported" @@ -38,6 +40,9 @@ func main() { fmt.Println(imported.ImportedConst) imported.ImportedFunc('x') fmt.Println(imported.ImportedType(3)) + + api := new(imported.ImportedAPI) + fmt.Println(reflect.TypeOf(api)) linkedPrintln(nil) fmt.Println(quote.Go()) } @@ -45,11 +50,14 @@ func main() { imported var value imported const value 3 +*imported.ImportedAPI Don't communicate by sharing memory, share memory by communicating. -- imported/imported.go -- package imported +import "reflect" + var ImportedVar = "imported var value" const ImportedConst = "imported const value" @@ -59,3 +67,7 @@ func ImportedFunc(param rune) string { } type ImportedType int + +type ImportedAPI int + +var _ = reflect.TypeOf(ImportedAPI(0)) \ No newline at end of file