/
service.go
81 lines (66 loc) · 1.82 KB
/
service.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
package main
import (
"go/ast"
"go/token"
"go/types"
"github.com/pkg/errors"
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/go/packages"
)
type builder struct {
pkg *packages.Package
muxType *types.Interface
}
func (b builder) astFindFile(pos token.Pos) (*ast.File, error) {
return astFindFile(b.pkg, pos)
}
func (b builder) Service(ms *types.MethodSet, hs *types.Named, fset *token.FileSet) (*serviceDesc, error) {
hdlRegFuncRef := ms.Lookup(b.pkg.Types, "RegisterHTTP")
if hdlRegFuncRef == nil {
return nil, errors.New("RegisterHTTP func was not located")
}
hdlRegFunc := hdlRegFuncRef.Obj().(*types.Func)
hpp, err := b.getHandlerNames(hdlRegFunc)
if err != nil {
return nil, errors.Wrap(err, "cannot retrieve handler names")
}
tokfile := b.pkg.Fset.File(hs.Obj().Pos())
tokfile.Name()
f, err := b.astFindFile(hs.Obj().Pos())
if err != nil {
return nil, errors.Wrap(err, "cannot get file for service")
}
// extract comments for service
reg, _ := astutil.PathEnclosingInterval(f, hs.Obj().Pos()-1, hs.Obj().Pos())
doc := reg[0].(*ast.GenDecl).Doc
hd := []hdlDesc{}
for _, hp := range hpp {
fnDesc, err := b.getHandleDesc(hp.fn.Sel, ms)
if err != nil {
return nil, errors.Wrapf(err, "when parsing '%v' '%v' of '%v'", hp.op, hp.path, hs.String())
}
hd = append(hd, hdlDesc{
op: hp.op,
path: hp.path,
inout: *fnDesc,
description: fnDesc.description,
goFuncName: hp.fn.Sel.Name,
})
}
ret := serviceDesc{
name: hs.Obj().Pkg().Name() + "." + hs.Obj().Name(),
handlers: hd,
pkg: hs.Obj().Pkg().Path(),
filename: tokfile.Name(),
serviceStructName: hs.Obj().Name(),
}
if doc != nil {
ret.doc = doc.Text()
}
return &ret, nil
}
type hdlPathPtr struct {
op string
path string
fn *ast.SelectorExpr
}