forked from rjeczalik/interfaces
-
Notifications
You must be signed in to change notification settings - Fork 0
/
func.go
87 lines (79 loc) · 2.07 KB
/
func.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
package interfaces
import (
"bytes"
"fmt"
"sort"
"strings"
)
// Func represents an interface function.
type Func struct {
Name string `json:"name,omitempty"` // name of the function
Ins []Type `json:"ins,omitempty"` // input parameters
Outs []Type `json:"outs,omitempty"` // output parameters
IsVariadic bool // whether the function is variadic
}
var variadic = strings.NewReplacer("[]", "...")
// String gives Go code representation of the function.
func (f Func) String() string {
var buf bytes.Buffer
if len(f.Ins) == 0 {
fmt.Fprintf(&buf, "%s()", f.Name)
} else {
fmt.Fprintf(&buf, "%s(%s", f.Name, f.in(0))
for i := range f.Ins[1:] {
fmt.Fprintf(&buf, ", %s", f.in(i+1))
}
buf.WriteString(")")
}
if len(f.Outs) == 1 {
fmt.Fprintf(&buf, " %s", f.Outs[0])
} else if len(f.Outs) > 1 {
fmt.Fprintf(&buf, " (%s", f.Outs[0])
for _, typ := range f.Outs[1:] {
fmt.Fprintf(&buf, ", %s", typ)
}
buf.WriteString(")")
}
return buf.String()
}
func (f Func) in(i int) string {
if typ := f.Ins[i]; i == len(f.Ins)-1 && f.IsVariadic {
return variadic.Replace(typ.String())
} else {
return typ.String()
}
}
// Deps gives a list of packages the function depends on. E.g. if the function
// represents Serve(net.Listener, http.Handler) error, calling Deps() will
// return []string{"http", "net"}.
//
// The packages are sorted by name.
func (f Func) Deps() []string {
pkgs := make(map[string]struct{}, 0)
for _, in := range f.Ins {
pkgs[in.ImportPath] = struct{}{}
for _, dep := range in.Deps {
pkgs[dep] = struct{}{}
}
}
for _, out := range f.Outs {
pkgs[out.ImportPath] = struct{}{}
for _, dep := range out.Deps {
pkgs[dep] = struct{}{}
}
}
delete(pkgs, "")
if len(pkgs) == 0 {
return nil
}
deps := make([]string, 0, len(pkgs))
for pkg := range pkgs {
deps = append(deps, pkg)
}
sort.Strings(deps)
return deps
}
type funcs []Func
func (f funcs) Len() int { return len(f) }
func (f funcs) Less(i, j int) bool { return f[i].Name < f[j].Name }
func (f funcs) Swap(i, j int) { f[i], f[j] = f[j], f[i] }