Clean up qualified names between implementations.
Implementations are relying more on each others' interfaces, which allows for better code isolation and a better chance at pruning down binaries when needed. Still plenty of TODO items left to tackle.
このコミットが含まれているのは:
コミット
aeda61d2f1
|
@ -202,6 +202,12 @@ func (m Method) Call(on string, params ...jen.Code) jen.Code {
|
||||||
return jen.Id(on).Dot(m.function.name).Call(params...)
|
return jen.Id(on).Dot(m.function.name).Call(params...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On generates the Go code that determines the qualified method name on a
|
||||||
|
// specific variable.
|
||||||
|
func (m Method) On(on string) *jen.Statement {
|
||||||
|
return jen.Id(on).Dot(m.function.name)
|
||||||
|
}
|
||||||
|
|
||||||
// Name returns the identifier of this function.
|
// Name returns the identifier of this function.
|
||||||
func (m Method) Name() string {
|
func (m Method) Name() string {
|
||||||
return m.function.name
|
return m.function.name
|
||||||
|
|
|
@ -282,6 +282,9 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, *co
|
||||||
jen.Id(codegen.This()).Dot(p.isMethodName(i)).Call(),
|
jen.Id(codegen.This()).Dot(p.isMethodName(i)).Call(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if kind.SerializeFn != nil {
|
||||||
|
// This is a value that has a function that must be
|
||||||
|
// called to serialize properly.
|
||||||
serializeFns = serializeFns.Block(
|
serializeFns = serializeFns.Block(
|
||||||
jen.Return(
|
jen.Return(
|
||||||
kind.SerializeFn.Clone().Call(
|
kind.SerializeFn.Clone().Call(
|
||||||
|
@ -289,6 +292,14 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, *co
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
// This is a type with a Serialize method.
|
||||||
|
serializeFns = serializeFns.Block(
|
||||||
|
jen.Return(
|
||||||
|
jen.Id(codegen.This()).Dot(p.getFnName(i)).Call().Dot(serializeMethodName).Call(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serialize := codegen.NewCommentedValueMethod(
|
serialize := codegen.NewCommentedValueMethod(
|
||||||
p.Package.Path(),
|
p.Package.Path(),
|
||||||
|
|
|
@ -58,6 +58,7 @@ type ManagerGenerator struct {
|
||||||
// properties and types.
|
// properties and types.
|
||||||
type managedMethods struct {
|
type managedMethods struct {
|
||||||
deserializor *codegen.Method
|
deserializor *codegen.Method
|
||||||
|
// TODO: Delete these?
|
||||||
publicDeserializor *codegen.Method
|
publicDeserializor *codegen.Method
|
||||||
// Interface for a manager
|
// Interface for a manager
|
||||||
mIface *codegen.Interface
|
mIface *codegen.Interface
|
||||||
|
@ -203,6 +204,7 @@ func (m *ManagerGenerator) PrivateManager() *codegen.Struct {
|
||||||
func (m *ManagerGenerator) createPrivateDeserializationMethodForType(tg *TypeGenerator) *codegen.Method {
|
func (m *ManagerGenerator) createPrivateDeserializationMethodForType(tg *TypeGenerator) *codegen.Method {
|
||||||
dn := tg.deserializationFnName()
|
dn := tg.deserializationFnName()
|
||||||
pkg := m.pm.PrivatePackage()
|
pkg := m.pm.PrivatePackage()
|
||||||
|
// TODO: Better naming scheme from package name
|
||||||
name := fmt.Sprintf("%s%s%s", dn, tg.PrivatePackage().Name(), strings.Title(pkg.Name()))
|
name := fmt.Sprintf("%s%s%s", dn, tg.PrivatePackage().Name(), strings.Title(pkg.Name()))
|
||||||
return codegen.NewCommentedValueMethod(
|
return codegen.NewCommentedValueMethod(
|
||||||
pkg.Path(),
|
pkg.Path(),
|
||||||
|
@ -233,6 +235,7 @@ func (m *ManagerGenerator) createPrivateDeserializationMethodForType(tg *TypeGen
|
||||||
func (m *ManagerGenerator) createPrivateDeserializationMethodForFuncProperty(fp *FunctionalPropertyGenerator) *codegen.Method {
|
func (m *ManagerGenerator) createPrivateDeserializationMethodForFuncProperty(fp *FunctionalPropertyGenerator) *codegen.Method {
|
||||||
dn := fp.DeserializeFnName()
|
dn := fp.DeserializeFnName()
|
||||||
pkg := m.pm.PrivatePackage()
|
pkg := m.pm.PrivatePackage()
|
||||||
|
// TODO: Better naming scheme from package name
|
||||||
name := fmt.Sprintf("%s%s%s", dn, fp.Package.Name(), strings.Title(pkg.Name()))
|
name := fmt.Sprintf("%s%s%s", dn, fp.Package.Name(), strings.Title(pkg.Name()))
|
||||||
return codegen.NewCommentedValueMethod(
|
return codegen.NewCommentedValueMethod(
|
||||||
pkg.Path(),
|
pkg.Path(),
|
||||||
|
@ -263,6 +266,7 @@ func (m *ManagerGenerator) createPrivateDeserializationMethodForFuncProperty(fp
|
||||||
func (m *ManagerGenerator) createPrivateDeserializationMethodForNonFuncProperty(nfp *NonFunctionalPropertyGenerator) *codegen.Method {
|
func (m *ManagerGenerator) createPrivateDeserializationMethodForNonFuncProperty(nfp *NonFunctionalPropertyGenerator) *codegen.Method {
|
||||||
dn := nfp.DeserializeFnName()
|
dn := nfp.DeserializeFnName()
|
||||||
pkg := m.pm.PrivatePackage()
|
pkg := m.pm.PrivatePackage()
|
||||||
|
// TODO: Better naming scheme from package name
|
||||||
name := fmt.Sprintf("%s%s%s", dn, nfp.Package.Name(), strings.Title(pkg.Name()))
|
name := fmt.Sprintf("%s%s%s", dn, nfp.Package.Name(), strings.Title(pkg.Name()))
|
||||||
return codegen.NewCommentedValueMethod(
|
return codegen.NewCommentedValueMethod(
|
||||||
pkg.Path(),
|
pkg.Path(),
|
||||||
|
|
|
@ -156,15 +156,21 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
less.Else()
|
less.Else()
|
||||||
}
|
}
|
||||||
|
// LessFn is nil case -- call Less method directly on the LHS.
|
||||||
|
lessCall := jen.Id("lhs").Dot(lessMethod).Call(jen.Id("rhs"))
|
||||||
|
if kind.LessFn != nil {
|
||||||
|
// LessFn is indeed a function -- call this function
|
||||||
|
lessCall = kind.LessFn.Clone().Call(
|
||||||
|
jen.Id("lhs"),
|
||||||
|
jen.Id("rhs"),
|
||||||
|
)
|
||||||
|
}
|
||||||
less.If(
|
less.If(
|
||||||
jen.Id("idx1").Op("==").Lit(i),
|
jen.Id("idx1").Op("==").Lit(i),
|
||||||
).Block(
|
).Block(
|
||||||
jen.Id("lhs").Op(":=").Id(codegen.This()).Index(jen.Id("i")).Dot(p.getFnName(i)).Call(),
|
jen.Id("lhs").Op(":=").Id(codegen.This()).Index(jen.Id("i")).Dot(p.getFnName(i)).Call(),
|
||||||
jen.Id("rhs").Op(":=").Id(codegen.This()).Index(jen.Id("j")).Dot(p.getFnName(i)).Call(),
|
jen.Id("rhs").Op(":=").Id(codegen.This()).Index(jen.Id("j")).Dot(p.getFnName(i)).Call(),
|
||||||
jen.Return(kind.LessFn.Clone().Call(
|
jen.Return(lessCall),
|
||||||
jen.Id("lhs"),
|
|
||||||
jen.Id("rhs"),
|
|
||||||
)),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// Remove Method
|
// Remove Method
|
||||||
|
|
|
@ -62,12 +62,14 @@ type Identifier struct {
|
||||||
// Only represents values and other types.
|
// Only represents values and other types.
|
||||||
type Kind struct {
|
type Kind struct {
|
||||||
Name Identifier
|
Name Identifier
|
||||||
// ConcreteKind is expected to be a jen.Qual
|
// ConcreteKind is expected to be properly qualified.
|
||||||
ConcreteKind *jen.Statement
|
ConcreteKind *jen.Statement
|
||||||
Nilable bool
|
Nilable bool
|
||||||
// These functions are expected to be a jen.Qual
|
// Expected to always be non-nil: a function is needed to deserialize.
|
||||||
SerializeFn *jen.Statement
|
|
||||||
DeserializeFn *jen.Statement
|
DeserializeFn *jen.Statement
|
||||||
|
// If any of these are nil at generation time, assume to call the method
|
||||||
|
// on the object directly (instead of a qualified function).
|
||||||
|
SerializeFn *jen.Statement
|
||||||
LessFn *jen.Statement
|
LessFn *jen.Statement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,16 +102,14 @@ func (p *PropertyGenerator) GetPackage() Package {
|
||||||
// The name parameter must match the LowerName of an Identifier.
|
// The name parameter must match the LowerName of an Identifier.
|
||||||
//
|
//
|
||||||
// This feels very hacky.
|
// This feels very hacky.
|
||||||
func (p *PropertyGenerator) SetKindFns(name string, qualKind, ser, deser, less *jen.Statement) error {
|
func (p *PropertyGenerator) SetKindFns(name string, qualKind, deser *jen.Statement) error {
|
||||||
for i, kind := range p.Kinds {
|
for i, kind := range p.Kinds {
|
||||||
if kind.Name.LowerName == name {
|
if kind.Name.LowerName == name {
|
||||||
if kind.SerializeFn != nil || kind.DeserializeFn != nil || kind.LessFn != nil {
|
if kind.SerializeFn != nil || kind.DeserializeFn != nil || kind.LessFn != nil {
|
||||||
return fmt.Errorf("property kind already has serialization functions set for %q", name)
|
return fmt.Errorf("property kind already has serialization functions set for %q", name)
|
||||||
}
|
}
|
||||||
kind.ConcreteKind = qualKind
|
kind.ConcreteKind = qualKind
|
||||||
kind.SerializeFn = ser
|
|
||||||
kind.DeserializeFn = deser
|
kind.DeserializeFn = deser
|
||||||
kind.LessFn = less
|
|
||||||
p.Kinds[i] = kind
|
p.Kinds[i] = kind
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Prevent circular dependency by somehow abstracting the requisite
|
|
||||||
// functions between props and types.
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeInterfaceName = "Type"
|
typeInterfaceName = "Type"
|
||||||
extendedByMethod = "IsExtendedBy"
|
extendedByMethod = "IsExtendedBy"
|
||||||
|
@ -21,7 +18,7 @@ const (
|
||||||
typeNameMethod = "Name"
|
typeNameMethod = "Name"
|
||||||
serializeMethodName = "Serialize"
|
serializeMethodName = "Serialize"
|
||||||
deserializeFnName = "Deserialize"
|
deserializeFnName = "Deserialize"
|
||||||
lessFnName = "Less"
|
typeLessMethod = "LessThan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TypeInterface returns the Type Interface that is needed for ActivityStream
|
// TypeInterface returns the Type Interface that is needed for ActivityStream
|
||||||
|
@ -45,7 +42,7 @@ type Property interface {
|
||||||
GetPackage() Package
|
GetPackage() Package
|
||||||
PropertyName() string
|
PropertyName() string
|
||||||
StructName() string
|
StructName() string
|
||||||
SetKindFns(name string, kind, ser, deser, less *jen.Statement) error
|
SetKindFns(name string, kind, deser *jen.Statement) error
|
||||||
DeserializeFnName() string
|
DeserializeFnName() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,13 +125,12 @@ func NewTypeGenerator(pm *PackageManager, typeName, comment string,
|
||||||
func (t *TypeGenerator) apply(m *ManagerGenerator) error {
|
func (t *TypeGenerator) apply(m *ManagerGenerator) error {
|
||||||
t.m = m
|
t.m = m
|
||||||
// Set up Kind functions
|
// Set up Kind functions
|
||||||
// TODO: Call serialize on an object instead of using a function.
|
// Note: this "i" must be the same as the "i" in the deserialization definition.
|
||||||
ser := jen.Qual(t.PrivatePackage().Path(), t.serializationFnName())
|
// TODO: Remove this kluge.
|
||||||
deser := jen.Qual(m.privatePackage().Path(), m.getPrivateDeserializationMethodForType(t).Name())
|
deser := m.getPrivateDeserializationMethodForType(t).On(managerInitName())
|
||||||
less := jen.Qual(t.PrivatePackage().Path(), t.lessFnName())
|
|
||||||
kind := jen.Qual(t.PublicPackage().Path(), t.InterfaceName())
|
kind := jen.Qual(t.PublicPackage().Path(), t.InterfaceName())
|
||||||
for _, p := range t.rangeProperties {
|
for _, p := range t.rangeProperties {
|
||||||
if e := p.SetKindFns(t.TypeName(), kind, ser, deser, less); e != nil {
|
if e := p.SetKindFns(t.TypeName(), kind, deser); e != nil {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,17 +216,6 @@ func (t *TypeGenerator) deserializationFnName() string {
|
||||||
return fmt.Sprintf("%s%s", deserializeFnName, t.TypeName())
|
return fmt.Sprintf("%s%s", deserializeFnName, t.TypeName())
|
||||||
}
|
}
|
||||||
|
|
||||||
// serializationFnName determines the name of the serialize function for this
|
|
||||||
// type.
|
|
||||||
func (t *TypeGenerator) serializationFnName() string {
|
|
||||||
return fmt.Sprintf("%s%s", serializeMethodName, t.TypeName())
|
|
||||||
}
|
|
||||||
|
|
||||||
// lessFnName determines the name of the less function for this type.
|
|
||||||
func (t *TypeGenerator) lessFnName() string {
|
|
||||||
return fmt.Sprintf("%s%s", lessFnName, t.TypeName())
|
|
||||||
}
|
|
||||||
|
|
||||||
// toInterface creates the interface version of the definition generated.
|
// toInterface creates the interface version of the definition generated.
|
||||||
//
|
//
|
||||||
// Requires apply to have already been called.
|
// Requires apply to have already been called.
|
||||||
|
@ -254,8 +239,9 @@ func (t *TypeGenerator) InterfaceDefinition(pkg Package) *codegen.Interface {
|
||||||
func (t *TypeGenerator) Definition() *codegen.Struct {
|
func (t *TypeGenerator) Definition() *codegen.Struct {
|
||||||
t.cacheOnce.Do(func() {
|
t.cacheOnce.Do(func() {
|
||||||
members := t.members()
|
members := t.members()
|
||||||
m := t.serializationMethod()
|
ser := t.serializationMethod()
|
||||||
ser, deser, less := t.kindSerializationFuncs()
|
less := t.lessMethod()
|
||||||
|
deser := t.kindDeserializationFunc()
|
||||||
extendsFn, extendsMethod := t.extendsDefinition()
|
extendsFn, extendsMethod := t.extendsDefinition()
|
||||||
t.cachedStruct = codegen.NewStruct(
|
t.cachedStruct = codegen.NewStruct(
|
||||||
jen.Commentf(t.Comments()),
|
jen.Commentf(t.Comments()),
|
||||||
|
@ -263,15 +249,14 @@ func (t *TypeGenerator) Definition() *codegen.Struct {
|
||||||
[]*codegen.Method{
|
[]*codegen.Method{
|
||||||
t.nameDefinition(),
|
t.nameDefinition(),
|
||||||
extendsMethod,
|
extendsMethod,
|
||||||
m,
|
ser,
|
||||||
|
less,
|
||||||
},
|
},
|
||||||
[]*codegen.Function{
|
[]*codegen.Function{
|
||||||
t.extendedByDefinition(),
|
t.extendedByDefinition(),
|
||||||
extendsFn,
|
extendsFn,
|
||||||
t.disjointWithDefinition(),
|
t.disjointWithDefinition(),
|
||||||
ser,
|
|
||||||
deser,
|
deser,
|
||||||
less,
|
|
||||||
},
|
},
|
||||||
members)
|
members)
|
||||||
})
|
})
|
||||||
|
@ -322,6 +307,7 @@ func (t *TypeGenerator) members() (members []jen.Code) {
|
||||||
// Convert to jen.Code
|
// Convert to jen.Code
|
||||||
members = make([]jen.Code, 0, len(p))
|
members = make([]jen.Code, 0, len(p))
|
||||||
for _, property := range sortedMembers {
|
for _, property := range sortedMembers {
|
||||||
|
// TODO: Use interface instead
|
||||||
members = append(members, jen.Id(strings.Title(property.PropertyName())).Qual(property.GetPackage().Path(), property.StructName()))
|
members = append(members, jen.Id(strings.Title(property.PropertyName())).Qual(property.GetPackage().Path(), property.StructName()))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -508,20 +494,27 @@ func (t *TypeGenerator) serializationMethod() (ser *codegen.Method) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// kindSerializationFuncs returns free function references that can be used to
|
// lessMethod returns the method needed to compare a type with another type.
|
||||||
// treat a TypeGenerator as another property's Kind.
|
func (t *TypeGenerator) lessMethod() (less *codegen.Method) {
|
||||||
func (t *TypeGenerator) kindSerializationFuncs() (ser, deser, less *codegen.Function) {
|
less = codegen.NewCommentedValueMethod(
|
||||||
ser = codegen.NewCommentedFunction(
|
|
||||||
t.PrivatePackage().Path(),
|
t.PrivatePackage().Path(),
|
||||||
t.serializationFnName(),
|
typeLessMethod,
|
||||||
[]jen.Code{jen.Id("s").Id(t.TypeName())},
|
t.TypeName(),
|
||||||
[]jen.Code{jen.Interface(), jen.Error()},
|
|
||||||
[]jen.Code{
|
[]jen.Code{
|
||||||
jen.Return(
|
jen.Id("o").Op("*").Id(t.TypeName()),
|
||||||
jen.Id("s").Dot(serializeMethodName).Call(),
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
jen.Commentf("%s calls %s on the %s type.", t.serializationFnName(), serializeMethodName, t.TypeName()))
|
[]jen.Code{jen.Bool()},
|
||||||
|
[]jen.Code{
|
||||||
|
// TODO
|
||||||
|
jen.Commentf("TODO: Less code for %s", t.TypeName()),
|
||||||
|
},
|
||||||
|
jen.Commentf("%s computes if this %s is lesser, with an arbitrary but stable determination", typeLessMethod, t.TypeName()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// kindDeserializationFunc returns free function reference that can be used to
|
||||||
|
// treat a TypeGenerator as another property's Kind.
|
||||||
|
func (t *TypeGenerator) kindDeserializationFunc() (deser *codegen.Function) {
|
||||||
deserCode := jen.Empty()
|
deserCode := jen.Empty()
|
||||||
for name, prop := range t.allProperties() {
|
for name, prop := range t.allProperties() {
|
||||||
deserMethod := t.m.getPrivateDeserializationMethodForProperty(prop)
|
deserMethod := t.m.getPrivateDeserializationMethodForProperty(prop)
|
||||||
|
@ -550,18 +543,5 @@ func (t *TypeGenerator) kindSerializationFuncs() (ser, deser, less *codegen.Func
|
||||||
jen.Return(jen.Id(codegen.This()), jen.Nil()),
|
jen.Return(jen.Id(codegen.This()), jen.Nil()),
|
||||||
},
|
},
|
||||||
jen.Commentf("%s creates a %s from a map representation that has been unmarshalled from a text or binary format.", t.deserializationFnName(), t.TypeName()))
|
jen.Commentf("%s creates a %s from a map representation that has been unmarshalled from a text or binary format.", t.deserializationFnName(), t.TypeName()))
|
||||||
less = codegen.NewCommentedFunction(
|
|
||||||
t.PrivatePackage().Path(),
|
|
||||||
t.lessFnName(),
|
|
||||||
[]jen.Code{
|
|
||||||
jen.Id("i"),
|
|
||||||
jen.Id("j").Op("*").Id(t.TypeName()),
|
|
||||||
},
|
|
||||||
[]jen.Code{jen.Bool()},
|
|
||||||
[]jen.Code{
|
|
||||||
// TODO
|
|
||||||
jen.Commentf("TODO: Less code for %s", t.TypeName()),
|
|
||||||
},
|
|
||||||
jen.Commentf("%s computes which %s is lesser, with an arbitrary but stable determination", t.lessFnName(), t.TypeName()))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
読み込み中…
新しいイシューから参照