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.
このコミットが含まれているのは:
Cory Slep 2018-12-31 18:42:39 +01:00
コミット aeda61d2f1
6個のファイルの変更75行の追加68行の削除

ファイルの表示

@ -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...)
}
// 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.
func (m Method) Name() string {
return m.function.name

ファイルの表示

@ -282,13 +282,24 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, *co
jen.Id(codegen.This()).Dot(p.isMethodName(i)).Call(),
)
}
serializeFns = serializeFns.Block(
jen.Return(
kind.SerializeFn.Clone().Call(
jen.Id(codegen.This()).Dot(p.getFnName(i)).Call(),
if kind.SerializeFn != nil {
// This is a value that has a function that must be
// called to serialize properly.
serializeFns = serializeFns.Block(
jen.Return(
kind.SerializeFn.Clone().Call(
jen.Id(codegen.This()).Dot(p.getFnName(i)).Call(),
),
),
),
)
)
} 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(
p.Package.Path(),

ファイルの表示

@ -57,7 +57,8 @@ type ManagerGenerator struct {
// managedMethods caches the specific methods and interfaces mapped to specific
// properties and types.
type managedMethods struct {
deserializor *codegen.Method
deserializor *codegen.Method
// TODO: Delete these?
publicDeserializor *codegen.Method
// Interface for a manager
mIface *codegen.Interface
@ -203,6 +204,7 @@ func (m *ManagerGenerator) PrivateManager() *codegen.Struct {
func (m *ManagerGenerator) createPrivateDeserializationMethodForType(tg *TypeGenerator) *codegen.Method {
dn := tg.deserializationFnName()
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()))
return codegen.NewCommentedValueMethod(
pkg.Path(),
@ -233,6 +235,7 @@ func (m *ManagerGenerator) createPrivateDeserializationMethodForType(tg *TypeGen
func (m *ManagerGenerator) createPrivateDeserializationMethodForFuncProperty(fp *FunctionalPropertyGenerator) *codegen.Method {
dn := fp.DeserializeFnName()
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()))
return codegen.NewCommentedValueMethod(
pkg.Path(),
@ -263,6 +266,7 @@ func (m *ManagerGenerator) createPrivateDeserializationMethodForFuncProperty(fp
func (m *ManagerGenerator) createPrivateDeserializationMethodForNonFuncProperty(nfp *NonFunctionalPropertyGenerator) *codegen.Method {
dn := nfp.DeserializeFnName()
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()))
return codegen.NewCommentedValueMethod(
pkg.Path(),

ファイルの表示

@ -156,15 +156,21 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
if i > 0 {
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(
jen.Id("idx1").Op("==").Lit(i),
).Block(
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.Return(kind.LessFn.Clone().Call(
jen.Id("lhs"),
jen.Id("rhs"),
)),
jen.Return(lessCall),
)
}
// Remove Method

ファイルの表示

@ -62,13 +62,15 @@ type Identifier struct {
// Only represents values and other types.
type Kind struct {
Name Identifier
// ConcreteKind is expected to be a jen.Qual
// ConcreteKind is expected to be properly qualified.
ConcreteKind *jen.Statement
Nilable bool
// These functions are expected to be a jen.Qual
SerializeFn *jen.Statement
// Expected to always be non-nil: a function is needed to deserialize.
DeserializeFn *jen.Statement
LessFn *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
}
// PropertyGenerator is a common base struct used in both Functional and
@ -100,16 +102,14 @@ func (p *PropertyGenerator) GetPackage() Package {
// The name parameter must match the LowerName of an Identifier.
//
// 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 {
if kind.Name.LowerName == name {
if kind.SerializeFn != nil || kind.DeserializeFn != nil || kind.LessFn != nil {
return fmt.Errorf("property kind already has serialization functions set for %q", name)
}
kind.ConcreteKind = qualKind
kind.SerializeFn = ser
kind.DeserializeFn = deser
kind.LessFn = less
p.Kinds[i] = kind
return nil
}

ファイルの表示

@ -9,9 +9,6 @@ import (
"sync"
)
// TODO: Prevent circular dependency by somehow abstracting the requisite
// functions between props and types.
const (
typeInterfaceName = "Type"
extendedByMethod = "IsExtendedBy"
@ -21,7 +18,7 @@ const (
typeNameMethod = "Name"
serializeMethodName = "Serialize"
deserializeFnName = "Deserialize"
lessFnName = "Less"
typeLessMethod = "LessThan"
)
// TypeInterface returns the Type Interface that is needed for ActivityStream
@ -45,7 +42,7 @@ type Property interface {
GetPackage() Package
PropertyName() string
StructName() string
SetKindFns(name string, kind, ser, deser, less *jen.Statement) error
SetKindFns(name string, kind, deser *jen.Statement) error
DeserializeFnName() string
}
@ -128,13 +125,12 @@ func NewTypeGenerator(pm *PackageManager, typeName, comment string,
func (t *TypeGenerator) apply(m *ManagerGenerator) error {
t.m = m
// Set up Kind functions
// TODO: Call serialize on an object instead of using a function.
ser := jen.Qual(t.PrivatePackage().Path(), t.serializationFnName())
deser := jen.Qual(m.privatePackage().Path(), m.getPrivateDeserializationMethodForType(t).Name())
less := jen.Qual(t.PrivatePackage().Path(), t.lessFnName())
// Note: this "i" must be the same as the "i" in the deserialization definition.
// TODO: Remove this kluge.
deser := m.getPrivateDeserializationMethodForType(t).On(managerInitName())
kind := jen.Qual(t.PublicPackage().Path(), t.InterfaceName())
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
}
}
@ -220,17 +216,6 @@ func (t *TypeGenerator) deserializationFnName() string {
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.
//
// 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 {
t.cacheOnce.Do(func() {
members := t.members()
m := t.serializationMethod()
ser, deser, less := t.kindSerializationFuncs()
ser := t.serializationMethod()
less := t.lessMethod()
deser := t.kindDeserializationFunc()
extendsFn, extendsMethod := t.extendsDefinition()
t.cachedStruct = codegen.NewStruct(
jen.Commentf(t.Comments()),
@ -263,15 +249,14 @@ func (t *TypeGenerator) Definition() *codegen.Struct {
[]*codegen.Method{
t.nameDefinition(),
extendsMethod,
m,
ser,
less,
},
[]*codegen.Function{
t.extendedByDefinition(),
extendsFn,
t.disjointWithDefinition(),
ser,
deser,
less,
},
members)
})
@ -322,6 +307,7 @@ func (t *TypeGenerator) members() (members []jen.Code) {
// Convert to jen.Code
members = make([]jen.Code, 0, len(p))
for _, property := range sortedMembers {
// TODO: Use interface instead
members = append(members, jen.Id(strings.Title(property.PropertyName())).Qual(property.GetPackage().Path(), property.StructName()))
}
return
@ -508,20 +494,27 @@ func (t *TypeGenerator) serializationMethod() (ser *codegen.Method) {
return
}
// kindSerializationFuncs returns free function references that can be used to
// treat a TypeGenerator as another property's Kind.
func (t *TypeGenerator) kindSerializationFuncs() (ser, deser, less *codegen.Function) {
ser = codegen.NewCommentedFunction(
// lessMethod returns the method needed to compare a type with another type.
func (t *TypeGenerator) lessMethod() (less *codegen.Method) {
less = codegen.NewCommentedValueMethod(
t.PrivatePackage().Path(),
t.serializationFnName(),
[]jen.Code{jen.Id("s").Id(t.TypeName())},
[]jen.Code{jen.Interface(), jen.Error()},
typeLessMethod,
t.TypeName(),
[]jen.Code{
jen.Return(
jen.Id("s").Dot(serializeMethodName).Call(),
),
jen.Id("o").Op("*").Id(t.TypeName()),
},
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()
for name, prop := range t.allProperties() {
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.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
}