Fix concrete types to be interfaces in properties.

Fix bug in method calling code generation.
このコミットが含まれているのは:
Cory Slep 2018-12-31 16:49:25 +01:00
コミット 5db3a68a8d
7個のファイルの変更73行の追加60行の削除

ファイルの表示

@ -199,7 +199,7 @@ func (m Method) Definition() jen.Code {
// Call generates the Go code required to call this method, with qualifier if
// required.
func (m Method) Call(on string, params ...jen.Code) jen.Code {
return jen.Id(on).Call(params...)
return jen.Id(on).Dot(m.function.name).Call(params...)
}
// Name returns the identifier of this function.

ファイルの表示

@ -259,7 +259,6 @@ func (c Converter) convertType(t rdf.VocabularyType,
if e != nil {
return
}
pkg := pm.PrivatePackage()
// Determine the properties for this type
var p []props.Property
for _, prop := range t.Properties {
@ -345,7 +344,7 @@ func (c Converter) convertType(t rdf.VocabularyType,
}
}
tg, e = props.NewTypeGenerator(
pkg,
pm,
name,
t.Notes,
p,
@ -405,10 +404,11 @@ func (c Converter) convertNonFunctionalProperty(p rdf.VocabularyProperty,
func (c Converter) convertValue(v rdf.VocabularyValue) (k *props.Kind) {
k = &props.Kind{
Name: c.toIdentifier(v),
ConcreteKind: v.DefinitionType,
Name: c.toIdentifier(v),
// TODO: Add Qualifier
ConcreteKind: jen.Id(v.DefinitionType),
Nilable: c.isNilable(v.DefinitionType),
// TODO
// TODO: Fix Qualifying calls?
SerializeFn: jen.Empty().Add(v.SerializeFn.Call()),
DeserializeFn: jen.Empty().Add(v.DeserializeFn.Call()),
LessFn: jen.Empty().Add(v.LessFn.Call()),
@ -418,10 +418,10 @@ func (c Converter) convertValue(v rdf.VocabularyValue) (k *props.Kind) {
func (c Converter) convertTypeToKind(v rdf.VocabularyType) (k *props.Kind, e error) {
k = &props.Kind{
Name: c.toIdentifier(v),
ConcreteKind: c.convertTypeToConcreteKind(v),
Nilable: true,
Name: c.toIdentifier(v),
Nilable: true,
// Instead of populating:
// - ConcreteKind
// - SerializeFn
// - DeserializeFn
// - LessFn
@ -437,10 +437,6 @@ func (c Converter) convertTypeToName(v rdf.VocabularyType) string {
return strings.Title(v.Name)
}
func (c Converter) convertTypeToConcreteKind(v rdf.VocabularyType) string {
return "*" + c.convertTypeToName(v)
}
func (c Converter) propertyKinds(v rdf.VocabularyProperty,
kinds map[string]*props.Kind,
vocab rdf.Vocabulary,

ファイルの表示

@ -284,7 +284,7 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, *co
}
serializeFns = serializeFns.Block(
jen.Return(
kind.SerializeFn.Call(
kind.SerializeFn.Clone().Call(
jen.Id(codegen.This()).Dot(p.getFnName(i)).Call(),
),
),
@ -317,7 +317,7 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, *co
jen.Id("v"),
jen.Id("handled"),
jen.Err(),
).Op(":=").Add(kind.DeserializeFn.Call(
).Op(":=").Add(kind.DeserializeFn.Clone().Call(
jen.Id("i"),
)),
jen.Id("handled"),
@ -385,7 +385,7 @@ func (p *FunctionalPropertyGenerator) singleTypeDef() *codegen.Struct {
comment = jen.Commentf("%s is an iterator for a property. It is permitted to be a single nilable value type.", p.StructName())
}
kindMembers = []jen.Code{
jen.Id(p.memberName(0)).Id(p.Kinds[0].ConcreteKind),
jen.Id(p.memberName(0)).Add(p.Kinds[0].ConcreteKind),
}
} else {
comment = jen.Commentf("%s is the functional property %q. It is permitted to be a single default-valued value type.", p.StructName(), p.PropertyName())
@ -393,7 +393,7 @@ func (p *FunctionalPropertyGenerator) singleTypeDef() *codegen.Struct {
comment = jen.Commentf("%s is an iterator for a property. It is permitted to be a single default-valued value type.", p.StructName())
}
kindMembers = []jen.Code{
jen.Id(p.memberName(0)).Id(p.Kinds[0].ConcreteKind),
jen.Id(p.memberName(0)).Add(p.Kinds[0].ConcreteKind),
jen.Id(p.hasMemberName(0)).Bool(),
}
}
@ -463,7 +463,8 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
p.getFnName(0),
p.StructName(),
/*params=*/ nil,
[]jen.Code{jen.Id(p.Kinds[0].ConcreteKind)},
// TODO: Interface Kind
[]jen.Code{p.Kinds[0].ConcreteKind},
[]jen.Code{jen.Return(jen.Id(codegen.This()).Dot(p.memberName(0)))},
getComment,
))
@ -484,7 +485,8 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
p.Package.Path(),
p.setFnName(0),
p.StructName(),
[]jen.Code{jen.Id("v").Id(p.Kinds[0].ConcreteKind)},
// TODO: Interface Kind
[]jen.Code{jen.Id("v").Add(p.Kinds[0].ConcreteKind)},
/*ret=*/ nil,
[]jen.Code{
jen.Id(codegen.This()).Dot(p.clearMethodName()).Call(),
@ -497,7 +499,7 @@ func (p *FunctionalPropertyGenerator) singleTypeFuncs() []*codegen.Method {
p.Package.Path(),
p.setFnName(0),
p.StructName(),
[]jen.Code{jen.Id("v").Id(p.Kinds[0].ConcreteKind)},
[]jen.Code{jen.Id("v").Add(p.Kinds[0].ConcreteKind)},
/*ret=*/ nil,
[]jen.Code{
jen.Id(codegen.This()).Dot(p.clearMethodName()).Call(),
@ -551,9 +553,9 @@ func (p *FunctionalPropertyGenerator) multiTypeDef() *codegen.Struct {
kindMembers := make([]jen.Code, 0, len(p.Kinds))
for i, kind := range p.Kinds {
if kind.Nilable {
kindMembers = append(kindMembers, jen.Id(p.memberName(i)).Id(p.Kinds[i].ConcreteKind))
kindMembers = append(kindMembers, jen.Id(p.memberName(i)).Add(p.Kinds[i].ConcreteKind))
} else {
kindMembers = append(kindMembers, jen.Id(p.memberName(i)).Id(p.Kinds[i].ConcreteKind))
kindMembers = append(kindMembers, jen.Id(p.memberName(i)).Add(p.Kinds[i].ConcreteKind))
kindMembers = append(kindMembers, jen.Id(p.hasMemberName(i)).Bool())
}
}
@ -707,7 +709,8 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
p.Package.Path(),
p.setFnName(i),
p.StructName(),
[]jen.Code{jen.Id("v").Id(kind.ConcreteKind)},
// TODO: Interface Kind
[]jen.Code{jen.Id("v").Add(kind.ConcreteKind)},
/*ret=*/ nil,
[]jen.Code{
jen.Id(codegen.This()).Dot(p.clearMethodName()).Call(),
@ -720,7 +723,8 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
p.Package.Path(),
p.setFnName(i),
p.StructName(),
[]jen.Code{jen.Id("v").Id(kind.ConcreteKind)},
// TODO: Interface Kind
[]jen.Code{jen.Id("v").Add(kind.ConcreteKind)},
/*ret=*/ nil,
[]jen.Code{
jen.Id(codegen.This()).Dot(p.clearMethodName()).Call(),
@ -739,7 +743,8 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method {
p.getFnName(i),
p.StructName(),
/*params=*/ nil,
[]jen.Code{jen.Id(kind.ConcreteKind)},
// TODO: Interface Kind
[]jen.Code{jen.Add(kind.ConcreteKind)},
[]jen.Code{jen.Return(jen.Id(codegen.This()).Dot(p.memberName(i)))},
getComment,
))

ファイルの表示

@ -116,7 +116,7 @@ func NewManagerGenerator(pm PackageManager,
// Pass 3: Populate interfaces of the types and properties, which relies
// on the first pass's data population.
for _, t := range tg {
publicPkg := t.Package().Parent().PublicPackage()
publicPkg := t.PublicPackage()
mg.tgManagedMethods[t].ifaces = []*codegen.Interface{t.toInterface(publicPkg)}
}
// TODO: Move these back to pass 1
@ -187,14 +187,12 @@ func (m *ManagerGenerator) PrivateManager() *codegen.Struct {
for _, nfp := range m.nfpManagedMethods {
methods = append(methods, nfp.deserializor)
}
var functions []*codegen.Function
var members []jen.Code
s := codegen.NewStruct(
jen.Commentf(fmt.Sprintf("%s privately manages concrete types and deserializations for internal use by generated code. Application code should use the public version instead, which uses interfaces to abstract away the generated code and allow apps to not entirely rely on go-fed should they choose not to.", managerName)),
managerName,
methods,
functions,
members)
/*functions=*/ nil,
/*members=*/ nil)
return s
}
@ -205,7 +203,7 @@ func (m *ManagerGenerator) PrivateManager() *codegen.Struct {
func (m *ManagerGenerator) createPrivateDeserializationMethodForType(tg *TypeGenerator) *codegen.Method {
dn := tg.deserializationFnName()
pkg := m.pm.PrivatePackage()
name := fmt.Sprintf("%s%s%s", dn, tg.Package().Name(), strings.Title(pkg.Name()))
name := fmt.Sprintf("%s%s%s", dn, tg.PrivatePackage().Name(), strings.Title(pkg.Name()))
return codegen.NewCommentedValueMethod(
pkg.Path(),
name,
@ -222,10 +220,10 @@ func (m *ManagerGenerator) createPrivateDeserializationMethodForType(tg *TypeGen
},
[]jen.Code{
jen.Return(
jen.Qual(tg.Package().Path(), dn),
jen.Qual(tg.PrivatePackage().Path(), dn),
),
},
jen.Commentf("%s returns the deserialization method for the %q type in package %q", name, tg.TypeName(), tg.Package().Name()))
jen.Commentf("%s returns the deserialization method for the %q type in package %q", name, tg.TypeName(), tg.PrivatePackage().Name()))
}
// createPrivateDeserializationMethodForFuncProperty creates a new method for the

ファイルの表示

@ -121,7 +121,8 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
p.Package.Path(),
prependMethodName,
p.StructName(),
[]jen.Code{jen.Id("v").Id(kind.ConcreteKind)},
// TODO: Interface Kind
[]jen.Code{jen.Id("v").Add(kind.ConcreteKind)},
/*ret=*/ nil,
[]jen.Code{
jen.Op("*").Id(codegen.This()).Op("=").Append(
@ -139,7 +140,8 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
p.Package.Path(),
appendMethodName,
p.StructName(),
[]jen.Code{jen.Id("v").Id(kind.ConcreteKind)},
// TODO: Interface Kind
[]jen.Code{jen.Id("v").Add(kind.ConcreteKind)},
/*ret=*/ nil,
[]jen.Code{
jen.Op("*").Id(codegen.This()).Op("=").Append(
@ -159,7 +161,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method {
).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.Call(
jen.Return(kind.LessFn.Clone().Call(
jen.Id("lhs"),
jen.Id("rhs"),
)),

ファイルの表示

@ -58,11 +58,14 @@ type Identifier struct {
// Kind is data that describes a concrete Go type, how to serialize and
// deserialize such types, compare the types, and other meta-information to use
// during Go code generation.
//
// Only represents values and other types.
type Kind struct {
Name Identifier
ConcreteKind string
Name Identifier
// ConcreteKind is expected to be a jen.Qual
ConcreteKind *jen.Statement
Nilable bool
// Expected to be a jen.Qual
// These functions are expected to be a jen.Qual
SerializeFn *jen.Statement
DeserializeFn *jen.Statement
LessFn *jen.Statement
@ -97,12 +100,13 @@ 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, ser, deser, less *jen.Statement) error {
func (p *PropertyGenerator) SetKindFns(name string, qualKind, ser, deser, less *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

ファイルの表示

@ -45,13 +45,13 @@ type Property interface {
GetPackage() Package
PropertyName() string
StructName() string
SetKindFns(name string, ser, deser, less *jen.Statement) error
SetKindFns(name string, kind, ser, deser, less *jen.Statement) error
DeserializeFnName() string
}
// TypeGenerator represents an ActivityStream type definition to generate in Go.
type TypeGenerator struct {
pkg Package
pm *PackageManager
typeName string
comment string
properties map[string]Property
@ -85,11 +85,11 @@ type TypeGenerator struct {
//
// A ManagerGenerator must be created with this type before Definition is
// called, to ensure that the serialization functions are properly set up.
func NewTypeGenerator(pkg Package, typeName, comment string,
func NewTypeGenerator(pm *PackageManager, typeName, comment string,
properties, withoutProperties, rangeProperties []Property,
extends, disjoint []*TypeGenerator) (*TypeGenerator, error) {
t := &TypeGenerator{
pkg: pkg,
pm: pm,
typeName: typeName,
comment: comment,
properties: make(map[string]Property, len(properties)),
@ -128,20 +128,27 @@ func NewTypeGenerator(pkg Package, typeName, comment string,
func (t *TypeGenerator) apply(m *ManagerGenerator) error {
t.m = m
// Set up Kind functions
ser := jen.Qual(t.Package().Path(), t.serializationFnName())
// 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.Package().Path(), t.lessFnName())
less := jen.Qual(t.PrivatePackage().Path(), t.lessFnName())
kind := jen.Qual(t.PublicPackage().Path(), t.InterfaceName())
for _, p := range t.rangeProperties {
if e := p.SetKindFns(t.TypeName(), ser, deser, less); e != nil {
if e := p.SetKindFns(t.TypeName(), kind, ser, deser, less); e != nil {
return e
}
}
return nil
}
// Package gets this TypeGenerator's Package.
func (t *TypeGenerator) Package() Package {
return t.pkg
// Package gets this TypeGenerator's Private Package.
func (t *TypeGenerator) PrivatePackage() Package {
return t.pm.PrivatePackage()
}
// Package gets this TypeGenerator's Public Package.
func (t *TypeGenerator) PublicPackage() Package {
return t.pm.PublicPackage()
}
// Comment returns the comment for this type.
@ -324,7 +331,7 @@ func (t *TypeGenerator) members() (members []jen.Code) {
// type name.
func (t *TypeGenerator) nameDefinition() *codegen.Method {
return codegen.NewCommentedValueMethod(
t.pkg.Path(),
t.PrivatePackage().Path(),
typeNameMethod,
t.TypeName(),
/*params=*/ nil,
@ -374,14 +381,14 @@ func (t *TypeGenerator) extendsDefinition() (*codegen.Function, *codegen.Method)
jen.Return(jen.False())}
}
f := codegen.NewCommentedFunction(
t.pkg.Path(),
t.PrivatePackage().Path(),
t.extendsFnName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
[]jen.Code{jen.Bool()},
impl,
jen.Commentf("%s returns true if the %s type extends from the other type.", t.extendsFnName(), t.TypeName()))
m := codegen.NewCommentedValueMethod(
t.pkg.Path(),
t.PrivatePackage().Path(),
extendingMethod,
t.TypeName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
@ -430,7 +437,7 @@ func (t *TypeGenerator) extendedByDefinition() *codegen.Function {
jen.Return(jen.False())}
}
return codegen.NewCommentedFunction(
t.pkg.Path(),
t.PrivatePackage().Path(),
t.extendedByFnName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
[]jen.Code{jen.Bool()},
@ -476,7 +483,7 @@ func (t *TypeGenerator) disjointWithDefinition() *codegen.Function {
jen.Return(jen.False())}
}
return codegen.NewCommentedFunction(
t.pkg.Path(),
t.PrivatePackage().Path(),
t.disjointWithFnName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
[]jen.Code{jen.Bool()},
@ -488,7 +495,7 @@ func (t *TypeGenerator) disjointWithDefinition() *codegen.Function {
// a property.
func (t *TypeGenerator) serializationMethod() (ser *codegen.Method) {
ser = codegen.NewCommentedValueMethod(
t.pkg.Path(),
t.PrivatePackage().Path(),
serializeMethodName,
t.TypeName(),
/*params=*/ nil,
@ -505,7 +512,7 @@ func (t *TypeGenerator) serializationMethod() (ser *codegen.Method) {
// treat a TypeGenerator as another property's Kind.
func (t *TypeGenerator) kindSerializationFuncs() (ser, deser, less *codegen.Function) {
ser = codegen.NewCommentedFunction(
t.pkg.Path(),
t.PrivatePackage().Path(),
t.serializationFnName(),
[]jen.Code{jen.Id("s").Id(t.TypeName())},
[]jen.Code{jen.Interface(), jen.Error()},
@ -523,7 +530,8 @@ func (t *TypeGenerator) kindSerializationFuncs() (ser, deser, less *codegen.Func
jen.List(
jen.Id("p"),
jen.Err(),
).Op(":=").Add(deserMethod.Call(managerInitName())).Call(jen.Id("m")),
// TODO: Ensure this variable is called correctly
).Op(":=").Add(deserMethod.Call(managerInitName(), jen.Id("m"))),
jen.Err().Op("!=").Nil(),
).Block(
jen.Return(jen.Nil(), jen.Err()),
@ -532,7 +540,7 @@ func (t *TypeGenerator) kindSerializationFuncs() (ser, deser, less *codegen.Func
).Line())
}
deser = codegen.NewCommentedFunction(
t.pkg.Path(),
t.PrivatePackage().Path(),
t.deserializationFnName(),
[]jen.Code{jen.Id("m").Map(jen.String()).Interface()},
[]jen.Code{jen.Op("*").Id(t.TypeName()), jen.Error()},
@ -543,7 +551,7 @@ func (t *TypeGenerator) kindSerializationFuncs() (ser, deser, less *codegen.Func
},
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.pkg.Path(),
t.PrivatePackage().Path(),
t.lessFnName(),
[]jen.Code{
jen.Id("i"),