/
get_structs.go
75 lines (61 loc) · 1.62 KB
/
get_structs.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
package generator
import (
"go/token"
"go/types"
"golang.org/x/tools/go/packages"
"github.com/sirkon/errors"
)
type structDescription struct {
pkg string
name string
}
func (d structDescription) String() string {
return d.pkg + ":" + d.name
}
// getOrigStructs получение конвертируемых типов
func (g *Generator) getOrigStructs(descrs ...structDescription) (map[string]*types.Named, error) {
if g.fs == nil {
g.fs = token.NewFileSet()
}
var packageNames []string
for _, pkg := range descrs {
packageNames = append(packageNames, pkg.pkg)
}
pkgs, err := packages.Load(
&packages.Config{
Mode: packages.NeedImports | packages.NeedTypes | packages.NeedName | packages.NeedDeps |
packages.NeedSyntax | packages.NeedFiles | packages.NeedModule,
Fset: g.fs,
Tests: false,
},
packageNames...,
)
if err != nil {
return nil, errors.Wrap(err, "parse package")
}
res := map[string]*types.Named{}
for _, p := range pkgs {
for _, descr := range descrs {
if p.PkgPath != descr.pkg {
continue
}
t := p.Types.Scope().Lookup(descr.name)
if t == nil {
return nil, errors.Newf("type '%s' not found in '%s'", descr.name, descr.pkg)
}
v := t.Type().(*types.Named)
switch vv := v.Underlying().(type) {
case *types.Struct:
res[descr.String()] = v
default:
return nil, errors.Newf("can only process %T, but %s is %T", &types.Struct{}, descr.name, vv)
}
}
}
for _, descr := range descrs {
if _, ok := res[descr.String()]; !ok {
return nil, errors.Newf("package '%s' not found, please run 'go mod tidy'", descr.name)
}
}
return res, nil
}