2019-08-01 19:03:12 +03:00
|
|
|
package parser
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
|
2019-08-02 05:34:32 +03:00
|
|
|
"github.com/markbates/pkger"
|
2019-08-01 19:03:12 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
var DefaultIgnoredFolders = []string{".", "_", "vendor", "node_modules", "_fixtures", "testdata"}
|
|
|
|
|
|
|
|
func Parse(name string) (Results, error) {
|
|
|
|
var r Results
|
2019-08-02 05:34:32 +03:00
|
|
|
c, err := pkger.Current()
|
2019-08-02 00:56:37 +03:00
|
|
|
if err != nil {
|
|
|
|
return r, err
|
|
|
|
}
|
|
|
|
|
2019-08-01 19:03:12 +03:00
|
|
|
if name == "" || name == "." {
|
|
|
|
name = c.ImportPath
|
|
|
|
}
|
2019-08-02 00:56:37 +03:00
|
|
|
|
2019-08-02 05:34:32 +03:00
|
|
|
pt, err := pkger.Parse(name)
|
2019-08-01 19:03:12 +03:00
|
|
|
if err != nil {
|
|
|
|
return r, err
|
|
|
|
}
|
|
|
|
r.Path = pt
|
|
|
|
|
2019-08-02 06:21:37 +03:00
|
|
|
her, err := pkger.Info(r.Path.Pkg)
|
2019-08-01 19:03:12 +03:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return r, err
|
|
|
|
}
|
|
|
|
|
2019-08-02 05:34:32 +03:00
|
|
|
m := map[pkger.Path]bool{}
|
2019-08-02 00:56:37 +03:00
|
|
|
|
2019-08-01 21:37:01 +03:00
|
|
|
root := r.Path.Name
|
|
|
|
if !strings.HasPrefix(root, string(filepath.Separator)) {
|
|
|
|
root = string(filepath.Separator) + root
|
|
|
|
}
|
2019-08-02 00:56:37 +03:00
|
|
|
|
2019-08-01 21:37:01 +03:00
|
|
|
if !strings.HasPrefix(root, her.Dir) {
|
|
|
|
root = filepath.Join(her.Dir, root)
|
|
|
|
}
|
2019-08-02 00:56:37 +03:00
|
|
|
|
|
|
|
if name != her.Dir {
|
|
|
|
_, err = os.Stat(filepath.Join(root, "go.mod"))
|
|
|
|
if err == nil {
|
|
|
|
return Results{}, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 19:03:12 +03:00
|
|
|
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-08-02 00:56:37 +03:00
|
|
|
if info.IsDir() {
|
|
|
|
if path != c.Dir {
|
|
|
|
_, err = os.Stat(filepath.Join(path, "go.mod"))
|
|
|
|
if err == nil {
|
|
|
|
return filepath.SkipDir
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 19:03:12 +03:00
|
|
|
base := filepath.Base(path)
|
|
|
|
|
|
|
|
for _, ig := range DefaultIgnoredFolders {
|
|
|
|
if strings.HasPrefix(base, ig) {
|
|
|
|
if info.IsDir() {
|
|
|
|
return filepath.SkipDir
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if info.IsDir() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ext := filepath.Ext(path)
|
|
|
|
if ext != ".go" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-08-02 06:21:37 +03:00
|
|
|
v, err := newVisitor(path)
|
2019-08-01 19:03:12 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
found, err := v.Run()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, p := range found {
|
|
|
|
if _, ok := m[p]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
m[p] = true
|
|
|
|
found, err := sourceFiles(p)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for _, pf := range found {
|
|
|
|
pf.Pkg = p.Pkg
|
|
|
|
m[pf] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
2019-08-02 05:34:32 +03:00
|
|
|
var found []pkger.Path
|
2019-08-01 19:03:12 +03:00
|
|
|
|
|
|
|
for k := range m {
|
|
|
|
if len(k.String()) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
found = append(found, k)
|
|
|
|
}
|
|
|
|
sort.Slice(found, func(a, b int) bool {
|
|
|
|
return found[a].String() <= found[b].String()
|
|
|
|
})
|
|
|
|
r.Paths = found
|
|
|
|
|
|
|
|
return r, err
|
|
|
|
}
|
|
|
|
|
2019-08-02 05:34:32 +03:00
|
|
|
func sourceFiles(pt pkger.Path) ([]pkger.Path, error) {
|
|
|
|
var res []pkger.Path
|
2019-08-01 19:03:12 +03:00
|
|
|
|
2019-08-02 06:21:37 +03:00
|
|
|
her, err := pkger.Info(pt.Pkg)
|
2019-08-01 19:03:12 +03:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return res, err
|
|
|
|
}
|
2019-08-01 21:37:01 +03:00
|
|
|
|
|
|
|
fp := her.FilePath(pt.Name)
|
|
|
|
fi, err := os.Stat(fp)
|
|
|
|
if err != nil {
|
|
|
|
return res, err
|
|
|
|
}
|
|
|
|
if !fi.IsDir() {
|
|
|
|
return res, nil
|
|
|
|
}
|
2019-08-02 00:56:37 +03:00
|
|
|
|
2019-08-02 05:34:32 +03:00
|
|
|
c, err := pkger.Current()
|
2019-08-02 00:56:37 +03:00
|
|
|
if err != nil {
|
|
|
|
return res, err
|
|
|
|
}
|
|
|
|
|
2019-08-01 21:37:01 +03:00
|
|
|
err = filepath.Walk(fp, func(p string, info os.FileInfo, err error) error {
|
2019-08-01 19:03:12 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-08-02 00:56:37 +03:00
|
|
|
if info.IsDir() {
|
|
|
|
if p != c.Dir {
|
|
|
|
_, err = os.Stat(filepath.Join(p, "go.mod"))
|
|
|
|
if err == nil {
|
|
|
|
return filepath.SkipDir
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 19:03:12 +03:00
|
|
|
base := filepath.Base(p)
|
|
|
|
|
|
|
|
if base == "." {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, ig := range DefaultIgnoredFolders {
|
|
|
|
if strings.HasPrefix(base, ig) {
|
|
|
|
if info.IsDir() {
|
|
|
|
return filepath.SkipDir
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if info.IsDir() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
n := strings.TrimPrefix(strings.TrimPrefix(p, her.Dir), "/")
|
2019-08-02 05:34:32 +03:00
|
|
|
pt := pkger.Path{
|
2019-08-01 19:03:12 +03:00
|
|
|
Name: n,
|
|
|
|
}
|
|
|
|
res = append(res, pt)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return res, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
type Results struct {
|
2019-08-02 05:34:32 +03:00
|
|
|
Paths []pkger.Path
|
|
|
|
Path pkger.Path
|
2019-08-01 19:03:12 +03:00
|
|
|
}
|