Remove unused imports via go/types.

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

@ -10,7 +10,6 @@ import (
"go/token"
"go/types"
mathrand "math/rand"
"strconv"
"golang.org/x/tools/go/ast/astutil"
ah "mvdan.cc/garble/internal/asthelper"
@ -130,46 +129,7 @@ func Obfuscate(file *ast.File, info *types.Info, fset *token.FileSet, linkString
return true
}
// Imports which are used might be marked as unused by only looking at the ast,
// 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
return astutil.Apply(file, pre, post).(*ast.File)
}
// 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.
if flagLiterals && curPkg.ToObfuscate {
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 {

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

Loading…
Cancel
Save