diff --git a/tools/exp/props/funcprop.go b/tools/exp/props/funcprop.go index 7dd70fa..31eb664 100644 --- a/tools/exp/props/funcprop.go +++ b/tools/exp/props/funcprop.go @@ -135,7 +135,7 @@ func (p *FunctionalPropertyGenerator) funcs() []*codegen.Method { join(kindIndexFns), jen.Return(jen.Lit(-1)), }, - jen.Commentf("%s computes an arbitrary value for indexing this kind of value.", kindIndexMethod), + jen.Commentf("%s computes an arbitrary value for indexing this kind of value. This is a leaky API detail only for folks looking to replace the go-fed implementation. Applications should not use this method.", kindIndexMethod), ), } if p.HasNaturalLanguageMap { @@ -320,19 +320,18 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, *co deserializeFns = deserializeFns.If( jen.List( jen.Id("v"), - jen.Id("handled"), jen.Err(), ).Op(":=").Add(kind.DeserializeFn.Clone().Call( jen.Id("i"), )), - jen.Id("handled"), + jen.Err().Op("!=").Nil(), ).Block( jen.Id(codegen.This()).Op(":=").Op("&").Id(p.StructName()).Values( values, ), jen.Return( jen.Id(codegen.This()), - jen.Err(), + jen.Nil(), ), ) } @@ -344,7 +343,15 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, *co []jen.Code{jen.Id("i").Interface()}, []jen.Code{jen.Op("*").Id(p.StructName()), jen.Error()}, []jen.Code{ - p.addUnknownDeserializeCode(deserializeFns), + p.addUnknownDeserializeCode(deserializeFns).Else().Block( + jen.Return( + jen.Nil(), + jen.Qual("fmt", "Errorf").Call( + jen.Lit("could not deserialize %q property"), + jen.Lit(p.PropertyName()), + ), + ), + ), jen.Return( jen.Nil(), jen.Nil(), @@ -653,7 +660,7 @@ func (p *FunctionalPropertyGenerator) multiTypeFuncs() []*codegen.Method { isLanguageMapMethod, ) } - methods = append(methods, codegen.NewCommentedPointerMethod( + methods = append(methods, codegen.NewCommentedValueMethod( p.GetPrivatePackage().Path(), hasAnyMethodName, p.StructName(), @@ -816,7 +823,7 @@ func (p *FunctionalPropertyGenerator) unknownMemberDef() jen.Code { // addUnknownDeserializeCode generates the "else if it's a []byte" code used for // deserializing unknown values. -func (p *FunctionalPropertyGenerator) addUnknownDeserializeCode(existing jen.Code) jen.Code { +func (p *FunctionalPropertyGenerator) addUnknownDeserializeCode(existing jen.Code) *jen.Statement { if len(p.Kinds) > 0 { existing = jen.Add(existing, jen.Else()) } diff --git a/tools/exp/props/nonfuncprop.go b/tools/exp/props/nonfuncprop.go index 9087952..ec2a8b5 100644 --- a/tools/exp/props/nonfuncprop.go +++ b/tools/exp/props/nonfuncprop.go @@ -7,6 +7,10 @@ import ( "sync" ) +const ( + atMethodName = "At" +) + // NonFunctionalPropertyGenerator produces Go code for properties that can have // more than one value. The resulting property is a type that is a list of // iterators; each iterator is a concrete struct type. The property can be @@ -63,7 +67,7 @@ func (p *NonFunctionalPropertyGenerator) Definitions() (*codegen.Struct, *codege property := codegen.NewTypedef( jen.Commentf("%s is the non-functional property %q. It is permitted to have one or more values, and of different value types.", p.StructName(), p.PropertyName()), p.StructName(), - jen.Index().Id(p.iteratorTypeName().CamelName), + jen.Index().Op("*").Id(p.iteratorTypeName().CamelName), methods, funcs) iterator := p.elementTypeGenerator().Definition() @@ -80,6 +84,15 @@ func (p *NonFunctionalPropertyGenerator) iteratorTypeName() Identifier { } } +// iteratorInterfaceName gets the interface name for the iterator. +// +// TODO: Fix this kluge, which must be kept in sync with +// PropertyGenerator.InterfaceName(). +func (p *NonFunctionalPropertyGenerator) iteratorInterfaceName() string { + id := p.iteratorTypeName() + return fmt.Sprintf("%sInterface", id.CamelName) +} + // elementTypeGenerator produces a FunctionalPropertyGenerator for the iterator // type. func (p *NonFunctionalPropertyGenerator) elementTypeGenerator() *FunctionalPropertyGenerator { @@ -116,7 +129,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method { /*ret=*/ nil, []jen.Code{ jen.Op("*").Id(codegen.This()).Op("=").Append( - jen.Index().Id(p.iteratorTypeName().CamelName).Values( + jen.Index().Op("*").Id(p.iteratorTypeName().CamelName).Values( jen.Values(dict), ), jen.Op("*").Id(codegen.This()).Op("..."), @@ -135,7 +148,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method { []jen.Code{ jen.Op("*").Id(codegen.This()).Op("=").Append( jen.Op("*").Id(codegen.This()), - jen.Id(p.iteratorTypeName().CamelName).Values( + jen.Op("&").Id(p.iteratorTypeName().CamelName).Values( dict, ), ), @@ -181,7 +194,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method { jen.Op("*").Id(codegen.This()), ).Index( jen.Len(jen.Op("*").Id(codegen.This())).Op("-").Lit(1), - ).Op("=").Id(p.iteratorTypeName().CamelName).Values(), + ).Op("=").Op("&").Id(p.iteratorTypeName().CamelName).Values(), jen.Op("*").Id(codegen.This()).Op("=").Parens( jen.Op("*").Id(codegen.This()), ).Index( @@ -249,7 +262,7 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method { jen.Return(jen.False()), }, jen.Commentf("%s computes whether another property is less than this one. Mixing types results in a consistent but arbitrary ordering", lessMethod))) - // Kind Method + // KindIndex Method methods = append(methods, codegen.NewCommentedValueMethod( p.GetPrivatePackage().Path(), @@ -300,6 +313,19 @@ func (p *NonFunctionalPropertyGenerator) funcs() []*codegen.Method { }, jen.Commentf("%s compares two instances of this property with an arbitrary but stable comparison.", compareLessMethod), )) + // At Method + methods = append(methods, codegen.NewCommentedValueMethod( + p.GetPrivatePackage().Path(), + atMethodName, + p.StructName(), + []jen.Code{jen.Id("index").Int()}, + []jen.Code{jen.Qual(p.GetPublicPackage().Path(), p.iteratorInterfaceName())}, + []jen.Code{ + jen.Return( + jen.Id(codegen.This()).Index(jen.Id("index")), + ), + }, + jen.Commentf("%s returns the property value for the specified index.", atMethodName))) methods = append(methods, p.commonMethods()...) return methods } @@ -369,7 +395,7 @@ func (p *NonFunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, ).Block( jen.Id(codegen.This()).Op("=").Append( jen.Id(codegen.This()), - jen.Op("*").Id("p"), + jen.Id("p"), ), ) } @@ -379,7 +405,7 @@ func (p *NonFunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, []jen.Code{jen.Id("m").Map(jen.String()).Interface()}, []jen.Code{jen.Id(p.StructName()), jen.Error()}, []jen.Code{ - jen.Var().Id(codegen.This()).Index().Id(p.iteratorTypeName().CamelName), + jen.Var().Id(codegen.This()).Index().Op("*").Id(p.iteratorTypeName().CamelName), jen.If( jen.List( jen.Id("i"), diff --git a/tools/exp/props/property.go b/tools/exp/props/property.go index 0310b8c..249a2de 100644 --- a/tools/exp/props/property.go +++ b/tools/exp/props/property.go @@ -20,7 +20,7 @@ const ( lenMethod = "Len" swapMethod = "Swap" lessMethod = "Less" - kindIndexMethod = "kindIndex" + kindIndexMethod = "KindIndex" serializeMethod = "Serialize" deserializeMethod = "Deserialize" nameMethod = "Name"