-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathparse.go
72 lines (60 loc) · 1.73 KB
/
parse.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
package main
import (
"errors"
"go/ast"
"go/doc"
"go/parser"
"go/token"
"os"
"path/filepath"
"strings"
)
// ErrEmpty sentinel indicating empty folder
var ErrEmpty = errors.New("empty folder")
func mustParse(fset *token.FileSet, filename string, src []byte) *ast.File {
f, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
if err != nil {
panic(err)
}
return f
}
// Parse walks the directory tree rooted at root and parses all .go files
// it returns a [Package] for each directory containing .go files
// or empty [Package] and [ErrEmpty]
func Parse(root, path string, recursive bool) (Package, error) {
entries, _ := os.ReadDir(filepath.Join(root, path))
fset := token.NewFileSet()
files := []*ast.File{}
pkgs := []Package{}
fnames := []string{}
for _, e := range entries {
// Hidden file or directory. The Go compiler behaves consistently across Windows and POSIX.
// It skips files and directories that begin with '.' but ignores hidden attribute on Windows.
if strings.HasPrefix(e.Name(), ".") {
continue
}
nextPath := filepath.Join(path, e.Name())
if e.IsDir() && recursive {
pkg, err := Parse(root, nextPath, recursive)
if err == nil {
pkgs = append(pkgs, pkg)
} // else ignore error
} else {
if !strings.HasSuffix(e.Name(), ".go") ||
strings.HasSuffix(e.Name(), "_test.go") {
continue
}
fnames = append(fnames, e.Name())
src, _ := os.ReadFile(filepath.Join(root, nextPath))
files = append(files, mustParse(fset, e.Name(), src))
}
}
p, err := doc.NewFromFiles(fset, files, "example.com")
if err != nil {
return Package{}, err
}
if len(fnames) == 0 && len(pkgs) == 0 {
return Package{}, ErrEmpty
}
return NewPackage(fset, p, path, pkgs, fnames)
}