Add unknown property support
このコミットが含まれているのは:
コミット
c36c529c5f
|
@ -19,6 +19,8 @@ const (
|
|||
serializeMethodName = "Serialize"
|
||||
deserializeFnName = "Deserialize"
|
||||
compareLessMethod = "LessThan"
|
||||
getUnknownMethod = "GetUnknownProperties"
|
||||
unknownMember = "unknown"
|
||||
)
|
||||
|
||||
// TypeInterface returns the Type Interface that is needed for ActivityStream
|
||||
|
@ -228,9 +230,11 @@ func (t *TypeGenerator) InterfaceDefinition(pkg Package) *codegen.Interface {
|
|||
// Definition generates the golang code for this ActivityStreams type.
|
||||
func (t *TypeGenerator) Definition() *codegen.Struct {
|
||||
t.cacheOnce.Do(func() {
|
||||
// TODO: Constructor function (not here, maybe in manager?)
|
||||
members := t.members()
|
||||
ser := t.serializationMethod()
|
||||
less := t.lessMethod()
|
||||
get := t.getUnknownMethod()
|
||||
deser := t.kindDeserializationFunc()
|
||||
extendsFn, extendsMethod := t.extendsDefinition()
|
||||
t.cachedStruct = codegen.NewStruct(
|
||||
|
@ -241,6 +245,7 @@ func (t *TypeGenerator) Definition() *codegen.Struct {
|
|||
extendsMethod,
|
||||
ser,
|
||||
less,
|
||||
get,
|
||||
},
|
||||
[]*codegen.Function{
|
||||
t.extendedByDefinition(),
|
||||
|
@ -307,7 +312,7 @@ func (t *TypeGenerator) members() (members []jen.Code) {
|
|||
for _, property := range p {
|
||||
members = append(members, jen.Id(t.memberName(property)).Qual(property.GetPublicPackage().Path(), property.InterfaceName()))
|
||||
}
|
||||
// TODO: Unknown member
|
||||
members = append(members, jen.Id(unknownMember).Map(jen.String()).Interface())
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -480,7 +485,7 @@ func (t *TypeGenerator) disjointWithDefinition() *codegen.Function {
|
|||
// serializationMethod returns the method needed to serialize a TypeGenerator as
|
||||
// a property.
|
||||
func (t *TypeGenerator) serializationMethod() (ser *codegen.Method) {
|
||||
serCode := jen.Empty()
|
||||
serCode := jen.Commentf("Begin: Serialize known properties").Line()
|
||||
for _, prop := range t.allProperties() {
|
||||
serCode.Add(
|
||||
jen.Commentf("Maybe serialize property %q", prop.PropertyName()).Line(),
|
||||
|
@ -498,6 +503,24 @@ func (t *TypeGenerator) serializationMethod() (ser *codegen.Method) {
|
|||
jen.Id("m").Index(jen.Id(codegen.This()).Dot(t.memberName(prop)).Dot(nameMethod).Call()).Op("=").Id("i"),
|
||||
).Line())
|
||||
}
|
||||
serCode = serCode.Commentf("End: Serialize known properties").Line()
|
||||
unknownCode := jen.Commentf("Begin: Serialize unknown properties").Line().For(
|
||||
jen.List(
|
||||
jen.Id("k"),
|
||||
jen.Id("v"),
|
||||
).Op(":=").Range().Id(codegen.This()).Dot(unknownMember),
|
||||
).Block(
|
||||
jen.Commentf("To be safe, ensure we aren't overwriting a known property"),
|
||||
jen.If(
|
||||
jen.List(
|
||||
jen.Id("_"),
|
||||
jen.Id("has"),
|
||||
).Op(":=").Id("m").Index(jen.Id("k")),
|
||||
jen.Op("!").Id("has"),
|
||||
).Block(
|
||||
jen.Id("m").Index(jen.Id("k")).Op("=").Id("v"),
|
||||
),
|
||||
).Line().Commentf("End: Serialize unknown properties").Line()
|
||||
ser = codegen.NewCommentedValueMethod(
|
||||
t.PrivatePackage().Path(),
|
||||
serializeMethodName,
|
||||
|
@ -509,6 +532,7 @@ func (t *TypeGenerator) serializationMethod() (ser *codegen.Method) {
|
|||
jen.Map(jen.String()).Interface(),
|
||||
),
|
||||
serCode,
|
||||
unknownCode,
|
||||
jen.Return(jen.Id("m"), jen.Nil()),
|
||||
},
|
||||
jen.Commentf("%s converts this into an interface representation suitable for marshalling into a text or binary format.", serializeMethodName))
|
||||
|
@ -517,7 +541,7 @@ func (t *TypeGenerator) serializationMethod() (ser *codegen.Method) {
|
|||
|
||||
// lessMethod returns the method needed to compare a type with another type.
|
||||
func (t *TypeGenerator) lessMethod() (less *codegen.Method) {
|
||||
lessCode := jen.Empty()
|
||||
lessCode := jen.Commentf("Begin: Compare known properties").Line()
|
||||
for _, prop := range t.allProperties() {
|
||||
lessCode = lessCode.Add(
|
||||
jen.Commentf("Compare property %q", prop.PropertyName()).Line(),
|
||||
|
@ -535,6 +559,24 @@ func (t *TypeGenerator) lessMethod() (less *codegen.Method) {
|
|||
jen.Return(jen.False()),
|
||||
).Line())
|
||||
}
|
||||
lessCode = lessCode.Commentf("End: Compare known properties").Line()
|
||||
unknownCode := jen.Commentf("Begin: Compare unknown properties (only by number of them)").Line().If(
|
||||
jen.Len(
|
||||
jen.Id(codegen.This()).Dot(unknownMember),
|
||||
).Op("<").Len(
|
||||
jen.Id("o").Dot(getUnknownMethod).Call(),
|
||||
),
|
||||
).Block(
|
||||
jen.Return(jen.True()),
|
||||
).Else().If(
|
||||
jen.Len(
|
||||
jen.Id("o").Dot(getUnknownMethod).Call(),
|
||||
).Op("<").Len(
|
||||
jen.Id(codegen.This()).Dot(unknownMember),
|
||||
),
|
||||
).Block(
|
||||
jen.Return(jen.False()),
|
||||
).Commentf("End: Compare unknown properties (only by number of them)").Line()
|
||||
less = codegen.NewCommentedValueMethod(
|
||||
t.PrivatePackage().Path(),
|
||||
compareLessMethod,
|
||||
|
@ -545,17 +587,18 @@ func (t *TypeGenerator) lessMethod() (less *codegen.Method) {
|
|||
[]jen.Code{jen.Bool()},
|
||||
[]jen.Code{
|
||||
lessCode,
|
||||
unknownCode,
|
||||
jen.Commentf("All properties are the same."),
|
||||
jen.Return(jen.False()),
|
||||
},
|
||||
jen.Commentf("%s computes if this %s is lesser, with an arbitrary but stable determination", compareLessMethod, t.TypeName()))
|
||||
jen.Commentf("%s computes if this %s is lesser, with an arbitrary but stable determination.", compareLessMethod, 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.Commentf("Begin: Known property deserialization").Line()
|
||||
for _, prop := range t.allProperties() {
|
||||
deserMethod := t.m.getPrivateDeserializationMethodForProperty(prop)
|
||||
deserCode = deserCode.Add(
|
||||
|
@ -572,16 +615,64 @@ func (t *TypeGenerator) kindDeserializationFunc() (deser *codegen.Function) {
|
|||
jen.Id(codegen.This()).Dot(t.memberName(prop)).Op("=").Op("*").Id("p"),
|
||||
).Line())
|
||||
}
|
||||
deserCode = deserCode.Commentf("End: Known property deserialization").Line()
|
||||
knownProps := jen.Commentf("Begin: Code that ensures a property name is unknown").Line()
|
||||
for i, prop := range t.allProperties() {
|
||||
if i > 0 {
|
||||
knownProps = knownProps.Else()
|
||||
}
|
||||
knownProps = knownProps.If(
|
||||
jen.Id("k").Op("==").Lit(prop.PropertyName()),
|
||||
).Block(
|
||||
jen.Continue(),
|
||||
)
|
||||
}
|
||||
knownProps = knownProps.Commentf("End: Code that ensures a property name is unknown").Line()
|
||||
unknownCode := jen.Commentf("Begin: Unknown deserialization").Line().For(
|
||||
jen.List(
|
||||
jen.Id("k"),
|
||||
jen.Id("v"),
|
||||
).Op(":=").Range().Id("m"),
|
||||
).Block(
|
||||
knownProps,
|
||||
jen.Id(codegen.This()).Dot(unknownMember).Index(jen.Id("k")).Op("=").Id("v"),
|
||||
).Line().Commentf("End: Unknown deserialization").Line()
|
||||
deser = codegen.NewCommentedFunction(
|
||||
t.PrivatePackage().Path(),
|
||||
t.deserializationFnName(),
|
||||
[]jen.Code{jen.Id("m").Map(jen.String()).Interface()},
|
||||
[]jen.Code{jen.Op("*").Id(t.TypeName()), jen.Error()},
|
||||
[]jen.Code{
|
||||
jen.Id(codegen.This()).Op(":=").Op("&").Id(t.TypeName()).Values(),
|
||||
jen.Id(codegen.This()).Op(":=").Op("&").Id(t.TypeName()).Values(jen.Dict{
|
||||
jen.Id(unknownMember): jen.Make(jen.Map(jen.String()).Interface()),
|
||||
}),
|
||||
deserCode,
|
||||
unknownCode,
|
||||
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()))
|
||||
return
|
||||
}
|
||||
|
||||
// getUnknownMethod returns the GetUnknown helper used to compare which type is
|
||||
// LessThan. This method is API-leaky and shouldn't be used by normal app
|
||||
// developers.
|
||||
func (t *TypeGenerator) getUnknownMethod() (get *codegen.Method) {
|
||||
get = codegen.NewCommentedValueMethod(
|
||||
t.PrivatePackage().Path(),
|
||||
getUnknownMethod,
|
||||
t.TypeName(),
|
||||
/*params=*/ nil,
|
||||
[]jen.Code{jen.Map(jen.String()).Interface()},
|
||||
[]jen.Code{
|
||||
jen.Return(jen.Id(codegen.This()).Dot(unknownMember)),
|
||||
},
|
||||
jen.Commentf(`%s returns the unknown properties for the %s type.
|
||||
|
||||
Note that this should not be used by app developers. It is only used to help determine
|
||||
which implementation is LessThan the other. Developers who are creating a different
|
||||
implementation of this type's interface can use this method in their LessThan
|
||||
implementation, but routine ActivityPub applications should not use this to bypass the
|
||||
code generation tool.`, getUnknownMethod, t.TypeName()))
|
||||
return
|
||||
}
|
||||
|
|
読み込み中…
新しいイシューから参照