Reorganize code into individual tool files
This commit is contained in:
98
tool_find_imports.go
Normal file
98
tool_find_imports.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Import analysis types
|
||||
type ImportInfo struct {
|
||||
Package string `json:"package"`
|
||||
File string `json:"file"`
|
||||
Imports []ImportDetail `json:"imports"`
|
||||
UnusedImports []string `json:"unused_imports,omitempty"`
|
||||
}
|
||||
|
||||
type ImportDetail struct {
|
||||
Path string `json:"path"`
|
||||
Alias string `json:"alias,omitempty"`
|
||||
Used []string `json:"used_symbols,omitempty"`
|
||||
Position Position `json:"position"`
|
||||
}
|
||||
|
||||
func findImports(dir string) ([]ImportInfo, error) {
|
||||
var imports []ImportInfo
|
||||
|
||||
err := walkGoFiles(dir, func(path string, src []byte, file *ast.File, fset *token.FileSet) error {
|
||||
info := ImportInfo{
|
||||
Package: file.Name.Name,
|
||||
File: path,
|
||||
Imports: []ImportDetail{},
|
||||
}
|
||||
|
||||
// Collect all imports
|
||||
importMap := make(map[string]*ImportDetail)
|
||||
for _, imp := range file.Imports {
|
||||
importPath := strings.Trim(imp.Path.Value, `"`)
|
||||
pos := fset.Position(imp.Pos())
|
||||
detail := &ImportDetail{
|
||||
Path: importPath,
|
||||
Position: newPosition(pos),
|
||||
}
|
||||
if imp.Name != nil {
|
||||
detail.Alias = imp.Name.Name
|
||||
}
|
||||
importMap[importPath] = detail
|
||||
info.Imports = append(info.Imports, *detail)
|
||||
}
|
||||
|
||||
// Track which imports are used
|
||||
usedImports := make(map[string]map[string]bool)
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
switch x := n.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
if ident, ok := x.X.(*ast.Ident); ok {
|
||||
pkgName := ident.Name
|
||||
symbol := x.Sel.Name
|
||||
|
||||
// Find matching import
|
||||
for importPath, detail := range importMap {
|
||||
importName := filepath.Base(importPath)
|
||||
if detail.Alias != "" && detail.Alias == pkgName {
|
||||
if usedImports[importPath] == nil {
|
||||
usedImports[importPath] = make(map[string]bool)
|
||||
}
|
||||
usedImports[importPath][symbol] = true
|
||||
} else if importName == pkgName {
|
||||
if usedImports[importPath] == nil {
|
||||
usedImports[importPath] = make(map[string]bool)
|
||||
}
|
||||
usedImports[importPath][symbol] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// Update import details with used symbols
|
||||
for i, imp := range info.Imports {
|
||||
if used, ok := usedImports[imp.Path]; ok {
|
||||
for symbol := range used {
|
||||
info.Imports[i].Used = append(info.Imports[i].Used, symbol)
|
||||
}
|
||||
} else if !strings.HasSuffix(imp.Path, "_test") && imp.Alias != "_" {
|
||||
info.UnusedImports = append(info.UnusedImports, imp.Path)
|
||||
}
|
||||
}
|
||||
|
||||
if len(info.Imports) > 0 {
|
||||
imports = append(imports, info)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return imports, err
|
||||
}
|
||||
Reference in New Issue
Block a user