2018-10-20 05:44:13 +09:00
|
|
|
package codegen
|
2018-10-09 05:19:10 +09:00
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/dave/jennifer/jen"
|
2019-01-08 05:22:01 +09:00
|
|
|
"sort"
|
2018-12-31 08:45:25 +09:00
|
|
|
"unicode"
|
2018-10-09 05:19:10 +09:00
|
|
|
)
|
|
|
|
|
2018-10-20 05:44:13 +09:00
|
|
|
// join appends a bunch of Go Code together, each on their own line.
|
|
|
|
func join(s []jen.Code) *jen.Statement {
|
|
|
|
r := jen.Empty()
|
|
|
|
for i, stmt := range s {
|
|
|
|
if i > 0 {
|
|
|
|
r.Line()
|
|
|
|
}
|
|
|
|
r.Add(stmt)
|
|
|
|
}
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
2018-10-10 07:32:37 +09:00
|
|
|
// Struct defines a struct-based type, its functions, and its methods for Go
|
|
|
|
// code generation.
|
2018-10-09 05:19:10 +09:00
|
|
|
type Struct struct {
|
2019-01-08 06:06:32 +09:00
|
|
|
comment string
|
2018-10-09 05:19:10 +09:00
|
|
|
name string
|
|
|
|
methods map[string]*Method
|
|
|
|
constructors map[string]*Function
|
|
|
|
members []jen.Code
|
|
|
|
}
|
|
|
|
|
2018-10-10 07:32:37 +09:00
|
|
|
// NewStruct creates a new commented Struct type.
|
2019-01-08 06:06:32 +09:00
|
|
|
func NewStruct(comment string,
|
2018-10-09 05:19:10 +09:00
|
|
|
name string,
|
|
|
|
methods []*Method,
|
|
|
|
constructors []*Function,
|
|
|
|
members []jen.Code) *Struct {
|
|
|
|
s := &Struct{
|
|
|
|
comment: comment,
|
|
|
|
name: name,
|
|
|
|
methods: make(map[string]*Method, len(methods)),
|
|
|
|
constructors: make(map[string]*Function, len(constructors)),
|
|
|
|
members: members,
|
|
|
|
}
|
|
|
|
for _, m := range methods {
|
|
|
|
s.methods[m.Name()] = m
|
|
|
|
}
|
|
|
|
for _, c := range constructors {
|
|
|
|
s.constructors[c.Name()] = c
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2018-10-10 07:32:37 +09:00
|
|
|
// Definition generates the Go code required to define and implement this
|
|
|
|
// struct, its methods, and its functions.
|
2018-10-09 05:19:10 +09:00
|
|
|
func (s *Struct) Definition() jen.Code {
|
|
|
|
comment := jen.Empty()
|
2019-01-08 06:06:32 +09:00
|
|
|
if len(s.comment) > 0 {
|
2019-01-08 06:39:30 +09:00
|
|
|
comment = jen.Commentf(insertNewlines(s.comment)).Line()
|
2018-10-09 05:19:10 +09:00
|
|
|
}
|
|
|
|
def := comment.Type().Id(s.name).Struct(
|
2018-10-10 07:32:37 +09:00
|
|
|
join(s.members),
|
2018-10-09 05:19:10 +09:00
|
|
|
)
|
2019-01-08 05:22:01 +09:00
|
|
|
// Sort the functions and methods.
|
|
|
|
fs := make([]string, 0, len(s.constructors))
|
2018-10-09 05:19:10 +09:00
|
|
|
for _, c := range s.constructors {
|
2019-01-08 05:22:01 +09:00
|
|
|
fs = append(fs, c.Name())
|
2018-10-09 05:19:10 +09:00
|
|
|
}
|
2019-01-08 05:22:01 +09:00
|
|
|
ms := make([]string, 0, len(s.methods))
|
2018-10-09 05:19:10 +09:00
|
|
|
for _, m := range s.methods {
|
2019-01-08 05:22:01 +09:00
|
|
|
ms = append(ms, m.Name())
|
|
|
|
}
|
|
|
|
sort.Sort(sort.StringSlice(fs))
|
|
|
|
sort.Sort(sort.StringSlice(ms))
|
|
|
|
// Add the functions and methods in order.
|
|
|
|
for _, c := range fs {
|
|
|
|
def = def.Line().Line().Add(s.constructors[c].Definition())
|
|
|
|
}
|
|
|
|
for _, m := range ms {
|
|
|
|
def = def.Line().Line().Add(s.methods[m].Definition())
|
2018-10-09 05:19:10 +09:00
|
|
|
}
|
|
|
|
return def
|
|
|
|
}
|
|
|
|
|
2018-10-10 07:32:37 +09:00
|
|
|
// Method obtains the Go code to be generated for the method with a specific
|
|
|
|
// name. Panics if no such method exists.
|
2018-10-09 05:19:10 +09:00
|
|
|
func (s *Struct) Method(name string) *Method {
|
|
|
|
return s.methods[name]
|
|
|
|
}
|
|
|
|
|
2018-10-10 07:32:37 +09:00
|
|
|
// Constructors obtains the Go code to be generated for the function with a
|
|
|
|
// specific name. Panics if no such function exists.
|
2018-10-09 05:19:10 +09:00
|
|
|
func (s *Struct) Constructors(name string) *Function {
|
|
|
|
return s.constructors[name]
|
|
|
|
}
|
2018-12-31 00:09:14 +09:00
|
|
|
|
|
|
|
// ToInterface creates an interface version of this struct.
|
|
|
|
func (s *Struct) ToInterface(pkg, name, comment string) *Interface {
|
|
|
|
fns := make([]FunctionSignature, 0, len(s.methods))
|
|
|
|
for _, m := range s.methods {
|
2018-12-31 08:45:25 +09:00
|
|
|
if unicode.IsUpper([]rune(m.Name())[0]) {
|
|
|
|
fns = append(fns, m.ToFunctionSignature())
|
|
|
|
}
|
2018-12-31 00:09:14 +09:00
|
|
|
}
|
|
|
|
return NewInterface(pkg, name, fns, comment)
|
|
|
|
}
|