-
Notifications
You must be signed in to change notification settings - Fork 5
/
method-snippet.go
96 lines (86 loc) · 1.88 KB
/
method-snippet.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
package snippets
import (
"go/ast"
"margo.sh/golang/cursor"
"margo.sh/mg"
"unicode"
)
func receiverName(typeName string) string {
name := make([]rune, 0, 4)
for _, r := range typeName {
if len(name) == 0 || unicode.IsUpper(r) {
name = append(name, unicode.ToLower(r))
}
}
return string(name)
}
func MethodSnippet(cx *cursor.CurCtx) []mg.Completion {
if cx.Scope != cursor.FileScope && !cx.Scope.Is(cursor.FuncDeclScope) {
return nil
}
type field struct {
nm string
typ string
}
fields := map[string]field{}
types := []string{}
for _, x := range cx.AstFile.Decls {
switch x := x.(type) {
case *ast.FuncDecl:
if x.Recv == nil || len(x.Recv.List) == 0 {
continue
}
r := x.Recv.List[0]
if len(r.Names) == 0 {
continue
}
name := ""
if id := r.Names[0]; id != nil {
name = id.String()
}
switch x := r.Type.(type) {
case *ast.Ident:
typ := x.String()
fields[typ] = field{nm: name, typ: typ}
case *ast.StarExpr:
if id, ok := x.X.(*ast.Ident); ok {
typ := id.String()
fields[typ] = field{nm: name, typ: "*" + typ}
}
}
case *ast.GenDecl:
for _, spec := range x.Specs {
spec, ok := spec.(*ast.TypeSpec)
if ok && spec.Name != nil && spec.Name.Name != "_" {
types = append(types, spec.Name.Name)
}
}
}
}
cl := make([]mg.Completion, 0, len(types))
for _, typ := range types {
if f, ok := fields[typ]; ok {
cl = append(cl, mg.Completion{
Query: `func method ` + f.typ,
Title: `(` + f.typ + `) method() {...}`,
Src: `
func (` + f.nm + ` ` + f.typ + `) ${1:name}($2)$3 {
$0
}
`,
})
} else {
nm := receiverName(typ)
cl = append(cl, mg.Completion{
Query: `func method ` + typ,
Title: `(` + typ + `) method() {...}`,
Src: `
func (${1:` + nm + `} ${2:*}` + typ + `) ${3:name}($4)$5 {
$0
}
`,
})
}
}
return cl
}