-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfindunexp.go
111 lines (102 loc) · 2.32 KB
/
findunexp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package main
import (
"flag"
"fmt"
"go/ast"
"go/build"
"go/parser"
"go/printer"
"go/token"
"log"
"os"
"path/filepath"
"regexp"
"golang.org/x/tools/go/buildutil"
)
var importRegexp *regexp.Regexp
type StructTypeVisitor struct {
structTypes []*ast.StructType
}
func (v *StructTypeVisitor) Visit(n ast.Node) (w ast.Visitor) {
structType, ok := n.(*ast.StructType)
if !ok {
return v
}
for _, field := range structType.Fields.List {
if field.Names != nil {
continue
}
starExpr, isPtr := field.Type.(*ast.StarExpr)
if !isPtr {
continue
}
ident, isIdent := starExpr.X.(*ast.Ident)
if !isIdent {
continue
}
if ast.IsExported(ident.Name) {
continue
}
v.structTypes = append(v.structTypes, structType)
}
return v
}
func searchStructs(astFile *ast.File) []*ast.StructType {
var visitor StructTypeVisitor
ast.Walk(&visitor, astFile)
return visitor.structTypes
}
func processPackage(importPath string, err error) {
if !importRegexp.MatchString(importPath) {
return
}
if err != nil {
if _, noGoErr := err.(*build.NoGoError); !noGoErr {
fmt.Println(err)
}
return
}
pkg, err := build.Import(importPath, "", 0)
if err != nil {
if _, noGoErr := err.(*build.NoGoError); !noGoErr {
fmt.Println(err)
}
return
}
fset := token.NewFileSet()
var visitor StructTypeVisitor
var pkgFiles []string
pkgFiles = append(pkgFiles, pkg.GoFiles...)
pkgFiles = append(pkgFiles, pkg.TestGoFiles...)
pkgFiles = append(pkgFiles, pkg.XTestGoFiles...)
pkgFiles = append(pkgFiles, pkg.CgoFiles...)
if len(pkgFiles) > 0 {
filename := pkgFiles[0]
path := filepath.Join(pkg.Dir, filename)
astFile, err := parser.ParseFile(fset, path, nil, 0)
if err != nil {
fmt.Println(err)
fmt.Println("aborting package")
return
}
ast.Walk(&visitor, astFile)
for _, structType := range visitor.structTypes {
fmt.Printf("\n%v:\n", fset.PositionFor(structType.Pos(), false))
err := printer.Fprint(os.Stdout, fset, structType)
if err != nil {
fmt.Println(err)
}
fmt.Println()
}
}
}
func main() {
importPattern := flag.String("importPattern", ".*", "only check packages with import path matching regex pattern")
flag.Parse()
var err error
importRegexp, err = regexp.Compile(*importPattern)
if err != nil {
log.Fatal(err)
}
buildutil.ForEachPackage(&build.Default, processPackage)
}