Remove unused imports via go/types.

Fixes #481
pull/514/head
lu4p 4 years ago
parent 8e7765ee6f
commit d555639657

@ -10,7 +10,6 @@ import (
"go/token" "go/token"
"go/types" "go/types"
mathrand "math/rand" mathrand "math/rand"
"strconv"
"golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/ast/astutil"
ah "mvdan.cc/garble/internal/asthelper" ah "mvdan.cc/garble/internal/asthelper"
@ -130,46 +129,7 @@ func Obfuscate(file *ast.File, info *types.Info, fset *token.FileSet, linkString
return true return true
} }
// Imports which are used might be marked as unused by only looking at the ast, return astutil.Apply(file, pre, post).(*ast.File)
// because packages can declare a name different from the last element of their import path.
//
// package main
//
// import "github.com/user/somepackage"
//
// func main(){
// // this line uses github.com/user/somepackage
// anotherpackage.Foo()
// }
//
// TODO: remove this check and detect used imports with go/types somehow
prevUsedImports := make(map[string]bool)
for _, imp := range file.Imports {
path, err := strconv.Unquote(imp.Path.Value)
if err != nil {
panic(err)
}
prevUsedImports[path] = astutil.UsesImport(file, path)
}
file = astutil.Apply(file, pre, post).(*ast.File)
// some imported constants might not be needed anymore, remove unnecessary imports
for _, imp := range file.Imports {
path, err := strconv.Unquote(imp.Path.Value)
if err != nil {
panic(err)
}
if !prevUsedImports[path] || astutil.UsesImport(file, path) {
continue
}
if !astutil.DeleteImport(fset, file, path) {
panic(fmt.Sprintf("cannot delete unused import: %v", path))
}
}
return file
} }
// withPos sets any token.Pos fields under node which affect printing to pos. // withPos sets any token.Pos fields under node which affect printing to pos.

@ -1453,6 +1453,50 @@ func (tf *transformer) transformGo(file *ast.File) *ast.File {
// and that's not allowed in the runtime itself. // and that's not allowed in the runtime itself.
if flagLiterals && curPkg.ToObfuscate { if flagLiterals && curPkg.ToObfuscate {
file = literals.Obfuscate(file, tf.info, fset, tf.linkerVariableStrings) file = literals.Obfuscate(file, tf.info, fset, tf.linkerVariableStrings)
// some imported constants might not be needed anymore, remove unnecessary imports
usedImports := make(map[string]bool)
ast.Inspect(file, func(n ast.Node) bool {
node, ok := n.(*ast.Ident)
if !ok {
return true
}
uses, ok := tf.info.Uses[node].(*types.PkgName)
if !ok {
return true
}
usedImports[uses.Imported().Path()] = true
return true
})
for _, imp := range file.Imports {
if imp.Name != nil && (imp.Name.Name == "_" || imp.Name.Name == ".") {
continue
}
path, err := strconv.Unquote(imp.Path.Value)
if err != nil {
panic(err)
}
// The import path can't be used directly here, because the actual
// path resolved via go/types might be different from the naive path.
lpkg, err := listPackage(path)
if err != nil {
panic(err)
}
if usedImports[lpkg.ImportPath] {
continue
}
if !astutil.DeleteImport(fset, file, path) {
panic(fmt.Sprintf("cannot delete unused import: %q", path))
}
}
} }
pre := func(cursor *astutil.Cursor) bool { pre := func(cursor *astutil.Cursor) bool {

@ -64,7 +64,7 @@ package main
import ( import (
_ "runtime/debug" _ "runtime/debug"
"test/main/imported" "test/main/imp"
) )
type structTest struct { type structTest struct {
@ -295,7 +295,7 @@ func shadowTest() {
println("obfuscated with shadowed builtins (types)") println("obfuscated with shadowed builtins (types)")
} }
} }
-- imported/imported.go -- -- imp/imported.go --
package imported package imported
type ImportedType int type ImportedType int

Loading…
Cancel
Save