-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresolver.go
133 lines (118 loc) · 3.6 KB
/
resolver.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"fmt"
"github.com/dave/jennifer/jen"
"go/ast"
"go/types"
"log"
"sync"
)
type pendingResolve struct {
pkg string
ident *ast.Ident
p *jen.Statement
o types.Object
}
type resolveMap struct {
index []string
resolve map[string]string
}
type mapResolveMap map[struct {
Pkg, Target string
}]resolveMap
type Resolver interface {
Resolve(ident *ast.Ident, pkg string, object types.Object) *jen.Statement
Overlap(pkg, target string, resolve []string) //maybe []ast.Expr //currently too rough
CompleteResolve(resolveMap resolveMap, allMaps mapResolveMap, group *sync.WaitGroup)
NewResolver() Resolver
Pop() Resolver
}
type genericResolver struct {
pkg, target string
overlap []string
pending []*pendingResolve
underlineResolver []Resolver
parent Resolver
}
func (r *genericResolver) Resolve(ident *ast.Ident, pkg string, object types.Object) *jen.Statement {
statement := jen.Id(ident.Name)
r.pending = append(r.pending, &pendingResolve{
ident: ident,
pkg: pkg,
o: object,
p: statement,
})
return statement
}
func (r *genericResolver) updateItems(resolveMap resolveMap, group *sync.WaitGroup) {
defer group.Done()
for _, statement := range r.pending {
resetStatement(statement.p)
if statement.ident.Obj == nil && ISScalarType(statement.ident.Name) { //it probably scalar // { //check Obj == nil is not enough
statement.p.Id(statement.ident.Name)
} else if resolved, ok := resolveMap.resolve[statement.ident.Name]; ok {
if statement.ident.Obj == nil && ISScalarType(resolved) {
statement.p.Id(resolved)
} else {
statement.p.Qual(statement.pkg, resolved)
}
} else if true { //local struct decl
statement.p.Qual(statement.pkg, statement.ident.Name)
} else { //for generics
log.Println("WARNING: skip *ast.SelectorExpr(recursBuildParam) unsupported format")
}
}
}
func (r *genericResolver) CompleteResolve(rslMap resolveMap, allMaps mapResolveMap, parentGroup *sync.WaitGroup) {
defer parentGroup.Done()
group := &sync.WaitGroup{}
group.Add(1 + len(r.underlineResolver))
merge := rslMap
if len(r.overlap) > 0 {
//merge direction base type + var decl + user input
merge = resolveMap{resolve: map[string]string{}, index: []string{}}
if original, ok := allMaps[struct{ Pkg, Target string }{Pkg: r.pkg, Target: r.target}]; ok {
if len(original.index) != len(r.overlap) {
critical(fmt.Sprintf("type and impl are missmathed %s, %s", r.pkg, r.target))
}
for i := range original.index {
if i < len(r.overlap) {
merge.resolve[original.index[i]] = r.overlap[i]
merge.index = append(merge.index, r.overlap[i])
} else {
merge.resolve[original.index[i]] = original.index[i]
merge.index = append(merge.index, original.index[i])
}
}
for i, org := range merge.resolve {
if override, ok := rslMap.resolve[org]; ok {
merge.resolve[i] = override
}
}
} else {
critical(fmt.Sprintf("unable to find original %s, %s declaration", r.pkg, r.target))
}
}
for i := range r.underlineResolver {
go r.underlineResolver[i].CompleteResolve(merge, allMaps, group)
}
go r.updateItems(merge, group)
group.Wait()
}
func (r *genericResolver) Pop() Resolver {
return r.parent
}
func (r *genericResolver) Overlap(pkg, target string, resolve []string) {
r.pkg, r.target = pkg, target
r.overlap = resolve
}
func (r *genericResolver) NewResolver() Resolver {
resolver := newResolver()
r.underlineResolver = append(r.underlineResolver, resolver)
resolver.parent = r
return resolver
}
func newResolver() *genericResolver {
resolver := &genericResolver{}
return resolver
}