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.
このコミットが含まれているのは:
コミット
58e3d21e19
|
@ -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
|
||||
}
|
||||
|
|
読み込み中…
新しいイシューから参照