Add per-package files for property-based packages.

このコミットが含まれているのは:
Cory Slep 2019-01-06 00:13:24 +01:00
コミット be110cf688
5個のファイルの変更99行の追加7行の削除

ファイルの表示

@ -173,6 +173,12 @@ func (c Converter) convertToFiles(v vocabulary) (f []*File, e error) {
Directory: pub.WriteDir(),
})
}
propPkgFiles, err := c.propertyPackageFiles(v.FProps, v.NFProps)
if err != nil {
e = err
return
}
f = append(f, propPkgFiles...)
// Types
for _, i := range v.Types {
var pm *props.PackageManager
@ -617,6 +623,45 @@ func (c Converter) typePackageFiles(t map[string]*props.TypeGenerator) (f []*Fil
return
}
func (c Converter) propertyPackageFiles(fp map[string]*props.FunctionalPropertyGenerator, nfp map[string]*props.NonFunctionalPropertyGenerator) (f []*File, e error) {
switch c.PropertyPackagePolicy {
case PropertyFlatUnderRoot:
fallthrough
case PropertyFlatUnderVocabularyRoot:
// Only need one for all types.
pgs := make([]*props.PropertyGenerator, 0, len(fp)+len(nfp))
for _, v := range fp {
pgs = append(pgs, &v.PropertyGenerator)
}
for _, v := range nfp {
pgs = append(pgs, &v.PropertyGenerator)
}
ppg := props.NewPropertyPackageGenerator()
// Private
s, i, fn := ppg.PrivateDefinitions(pgs)
priv := pgs[0].GetPrivatePackage()
file := jen.NewFilePath(priv.Path())
file.Add(
s,
).Line().Add(
i.Definition(),
).Line().Add(
fn.Definition(),
).Line()
f = append(f, &File{
F: file,
FileName: "gen_pkg.go",
Directory: priv.WriteDir(),
})
case PropertyIndividualUnderRoot:
// Need individual files per type.
// TODO
default:
e = fmt.Errorf("unrecognized PropertyPackagePolicy: %v", c.PropertyPackagePolicy)
}
return
}
type typeNamer interface {
TypeName() string
}

ファイルの表示

@ -321,7 +321,7 @@ func (p *FunctionalPropertyGenerator) serializationFuncs() (*codegen.Method, *co
jen.List(
jen.Id("v"),
jen.Err(),
).Op(":=").Add(kind.DeserializeFn.Clone().Call(
).Op(":=").Add(kind.DeserializeFn.Clone().Call().Call(
jen.Id("i"),
)),
jen.Err().Op("!=").Nil(),

ファイルの表示

@ -148,3 +148,42 @@ func (t *TypePackageGenerator) PrivateDefinitions(tgs []*TypeGenerator) (*jen.St
// PropertyPackageGenerator manages generating one-time files needed for
// properties.
type PropertyPackageGenerator struct{}
// NewPropertyPackageGenerator creates a new TypePackageGenerator.
func NewPropertyPackageGenerator() *PropertyPackageGenerator {
return &PropertyPackageGenerator{}
}
// PrivateDefinitions creates the private code generated definitions needed once
// per package.
//
// Precondition: The passed-in generators are the complete set of type
// generators within a package.
func (p *PropertyPackageGenerator) PrivateDefinitions(pgs []*PropertyGenerator) (*jen.Statement, *codegen.Interface, *codegen.Function) {
fnsMap := make(map[string]codegen.FunctionSignature)
for _, pg := range pgs {
for _, m := range pg.getAllManagerMethods() {
v := m.ToFunctionSignature()
fnsMap[v.Name] = v
}
}
var fns []codegen.FunctionSignature
for _, v := range fnsMap {
fns = append(fns, v)
}
return jen.Var().Id(managerInitName()).Id(managerInterfaceName),
codegen.NewInterface(pgs[0].GetPrivatePackage().Path(),
managerInterfaceName,
fns,
fmt.Sprintf("%s abstracts the code-generated manager that provides access to concrete implementations.", managerInterfaceName)),
codegen.NewCommentedFunction(pgs[0].GetPrivatePackage().Path(),
setManagerFunctionName,
[]jen.Code{
jen.Id("m").Id(managerInterfaceName),
},
/*ret=*/ nil,
[]jen.Code{
jen.Id(managerInitName()).Op("=").Id("m"),
},
jen.Commentf("%s sets the manager package-global variable. For internal use only, do not use as part of Application behavior. Must be called at golang init time.", setManagerFunctionName))
}

ファイルの表示

@ -105,7 +105,8 @@ func (k Kind) lessFnCode(this, other *jen.Statement) *jen.Statement {
//
// TODO: Make this type private
type PropertyGenerator struct {
vocabName string
vocabName string
managerMethods []*codegen.Method
// TODO: Make these private
PackageManager *PackageManager
Name Identifier
@ -136,14 +137,15 @@ func (p *PropertyGenerator) GetPublicPackage() Package {
// The name parameter must match the LowerName of an Identifier.
//
// This feels very hacky.
func (p *PropertyGenerator) SetKindFns(name string, qualKind, deser *jen.Statement) error {
func (p *PropertyGenerator) SetKindFns(name string, qualKind *jen.Statement, deser *codegen.Method) 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.DeserializeFn = deser
kind.DeserializeFn = deser.On(managerInitName())
p.managerMethods = append(p.managerMethods, deser)
p.Kinds[i] = kind
return nil
}
@ -151,6 +153,12 @@ func (p *PropertyGenerator) SetKindFns(name string, qualKind, deser *jen.Stateme
return fmt.Errorf("cannot find property kind %q", name)
}
// getAllManagerMethods returns the list of manager methods used by this
// property.
func (p *PropertyGenerator) getAllManagerMethods() []*codegen.Method {
return p.managerMethods
}
// StructName returns the name of the type, which may or may not be a struct,
// to generate.
func (p *PropertyGenerator) StructName() string {

ファイルの表示

@ -44,7 +44,7 @@ type Property interface {
GetPublicPackage() Package
PropertyName() string
InterfaceName() string
SetKindFns(name string, kind, deser *jen.Statement) error
SetKindFns(name string, kind *jen.Statement, deser *codegen.Method) error
DeserializeFnName() string
}
@ -130,8 +130,8 @@ func (t *TypeGenerator) apply(m *ManagerGenerator) error {
t.m = m
// Set up Kind functions
// Note: this "i" must be the same as the "i" in the deserialization definition.
// TODO: Remove this kluge.
deser := m.getDeserializationMethodForType(t).On(managerInitName())
// TODO: Remove this kluge. (2nd todo: figure out wtf this todo means)
deser := m.getDeserializationMethodForType(t)
kind := jen.Qual(t.PublicPackage().Path(), t.InterfaceName())
for _, p := range t.rangeProperties {
if e := p.SetKindFns(t.TypeName(), kind, deser); e != nil {