forked from harness/gitness
/
find.go
104 lines (95 loc) · 2.41 KB
/
find.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
package main
import (
"fmt"
"go/ast"
"go/build"
"go/parser"
"go/token"
"os"
"path/filepath"
"strings"
)
func findBoxes(pkg *build.Package) map[string]bool {
// create one list of files for this package
filenames := make([]string, 0, len(pkg.GoFiles)+len(pkg.CgoFiles))
filenames = append(filenames, pkg.GoFiles...)
filenames = append(filenames, pkg.CgoFiles...)
// create map of boxes to embed
var boxMap = make(map[string]bool)
// loop over files, search for rice.FindBox(..) calls
for _, filename := range filenames {
// find full filepath
fullpath := filepath.Join(pkg.Dir, filename)
if strings.HasSuffix(filename, "rice-box.go") {
// Ignore *.rice-box.go files
verbosef("skipping file %q\n", fullpath)
continue
}
verbosef("scanning file %q\n", fullpath)
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, fullpath, nil, 0)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
var riceIsImported bool
ricePkgName := "rice"
for _, imp := range f.Imports {
if strings.HasSuffix(imp.Path.Value, "go.rice\"") {
if imp.Name != nil {
ricePkgName = imp.Name.Name
}
riceIsImported = true
break
}
}
if !riceIsImported {
// Rice wasn't imported, so we won't find a box.
continue
}
if ricePkgName == "_" {
// Rice pkg is unnamed, so we won't find a box.
continue
}
// Inspect AST, looking for calls to (Must)?FindBox.
// First parameter of the func must be a basic literal.
// Identifiers won't be resolved.
var nextIdentIsBoxFunc bool
var nextBasicLitParamIsBoxName bool
ast.Inspect(f, func(node ast.Node) bool {
if node == nil {
return false
}
switch x := node.(type) {
case *ast.Ident:
if nextIdentIsBoxFunc || ricePkgName == "." {
nextIdentIsBoxFunc = false
if x.Name == "FindBox" || x.Name == "MustFindBox" {
nextBasicLitParamIsBoxName = true
}
} else {
if x.Name == ricePkgName {
nextIdentIsBoxFunc = true
}
}
case *ast.BasicLit:
if nextBasicLitParamIsBoxName && x.Kind == token.STRING {
nextBasicLitParamIsBoxName = false
// trim "" or ``
name := x.Value[1 : len(x.Value)-1]
boxMap[name] = true
verbosef("\tfound box %q\n", name)
}
default:
if nextIdentIsBoxFunc {
nextIdentIsBoxFunc = false
}
if nextBasicLitParamIsBoxName {
nextBasicLitParamIsBoxName = false
}
}
return true
})
}
return boxMap
}