-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathverb.go
119 lines (104 loc) · 3.26 KB
/
verb.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
package main
import "bytes"
import "fmt"
import "os"
import "reflect"
import "strings"
import "go/ast"
import "text/template"
// GlobalsTemplateParameter codifies the parameter of the
// (VerbDefinition).GlobalsTemplate.
//
// Each verb_*.go file asserts that the VerbPhrase it defines
// satisfies this interface.
type GlobalsTemplateParameter interface {
MethodName() string
InterfaceName() string
StructName() string
SlotName() string
MethodParameters() string
MethodResults() string
}
// VerbPhrase represents a single verb and its parameters from a Field
// in an interface definition.
type VerbPhrase interface {
// Verb returns the VerbDefinition that created this VerbPhrase.
Verb() VerbDefinition
// Tag returns the string that identifies a Verb in a tag
// comment.
Tag() string
// MethodName returns the function name of the method
// associated with this verb phrase.
MethodName() string
// InterfaceDefinition returns the InterfaceDefinition which
// represents the interface type declaration that this
// VerbPhrase's Field appears in.
InterfaceDefinition() *InterfaceDefinition
// Field returns the ast.Field whose tag comment the verb
// phrase is derived from.
Field() *ast.Field
// GlobalDefinitions returns the global code that should be
// included to support the VerbPhrase.
// GlobalDefinitions() (string, error)
// The following methods are a convenience for implementing
// GlobalsTemplate templates. Such templates are executed with
// either a VerbPhrase or a GlobalsTemplateParameter (see
// CheckSignatures).
// InterfaceName returns the InterfaceName from the InterfaceDefinition.
InterfaceName() string
// StructName returns the StructName from the InterfaceDefinition
StructName() string
}
// GetVerbPhrase is called on each field in an interface definition.
// If the Field has a defimpl comment then a VerbPhrase is added to
// the InterfaceDefinition.
func GetVerbPhrase(ctx *context, idef *InterfaceDefinition, method *ast.Field) {
if method.Comment == nil {
return
}
for _, c := range method.Comment.List {
val, ok := reflect.StructTag(c.Text[2:]).Lookup("defimpl")
if !ok {
continue
}
split := strings.Split(val, " ")
if len(split) < 1 {
continue
}
vd, ok := VerbDefinitions[split[0]]
if !ok {
fmt.Fprintf(os.Stderr, "defimpl: Unknown verb %q in defimpl comment %s: %q\n",
split[0], ctx.fset.Position(c.Slash), c.Text)
continue
}
vp, err := vd.NewVerbPhrase(ctx, idef, method, c)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
} else {
if vp != nil {
idef.VerbPhrases = append(idef.VerbPhrases, vp)
}
}
}
}
// GlobalDefinitions returns the global definitions to be generated by
// the VerbPhrase, including a method if any.
func GlobalDefinitions(vp VerbPhrase) (string, error) {
tmpl := vp.Verb().GlobalsTemplate()
if tmpl == nil {
return "", nil
}
w := &bytes.Buffer{}
if err := tmpl.Execute(w, vp); err != nil {
return "", err
}
return w.String(), nil
}
type VerbDefinition interface {
Tag() string
Description() string
NewVerbPhrase(*context, *InterfaceDefinition, *ast.Field, *ast.Comment) (VerbPhrase, error)
GlobalsTemplate() *template.Template
StructBody(VerbPhrase) (string, error)
}
var VerbDefinitions map[string]VerbDefinition = map[string]VerbDefinition{}