Add per-package files for type-based packages.

This takes care of abstracting away the manager for the generated types,
and also provides the hooks for the manager to inject itself at init
time.
このコミットが含まれているのは:
Cory Slep 2019-01-05 22:46:58 +01:00
コミット 58e3d21e19
3個のファイルの変更122行の追加4行の削除

ファイルの表示

@ -199,6 +199,12 @@ func (c Converter) convertToFiles(v vocabulary) (f []*File, e error) {
Directory: pub.WriteDir(),
})
}
typePkgFiles, err := c.typePackageFiles(v.Types)
if err != nil {
e = err
return
}
f = append(f, typePkgFiles...)
// Manager
pub := c.VocabularyRoot.PublicPackage()
file := jen.NewFilePath(pub.Path())
@ -565,6 +571,52 @@ func (c Converter) propertyPackageManager(v propertyNamer) (pkg *props.PackageMa
return
}
func (c Converter) typePackageFiles(t map[string]*props.TypeGenerator) (f []*File, e error) {
switch c.TypePackagePolicy {
case TypeFlatUnderRoot:
fallthrough
case TypeFlatUnderVocabularyRoot:
// Only need one for all types.
tgs := make([]*props.TypeGenerator, 0, len(t))
for _, v := range t {
tgs = append(tgs, v)
}
tpg := props.NewTypePackageGenerator()
pubI := tpg.PublicDefinitions(tgs)
// Public
pub := tgs[0].PublicPackage()
file := jen.NewFilePath(pub.Path())
file.Add(pubI.Definition())
f = append(f, &File{
F: file,
FileName: "gen_pkg.go",
Directory: pub.WriteDir(),
})
// Private
s, i, fn := tpg.PrivateDefinitions(tgs)
priv := tgs[0].PrivatePackage()
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 TypeIndividualUnderRoot:
// Need individual files per type.
// TODO
default:
e = fmt.Errorf("unrecognized TypePackagePolicy: %v", c.TypePackagePolicy)
}
return
}
type typeNamer interface {
TypeName() string
}

ファイルの表示

@ -2,6 +2,8 @@ package props
import (
"fmt"
"github.com/cjslep/activity/tools/exp/codegen"
"github.com/dave/jennifer/jen"
"strings"
)
@ -86,3 +88,58 @@ func (p Package) IsPublic() bool {
func (p Package) Parent() *PackageManager {
return p.parent
}
const (
managerInterfaceName = "privateManager"
setManagerFunctionName = "SetManager"
)
// TypePackageGenerator manages generating one-time files needed for types.
type TypePackageGenerator struct{}
// NewTypePackageGenerator creates a new TypePackageGenerator.
func NewTypePackageGenerator() *TypePackageGenerator {
return &TypePackageGenerator{}
}
// PublicDefinitions creates the public-facing code generated definitions needed
// once per package.
//
// Precondition: The passed-in generators are the complete set of type
// generators within a package.
func (t *TypePackageGenerator) PublicDefinitions(tgs []*TypeGenerator) *codegen.Interface {
return TypeInterface(tgs[0].PublicPackage())
}
// 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 (t *TypePackageGenerator) PrivateDefinitions(tgs []*TypeGenerator) (*jen.Statement, *codegen.Interface, *codegen.Function) {
var fns []codegen.FunctionSignature
for _, tg := range tgs {
for _, m := range tg.getAllManagerMethods() {
fns = append(fns, m.ToFunctionSignature())
}
}
return jen.Var().Id(managerInitName()).Id(managerInterfaceName),
codegen.NewInterface(tgs[0].PrivatePackage().Path(),
managerInterfaceName,
fns,
fmt.Sprintf("%s abstracts the code-generated manager that provides access to concrete implementations.", managerInterfaceName)),
codegen.NewCommentedFunction(tgs[0].PrivatePackage().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))
}
// PropertyPackageGenerator manages generating one-time files needed for
// properties.
type PropertyPackageGenerator struct{}

ファイルの表示

@ -377,7 +377,7 @@ func (t *TypeGenerator) extendsDefinition() (*codegen.Function, *codegen.Method)
f := codegen.NewCommentedFunction(
t.PrivatePackage().Path(),
t.extendsFnName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
[]jen.Code{jen.Id("other").Qual(t.PublicPackage().Path(), typeInterfaceName)},
[]jen.Code{jen.Bool()},
impl,
jen.Commentf("%s returns true if the %s type extends from the other type.", t.extendsFnName(), t.TypeName()))
@ -385,7 +385,7 @@ func (t *TypeGenerator) extendsDefinition() (*codegen.Function, *codegen.Method)
t.PrivatePackage().Path(),
extendingMethod,
t.TypeName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
[]jen.Code{jen.Id("other").Qual(t.PublicPackage().Path(), typeInterfaceName)},
[]jen.Code{jen.Bool()},
[]jen.Code{
jen.Return(
@ -433,7 +433,7 @@ func (t *TypeGenerator) extendedByDefinition() *codegen.Function {
return codegen.NewCommentedFunction(
t.PrivatePackage().Path(),
t.extendedByFnName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
[]jen.Code{jen.Id("other").Qual(t.PublicPackage().Path(), typeInterfaceName)},
[]jen.Code{jen.Bool()},
impl,
jen.Commentf("%s returns true if the other provided type extends from the %s type.", t.extendedByFnName(), t.TypeName()))
@ -482,7 +482,7 @@ func (t *TypeGenerator) disjointWithDefinition() *codegen.Function {
return codegen.NewCommentedFunction(
t.PrivatePackage().Path(),
t.disjointWithFnName(),
[]jen.Code{jen.Id("other").Id(typeInterfaceName)},
[]jen.Code{jen.Id("other").Qual(t.PublicPackage().Path(), typeInterfaceName)},
[]jen.Code{jen.Bool()},
impl,
jen.Commentf("%s returns true if the other provided type is disjoint with the %s type.", t.disjointWithFnName(), t.TypeName()))
@ -681,3 +681,12 @@ implementation, but routine ActivityPub applications should not use this to bypa
code generation tool.`, getUnknownMethod, t.TypeName()))
return
}
// getAllManagerMethods returns all the manager methods used by this type.
func (t *TypeGenerator) getAllManagerMethods() (m []*codegen.Method) {
for _, prop := range t.allProperties() {
deserMethod := t.m.getDeserializationMethodForProperty(prop)
m = append(m, deserMethod)
}
return m
}