-
Notifications
You must be signed in to change notification settings - Fork 1
/
parse.go
106 lines (92 loc) · 2.76 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
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
package parse
import (
"fmt"
"go/ast"
"path/filepath"
"github.com/emilien-puget/go-dependency-graph/pkg/parse/package_list"
"github.com/emilien-puget/go-dependency-graph/pkg/parse/struct_decl"
"golang.org/x/tools/go/packages"
)
// AstSchema is a simpler presentation of the ast of a project.
type AstSchema struct {
ModulePath string
Graph *Graph
}
// Parse parses the project located under pathDir and returns an AstSchema.
func Parse(pathDir string, skipDirs []string) (AstSchema, error) {
pathDir, err := filepath.Abs(pathDir)
if err != nil {
return AstSchema{}, fmt.Errorf("filepath.Abs:%w", err)
}
modulePath, err := getModulePath(pathDir)
if err != nil {
return AstSchema{}, fmt.Errorf("getModulePath:%w", err)
}
as := AstSchema{
ModulePath: modulePath,
Graph: NewGraph(),
}
pkgs, err := package_list.GetPackagesToParse(pathDir, skipDirs)
if err != nil {
return AstSchema{}, fmt.Errorf("package_list.GetPackagesToParse:%w", err)
}
types := struct_decl.Extract(pkgs)
if err != nil {
return AstSchema{}, fmt.Errorf("struct_decl.Extract:%w", err)
}
parsePackages(pkgs, &as, types)
return as, nil
}
func parsePackages(pkgs []*packages.Package, schema *AstSchema, types map[string]map[string]*struct_decl.Decl) {
for i := range pkgs {
parsePackage(pkgs[i], schema, types)
}
}
func parsePackage(p *packages.Package, schema *AstSchema, types map[string]map[string]*struct_decl.Decl) {
for _, f := range p.Syntax {
parseFile(f, p, schema.ModulePath, types, schema.Graph)
}
}
func parseFile(f *ast.File, p *packages.Package, modulePath string, types map[string]map[string]*struct_decl.Decl, graph *Graph) {
packageName := p.ID
structDoc := struct_decl.GetStructDoc(f, packageName)
imports := parseImports(f, modulePath, p.Imports)
for _, decl := range f.Decls {
d, ok := decl.(*ast.FuncDecl)
if !ok {
continue
}
name, deps, sDecl := searchProvider(d, packageName, imports, p.TypesInfo, types)
if name == "" {
continue
}
newNode := &Node{
Name: packageName + "." + name,
PackageName: packageName,
StructName: name,
Methods: sDecl.Methods,
ActualNamedType: sDecl.ActualNamedType,
P: p,
FilePath: sDecl.FilePath,
}
if len(structDoc[packageName+"."+name]) > 3 {
newNode.Doc = structDoc[packageName+"."+name][3:]
}
graph.AddNode(newNode)
for s := range deps {
for i2 := range deps[s] {
adjNode := &Node{
Name: deps[s][i2].PackageName + "." + deps[s][i2].DependencyName,
PackageName: deps[s][i2].PackageName,
StructName: deps[s][i2].DependencyName,
External: deps[s][i2].External,
}
graph.AddNode(adjNode)
graph.AddEdge(newNode, &Adj{
Node: adjNode,
Func: deps[s][i2].Funcs,
})
}
}
}
}