Code generate all kind of resolvers.
このコミットが含まれているのは:
コミット
929831f6e2
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
interfacePkg = "vocab"
|
interfacePkg = "vocab"
|
||||||
|
resolverPkg = "resolver"
|
||||||
)
|
)
|
||||||
|
|
||||||
// File is a code-generated file.
|
// File is a code-generated file.
|
||||||
|
@ -362,6 +363,12 @@ func (c Converter) convertToFiles(v vocabulary) (f []*File, e error) {
|
||||||
FileName: "gen_doc.go",
|
FileName: "gen_doc.go",
|
||||||
Directory: pub.WriteDir(),
|
Directory: pub.WriteDir(),
|
||||||
})
|
})
|
||||||
|
// Resolvers
|
||||||
|
files, e = c.resolverFiles(c.GenRoot.Sub(resolverPkg).PublicPackage(), v)
|
||||||
|
if e != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f = append(f, files...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1078,6 +1085,59 @@ func (c Converter) propertyPackageFiles(pg *gen.PropertyGenerator, vocabName str
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolverFiles creates the files necessary for the resolvers.
|
||||||
|
func (c Converter) resolverFiles(pkg gen.Package, root vocabulary) (files []*File, e error) {
|
||||||
|
rg := gen.NewResolverGenerator(root.allTypeArray(), pkg)
|
||||||
|
typeRes, intRes, typePredRes, intPredRes, errDefs, isUnFn, iFaces := rg.Definition()
|
||||||
|
// Utils
|
||||||
|
file := jen.NewFilePath(pkg.Path())
|
||||||
|
for _, errDef := range errDefs {
|
||||||
|
file.Add(errDef).Line()
|
||||||
|
}
|
||||||
|
for _, iFace := range iFaces {
|
||||||
|
file.Add(iFace.Definition()).Line()
|
||||||
|
}
|
||||||
|
file.Add(isUnFn.Definition())
|
||||||
|
files = append(files, &File{
|
||||||
|
F: file,
|
||||||
|
FileName: "gen_resolver_utils.go",
|
||||||
|
Directory: pkg.WriteDir(),
|
||||||
|
})
|
||||||
|
// Type, not predicated
|
||||||
|
file = jen.NewFilePath(pkg.Path())
|
||||||
|
file.Add(typeRes.Definition())
|
||||||
|
files = append(files, &File{
|
||||||
|
F: file,
|
||||||
|
FileName: "gen_type_resolver.go",
|
||||||
|
Directory: pkg.WriteDir(),
|
||||||
|
})
|
||||||
|
// Interface, not predicated
|
||||||
|
file = jen.NewFilePath(pkg.Path())
|
||||||
|
file.Add(intRes.Definition())
|
||||||
|
files = append(files, &File{
|
||||||
|
F: file,
|
||||||
|
FileName: "gen_interface_resolver.go",
|
||||||
|
Directory: pkg.WriteDir(),
|
||||||
|
})
|
||||||
|
// Type, Predicated
|
||||||
|
file = jen.NewFilePath(pkg.Path())
|
||||||
|
file.Add(typePredRes.Definition())
|
||||||
|
files = append(files, &File{
|
||||||
|
F: file,
|
||||||
|
FileName: "gen_type_predicated_resolver.go",
|
||||||
|
Directory: pkg.WriteDir(),
|
||||||
|
})
|
||||||
|
// Interface, Predicated
|
||||||
|
file = jen.NewFilePath(pkg.Path())
|
||||||
|
file.Add(intPredRes.Definition())
|
||||||
|
files = append(files, &File{
|
||||||
|
F: file,
|
||||||
|
FileName: "gen_interface_predicated_resolver.go",
|
||||||
|
Directory: pkg.WriteDir(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// allExtendsAreIn determines if a VocabularyType's parents are all already
|
// allExtendsAreIn determines if a VocabularyType's parents are all already
|
||||||
// converted to a TypeGenerator.
|
// converted to a TypeGenerator.
|
||||||
func (c Converter) allExtendsAreIn(registry *rdf.RDFRegistry, t rdf.VocabularyType, v map[string]*gen.TypeGenerator, genRefs map[string]*vocabulary) bool {
|
func (c Converter) allExtendsAreIn(registry *rdf.RDFRegistry, t rdf.VocabularyType, v map[string]*gen.TypeGenerator, genRefs map[string]*vocabulary) bool {
|
||||||
|
|
|
@ -8,32 +8,37 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeResolverStructName = "TypeResolver"
|
typeResolverStructName = "TypeResolver"
|
||||||
predicateResolverStructName = "PredicateResolver"
|
interfaceResolverStructName = "InterfaceResolver"
|
||||||
resolveMethod = "Resolve"
|
typePredicatedResolverStructName = "TypePredicatedResolver"
|
||||||
resolveMethodPrivate = "resolve"
|
interfacePredicatedResolverStructName = "InterfacePredicatedResolver"
|
||||||
applyMethod = "Apply"
|
resolveMethod = "Resolve"
|
||||||
activityStreamInterface = "ActivityStreamsInterface"
|
applyMethod = "Apply"
|
||||||
callbackMember = "callbacks"
|
activityStreamInterface = "ActivityStreamsInterface"
|
||||||
predicateMember = "predicate"
|
resolverInterface = "Resolver"
|
||||||
errorNoMatch = "ErrNoCallbackMatch"
|
callbackMember = "callbacks"
|
||||||
errorUnhandled = "ErrUnknownType"
|
predicateMember = "predicate"
|
||||||
errorPredicateUnmatched = "ErrPredicateUnmatched"
|
delegateMember = "delegate"
|
||||||
errorCannotTypeAssert = "errCannotTypeAssertType"
|
errorNoMatch = "ErrNoCallbackMatch"
|
||||||
errorCannotTypeAssertPredicate = "errCannotTypeAssertPredicate"
|
errorUnhandled = "ErrUnknownType"
|
||||||
isUnFnName = "IsUnknownOrUnmatchedErr"
|
errorPredicateUnmatched = "ErrPredicateUnmatched"
|
||||||
|
errorCannotTypeAssert = "errCannotTypeAssertType"
|
||||||
|
errorCannotTypeAssertPredicate = "errCannotTypeAssertPredicate"
|
||||||
|
isUnFnName = "IsUnknownOrUnmatchedErr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Interface-driven resolvers. For hierarchy.
|
// TODO: Interface-driven resolvers. For hierarchy.
|
||||||
|
|
||||||
// ResolverGenerator generates the code required for the TypeResolver and the
|
// ResolverGenerator generates the code required for the TypeResolver and the
|
||||||
// PredicateResolver.
|
// PredicateTypeResolver.
|
||||||
type ResolverGenerator struct {
|
type ResolverGenerator struct {
|
||||||
pkg Package
|
pkg Package
|
||||||
types []*TypeGenerator
|
types []*TypeGenerator
|
||||||
cacheOnce sync.Once
|
cacheOnce sync.Once
|
||||||
cachedPredicate *codegen.Struct
|
cachedTypePredicate *codegen.Struct
|
||||||
|
cachedInterfacePredicate *codegen.Struct
|
||||||
cachedType *codegen.Struct
|
cachedType *codegen.Struct
|
||||||
|
cachedInterface *codegen.Struct
|
||||||
cachedErrNoMatch jen.Code
|
cachedErrNoMatch jen.Code
|
||||||
cachedErrUnhandled jen.Code
|
cachedErrUnhandled jen.Code
|
||||||
cachedErrPredicateUnmatched jen.Code
|
cachedErrPredicateUnmatched jen.Code
|
||||||
|
@ -41,6 +46,7 @@ type ResolverGenerator struct {
|
||||||
cachedErrCannotTypeAssertPredicate jen.Code
|
cachedErrCannotTypeAssertPredicate jen.Code
|
||||||
cachedIsUnFn *codegen.Function
|
cachedIsUnFn *codegen.Function
|
||||||
cachedASInterface *codegen.Interface
|
cachedASInterface *codegen.Interface
|
||||||
|
cachedResolverInterface *codegen.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new ResolverGenerator for generating all the methods, functions,
|
// Creates a new ResolverGenerator for generating all the methods, functions,
|
||||||
|
@ -56,22 +62,36 @@ func NewResolverGenerator(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Definition returns the TypeResolver and PredicateResolver.
|
// Definition returns the TypeResolver and PredicateTypeResolver.
|
||||||
func (r *ResolverGenerator) Definition() (types, predicates *codegen.Struct, errs []jen.Code, isUnFn *codegen.Function, asInterface *codegen.Interface) {
|
func (r *ResolverGenerator) Definition() (typeRes, interfaceRes, typePredRes, interfacePredRes *codegen.Struct, errs []jen.Code, isUnFn *codegen.Function, iFaces []*codegen.Interface) {
|
||||||
r.cacheOnce.Do(func() {
|
r.cacheOnce.Do(func() {
|
||||||
r.cachedType = codegen.NewStruct(
|
r.cachedType = codegen.NewStruct(
|
||||||
// TODO: Comment
|
// TODO: Comment
|
||||||
fmt.Sprintf("", typeResolverStructName),
|
fmt.Sprintf("%s", typeResolverStructName),
|
||||||
typeResolverStructName,
|
typeResolverStructName,
|
||||||
r.typeResolverMethods(),
|
r.typeResolverMethods(),
|
||||||
r.typeResolverFunctions(),
|
r.resolverFunctions(typeResolverStructName),
|
||||||
r.typeResolverMembers())
|
r.resolverMembers())
|
||||||
r.cachedPredicate = codegen.NewStruct(
|
r.cachedInterface = codegen.NewStruct(
|
||||||
// TODO: Comment
|
// TODO: Comment
|
||||||
fmt.Sprintf("", predicateResolverStructName),
|
fmt.Sprintf("%s", interfaceResolverStructName),
|
||||||
predicateResolverStructName,
|
interfaceResolverStructName,
|
||||||
r.predicateResolverMethods(),
|
r.interfaceResolverMethods(),
|
||||||
r.predicateResolverFunctions(),
|
r.resolverFunctions(interfaceResolverStructName),
|
||||||
|
r.resolverMembers())
|
||||||
|
r.cachedTypePredicate = codegen.NewStruct(
|
||||||
|
// TODO: Comment
|
||||||
|
fmt.Sprintf("%s", typePredicatedResolverStructName),
|
||||||
|
typePredicatedResolverStructName,
|
||||||
|
r.typePredicatedResolverMethods(),
|
||||||
|
r.predicateResolverFunctions(typePredicatedResolverStructName),
|
||||||
|
r.predicateResolverMembers())
|
||||||
|
r.cachedInterfacePredicate = codegen.NewStruct(
|
||||||
|
// TODO: Comment
|
||||||
|
fmt.Sprintf("%s", interfacePredicatedResolverStructName),
|
||||||
|
interfacePredicatedResolverStructName,
|
||||||
|
r.interfacePredicatedResolverMethods(),
|
||||||
|
r.predicateResolverFunctions(interfacePredicatedResolverStructName),
|
||||||
r.predicateResolverMembers())
|
r.predicateResolverMembers())
|
||||||
r.cachedErrNoMatch = r.errorNoMatch()
|
r.cachedErrNoMatch = r.errorNoMatch()
|
||||||
r.cachedErrUnhandled = r.errorUnhandled()
|
r.cachedErrUnhandled = r.errorUnhandled()
|
||||||
|
@ -80,14 +100,18 @@ func (r *ResolverGenerator) Definition() (types, predicates *codegen.Struct, err
|
||||||
r.cachedErrCannotTypeAssertPredicate = r.errorCannotTypeAssertPredicate()
|
r.cachedErrCannotTypeAssertPredicate = r.errorCannotTypeAssertPredicate()
|
||||||
r.cachedIsUnFn = r.isUnFn()
|
r.cachedIsUnFn = r.isUnFn()
|
||||||
r.cachedASInterface = r.asInterface()
|
r.cachedASInterface = r.asInterface()
|
||||||
|
r.cachedResolverInterface = r.resolverInterface()
|
||||||
})
|
})
|
||||||
return r.cachedType, r.cachedPredicate, []jen.Code{
|
return r.cachedType, r.cachedInterface, r.cachedTypePredicate, r.cachedInterfacePredicate, []jen.Code{
|
||||||
r.cachedErrNoMatch,
|
r.cachedErrNoMatch,
|
||||||
r.cachedErrUnhandled,
|
r.cachedErrUnhandled,
|
||||||
r.cachedErrPredicateUnmatched,
|
r.cachedErrPredicateUnmatched,
|
||||||
r.cachedErrCannotTypeAssert,
|
r.cachedErrCannotTypeAssert,
|
||||||
r.cachedErrCannotTypeAssertPredicate,
|
r.cachedErrCannotTypeAssertPredicate,
|
||||||
}, r.cachedIsUnFn, r.cachedASInterface
|
}, r.cachedIsUnFn, []*codegen.Interface{
|
||||||
|
r.cachedASInterface,
|
||||||
|
r.cachedResolverInterface,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// errorNoMatch returns the declaration for the ErrNoMatch global value.
|
// errorNoMatch returns the declaration for the ErrNoMatch global value.
|
||||||
|
@ -151,120 +175,6 @@ func (r *ResolverGenerator) isUnFn() *codegen.Function {
|
||||||
|
|
||||||
// typeResolverMethods returns the methods for the TypeResolver.
|
// typeResolverMethods returns the methods for the TypeResolver.
|
||||||
func (r *ResolverGenerator) typeResolverMethods() (m []*codegen.Method) {
|
func (r *ResolverGenerator) typeResolverMethods() (m []*codegen.Method) {
|
||||||
m = append(m, r.resolveMethod(resolveMethod, typeResolverStructName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// predicateResolverMethods returns the methods for the PredicateResolver.
|
|
||||||
func (r *ResolverGenerator) predicateResolverMethods() (m []*codegen.Method) {
|
|
||||||
m = append(m, r.applyMethod())
|
|
||||||
m = append(m, r.resolveMethod(resolveMethodPrivate, predicateResolverStructName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeResolverFunctions returns the functions for the TypeResolver.
|
|
||||||
func (r *ResolverGenerator) typeResolverFunctions() (f []*codegen.Function) {
|
|
||||||
f = append(f, codegen.NewCommentedFunction(
|
|
||||||
r.pkg.Path(),
|
|
||||||
fmt.Sprintf("%s%s", constructorName, typeResolverStructName),
|
|
||||||
[]jen.Code{
|
|
||||||
jen.Id("callbacks").Index().Interface(),
|
|
||||||
},
|
|
||||||
[]jen.Code{
|
|
||||||
jen.Op("*").Id(typeResolverStructName),
|
|
||||||
jen.Error(),
|
|
||||||
},
|
|
||||||
[]jen.Code{
|
|
||||||
jen.For(
|
|
||||||
jen.List(
|
|
||||||
jen.Id("_"),
|
|
||||||
jen.Id("cb"),
|
|
||||||
).Op(":=").Range().Id("callbacks"),
|
|
||||||
).Block(
|
|
||||||
jen.Commentf("Each callback function must satisfy one known function signature, or else we will generate a runtime error instead of silently fail."),
|
|
||||||
jen.Switch(
|
|
||||||
jen.Id("cb").Assert(jen.Type()),
|
|
||||||
).Block(
|
|
||||||
r.mustAssertToKnownTypes("cb"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
jen.Return(
|
|
||||||
jen.Op("&").Id(typeResolverStructName).Values(
|
|
||||||
jen.Dict{
|
|
||||||
jen.Id(callbackMember): jen.Id("callbacks"),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
jen.Nil(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
// TODO: Comment
|
|
||||||
fmt.Sprintf("%s%s", constructorName, typeResolverStructName)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// predicateResolverFunctions returns the functions for the PredicateResolver.
|
|
||||||
func (r *ResolverGenerator) predicateResolverFunctions() (f []*codegen.Function) {
|
|
||||||
f = append(f, codegen.NewCommentedFunction(
|
|
||||||
r.pkg.Path(),
|
|
||||||
fmt.Sprintf("%s%s", constructorName, predicateResolverStructName),
|
|
||||||
[]jen.Code{
|
|
||||||
jen.Id("callbacks").Index().Interface(),
|
|
||||||
jen.Id("predicate").Interface(),
|
|
||||||
},
|
|
||||||
[]jen.Code{
|
|
||||||
jen.Op("*").Id(predicateResolverStructName),
|
|
||||||
jen.Error(),
|
|
||||||
},
|
|
||||||
[]jen.Code{
|
|
||||||
jen.For(
|
|
||||||
jen.List(
|
|
||||||
jen.Id("_"),
|
|
||||||
jen.Id("cb"),
|
|
||||||
).Op(":=").Range().Id("callbacks"),
|
|
||||||
).Block(
|
|
||||||
jen.Commentf("Each callback function must satisfy one known function signature, or else we will generate a runtime error instead of silently fail."),
|
|
||||||
jen.Switch(
|
|
||||||
jen.Id("cb").Assert(jen.Type()),
|
|
||||||
).Block(
|
|
||||||
r.mustAssertToKnownTypes("cb"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
jen.Commentf("The predicate must satisfy one known predicate function signature, or else we will generate a runtime error instead of silently fail."),
|
|
||||||
jen.Switch(
|
|
||||||
jen.Id("predicate").Assert(jen.Type()),
|
|
||||||
).Block(
|
|
||||||
r.mustAssertToKnownPredicate("predicate"),
|
|
||||||
),
|
|
||||||
jen.Return(
|
|
||||||
jen.Op("&").Id(typeResolverStructName).Values(
|
|
||||||
jen.Dict{
|
|
||||||
jen.Id(callbackMember): jen.Id("callbacks"),
|
|
||||||
jen.Id(predicateMember): jen.Id("predicate"),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
jen.Nil(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
// TODO: Comment
|
|
||||||
fmt.Sprintf("%s%s", constructorName, predicateResolverStructName)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeResolverMembers returns the members for the TypeResolver.
|
|
||||||
func (r *ResolverGenerator) typeResolverMembers() (m []jen.Code) {
|
|
||||||
m = append(m, jen.Id(callbackMember).Index().Interface())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// predicateResolverMembers returns the members for the PredicateResolver.
|
|
||||||
func (r *ResolverGenerator) predicateResolverMembers() (m []jen.Code) {
|
|
||||||
m = append(m, jen.Id(callbackMember).Index().Interface())
|
|
||||||
m = append(m, jen.Id(predicateMember).Interface())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolveMethod returns the Resolve method.
|
|
||||||
func (r *ResolverGenerator) resolveMethod(name, structName string) *codegen.Method {
|
|
||||||
impl := jen.Empty()
|
impl := jen.Empty()
|
||||||
for _, t := range r.types {
|
for _, t := range r.types {
|
||||||
impl = impl.Case(
|
impl = impl.Case(
|
||||||
|
@ -305,10 +215,10 @@ func (r *ResolverGenerator) resolveMethod(name, structName string) *codegen.Meth
|
||||||
),
|
),
|
||||||
).Line()
|
).Line()
|
||||||
}
|
}
|
||||||
return codegen.NewCommentedValueMethod(
|
m = append(m, codegen.NewCommentedValueMethod(
|
||||||
r.pkg.Path(),
|
r.pkg.Path(),
|
||||||
name,
|
resolveMethod,
|
||||||
structName,
|
typeResolverStructName,
|
||||||
[]jen.Code{
|
[]jen.Code{
|
||||||
jen.Id("ctx").Qual("context", "Context"),
|
jen.Id("ctx").Qual("context", "Context"),
|
||||||
jen.Id("o").Id(activityStreamInterface),
|
jen.Id("o").Id(activityStreamInterface),
|
||||||
|
@ -321,7 +231,7 @@ func (r *ResolverGenerator) resolveMethod(name, structName string) *codegen.Meth
|
||||||
jen.List(
|
jen.List(
|
||||||
jen.Id("_"),
|
jen.Id("_"),
|
||||||
jen.Id("i"),
|
jen.Id("i"),
|
||||||
).Op(":=").Range().Id(codegen.This()).Id(callbackMember),
|
).Op(":=").Range().Id(codegen.This()).Dot(callbackMember),
|
||||||
).Block(
|
).Block(
|
||||||
jen.Switch(jen.Id("o").Dot(typeNameMethod).Call()).Block(
|
jen.Switch(jen.Id("o").Dot(typeNameMethod).Call()).Block(
|
||||||
impl.Default().Block(
|
impl.Default().Block(
|
||||||
|
@ -336,37 +246,182 @@ func (r *ResolverGenerator) resolveMethod(name, structName string) *codegen.Meth
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
// TODO: Comment
|
// TODO: Comment
|
||||||
fmt.Sprintf("", resolveMethod))
|
fmt.Sprintf("%s", resolveMethod)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// mustAssertToKnownTypes creates the type assertion switch statement that will
|
// interfaceResolverMethods returns the methods for the TypeResolver.
|
||||||
// return an error if the parameter named does not match any of the expected
|
func (r *ResolverGenerator) interfaceResolverMethods() (m []*codegen.Method) {
|
||||||
// function signatures.
|
impl := jen.Empty()
|
||||||
func (r *ResolverGenerator) mustAssertToKnownTypes(paramName string) jen.Code {
|
|
||||||
c := jen.Empty()
|
|
||||||
for _, t := range r.types {
|
for _, t := range r.types {
|
||||||
c = c.Case(
|
impl = impl.If(
|
||||||
jen.Func().Parens(
|
jen.List(
|
||||||
jen.List(
|
jen.Id("v"),
|
||||||
jen.Qual("context", "Context"),
|
jen.Id("ok"),
|
||||||
jen.Qual(t.PublicPackage().Path(), t.InterfaceName()),
|
).Op(":=").Id("o").Assert(
|
||||||
),
|
jen.Qual(t.PublicPackage().Path(), t.InterfaceName()),
|
||||||
).Error(),
|
),
|
||||||
|
jen.Id("ok"),
|
||||||
).Block(
|
).Block(
|
||||||
jen.Commentf("Do nothing, this callback has a correct signature."),
|
jen.If(
|
||||||
|
jen.List(
|
||||||
|
jen.Id("fn"),
|
||||||
|
jen.Id("ok"),
|
||||||
|
).Op(":=").Id("i").Assert(
|
||||||
|
jen.Func().Parens(
|
||||||
|
jen.List(
|
||||||
|
jen.Qual("context", "Context"),
|
||||||
|
jen.Qual(t.PublicPackage().Path(), t.InterfaceName()),
|
||||||
|
),
|
||||||
|
).Error(),
|
||||||
|
),
|
||||||
|
jen.Id("ok"),
|
||||||
|
).Block(
|
||||||
|
jen.Return(
|
||||||
|
jen.Id("fn").Call(jen.Id("ctx"), jen.Id("v")),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
jen.Commentf("Else: this callback function doesn't support this duck-typed interface."),
|
||||||
).Line()
|
).Line()
|
||||||
}
|
}
|
||||||
c = c.Default().Block(
|
m = append(m, codegen.NewCommentedValueMethod(
|
||||||
jen.Return(
|
r.pkg.Path(),
|
||||||
jen.Nil(),
|
resolveMethod,
|
||||||
jen.Qual("errors", "New").Call(jen.Lit("a callback function is of the wrong signature and would never be called")),
|
interfaceResolverStructName,
|
||||||
),
|
[]jen.Code{
|
||||||
)
|
jen.Id("ctx").Qual("context", "Context"),
|
||||||
return c
|
jen.Id("o").Id(activityStreamInterface),
|
||||||
|
},
|
||||||
|
[]jen.Code{
|
||||||
|
jen.Error(),
|
||||||
|
},
|
||||||
|
[]jen.Code{
|
||||||
|
jen.For(
|
||||||
|
jen.List(
|
||||||
|
jen.Id("_"),
|
||||||
|
jen.Id("i"),
|
||||||
|
).Op(":=").Range().Id(codegen.This()).Dot(callbackMember),
|
||||||
|
).Block(
|
||||||
|
impl,
|
||||||
|
),
|
||||||
|
jen.Return(
|
||||||
|
jen.Id(errorNoMatch),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
// TODO: Comment
|
||||||
|
fmt.Sprintf("%s", resolveMethod)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyMethod generates the code required for the Apply method.
|
// typePredicatedResolverMethods returns the methods for the TypePredicatedResolver.
|
||||||
func (r *ResolverGenerator) applyMethod() *codegen.Method {
|
func (r *ResolverGenerator) typePredicatedResolverMethods() (m []*codegen.Method) {
|
||||||
|
impl := jen.Empty()
|
||||||
|
for _, t := range r.types {
|
||||||
|
impl = impl.Case(
|
||||||
|
jen.Lit(t.TypeName()),
|
||||||
|
).Block(
|
||||||
|
jen.If(
|
||||||
|
jen.List(
|
||||||
|
jen.Id("fn"),
|
||||||
|
jen.Id("ok"),
|
||||||
|
).Op(":=").Id(codegen.This()).Dot(predicateMember).Assert(
|
||||||
|
jen.Func().Parens(
|
||||||
|
jen.List(
|
||||||
|
jen.Qual("context", "Context"),
|
||||||
|
jen.Qual(t.PublicPackage().Path(), t.InterfaceName()),
|
||||||
|
),
|
||||||
|
).Parens(
|
||||||
|
jen.List(
|
||||||
|
jen.Bool(),
|
||||||
|
jen.Error(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
jen.Id("ok"),
|
||||||
|
).Block(
|
||||||
|
jen.If(
|
||||||
|
jen.List(
|
||||||
|
jen.Id("v"),
|
||||||
|
jen.Id("ok"),
|
||||||
|
).Op(":=").Id("o").Assert(
|
||||||
|
jen.Qual(t.PublicPackage().Path(), t.InterfaceName()),
|
||||||
|
),
|
||||||
|
jen.Id("ok"),
|
||||||
|
).Block(
|
||||||
|
jen.List(
|
||||||
|
jen.Id("predicatePasses"),
|
||||||
|
jen.Err(),
|
||||||
|
).Op("=").Id("fn").Call(jen.Id("ctx"), jen.Id("v")),
|
||||||
|
).Else().Block(
|
||||||
|
jen.Commentf("This occurs when the implementation is either not a go-fed type and is improperly satisfying various interfaces, or there is a bug in the go-fed generated code."),
|
||||||
|
jen.Return(
|
||||||
|
jen.False(),
|
||||||
|
jen.Id(errorCannotTypeAssert),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).Else().Block(
|
||||||
|
jen.Return(
|
||||||
|
jen.False(),
|
||||||
|
jen.Id(errorPredicateUnmatched),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).Line()
|
||||||
|
}
|
||||||
|
m = append(m, codegen.NewCommentedValueMethod(
|
||||||
|
r.pkg.Path(),
|
||||||
|
applyMethod,
|
||||||
|
typePredicatedResolverStructName,
|
||||||
|
[]jen.Code{
|
||||||
|
jen.Id("ctx").Qual("context", "Context"),
|
||||||
|
jen.Id("o").Id(activityStreamInterface),
|
||||||
|
},
|
||||||
|
[]jen.Code{
|
||||||
|
jen.Bool(),
|
||||||
|
jen.Error(),
|
||||||
|
},
|
||||||
|
[]jen.Code{
|
||||||
|
jen.Var().Id("predicatePasses").Bool(),
|
||||||
|
jen.Var().Err().Error(),
|
||||||
|
jen.Switch(jen.Id("o").Dot(typeNameMethod).Call()).Block(
|
||||||
|
impl.Default().Block(
|
||||||
|
jen.Return(
|
||||||
|
jen.False(),
|
||||||
|
jen.Id(errorUnhandled),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
jen.If(
|
||||||
|
jen.Err().Op("!=").Nil(),
|
||||||
|
).Block(
|
||||||
|
jen.Return(
|
||||||
|
jen.Id("predicatePasses"),
|
||||||
|
jen.Err(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
jen.If(
|
||||||
|
jen.Id("predicatePasses"),
|
||||||
|
).Block(
|
||||||
|
jen.Return(
|
||||||
|
jen.True(),
|
||||||
|
jen.Id(codegen.This()).Dot(delegateMember).Dot(resolveMethod).Call(
|
||||||
|
jen.Id("ctx"),
|
||||||
|
jen.Id("o"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).Else().Block(
|
||||||
|
jen.Return(
|
||||||
|
jen.False(),
|
||||||
|
jen.Nil(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
// TODO: Comment
|
||||||
|
fmt.Sprintf("%s", applyMethod)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// interfacePredicatedResolverMethods returns the methods for the PredicateTypeResolver.
|
||||||
|
func (r *ResolverGenerator) interfacePredicatedResolverMethods() (m []*codegen.Method) {
|
||||||
impl := jen.Empty()
|
impl := jen.Empty()
|
||||||
for _, t := range r.types {
|
for _, t := range r.types {
|
||||||
impl = impl.Case(
|
impl = impl.Case(
|
||||||
|
@ -403,10 +458,10 @@ func (r *ResolverGenerator) applyMethod() *codegen.Method {
|
||||||
),
|
),
|
||||||
).Line()
|
).Line()
|
||||||
}
|
}
|
||||||
return codegen.NewCommentedValueMethod(
|
m = append(m, codegen.NewCommentedValueMethod(
|
||||||
r.pkg.Path(),
|
r.pkg.Path(),
|
||||||
applyMethod,
|
applyMethod,
|
||||||
predicateResolverStructName,
|
interfacePredicatedResolverStructName,
|
||||||
[]jen.Code{
|
[]jen.Code{
|
||||||
jen.Id("ctx").Qual("context", "Context"),
|
jen.Id("ctx").Qual("context", "Context"),
|
||||||
jen.Id("o").Id(activityStreamInterface),
|
jen.Id("o").Id(activityStreamInterface),
|
||||||
|
@ -427,12 +482,20 @@ func (r *ResolverGenerator) applyMethod() *codegen.Method {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
jen.If(
|
||||||
|
jen.Err().Op("!=").Nil(),
|
||||||
|
).Block(
|
||||||
|
jen.Return(
|
||||||
|
jen.Id("predicatePasses"),
|
||||||
|
jen.Err(),
|
||||||
|
),
|
||||||
|
),
|
||||||
jen.If(
|
jen.If(
|
||||||
jen.Id("predicatePasses"),
|
jen.Id("predicatePasses"),
|
||||||
).Block(
|
).Block(
|
||||||
jen.Return(
|
jen.Return(
|
||||||
jen.True(),
|
jen.True(),
|
||||||
jen.Id(codegen.This()).Dot(resolveMethodPrivate).Call(
|
jen.Id(codegen.This()).Dot(delegateMember).Dot(resolveMethod).Call(
|
||||||
jen.Id("ctx"),
|
jen.Id("ctx"),
|
||||||
jen.Id("o"),
|
jen.Id("o"),
|
||||||
),
|
),
|
||||||
|
@ -445,7 +508,122 @@ func (r *ResolverGenerator) applyMethod() *codegen.Method {
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
// TODO: Comment
|
// TODO: Comment
|
||||||
fmt.Sprintf("%s", applyMethod))
|
fmt.Sprintf("%s", applyMethod)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolverFunctions returns the functions for the TypeResolver.
|
||||||
|
func (r *ResolverGenerator) resolverFunctions(name string) (f []*codegen.Function) {
|
||||||
|
f = append(f, codegen.NewCommentedFunction(
|
||||||
|
r.pkg.Path(),
|
||||||
|
fmt.Sprintf("%s%s", constructorName, name),
|
||||||
|
[]jen.Code{
|
||||||
|
jen.Id("callbacks").Index().Interface(),
|
||||||
|
},
|
||||||
|
[]jen.Code{
|
||||||
|
jen.Op("*").Id(name),
|
||||||
|
jen.Error(),
|
||||||
|
},
|
||||||
|
[]jen.Code{
|
||||||
|
jen.For(
|
||||||
|
jen.List(
|
||||||
|
jen.Id("_"),
|
||||||
|
jen.Id("cb"),
|
||||||
|
).Op(":=").Range().Id("callbacks"),
|
||||||
|
).Block(
|
||||||
|
jen.Commentf("Each callback function must satisfy one known function signature, or else we will generate a runtime error instead of silently fail."),
|
||||||
|
jen.Switch(
|
||||||
|
jen.Id("cb").Assert(jen.Type()),
|
||||||
|
).Block(
|
||||||
|
r.mustAssertToKnownTypes("cb"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
jen.Return(
|
||||||
|
jen.Op("&").Id(name).Values(
|
||||||
|
jen.Dict{
|
||||||
|
jen.Id(callbackMember): jen.Id("callbacks"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
jen.Nil(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
// TODO: Comment
|
||||||
|
fmt.Sprintf("%s%s", constructorName, name)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// predicateResolverFunctions returns the functions for the PredicateTypeResolver.
|
||||||
|
func (r *ResolverGenerator) predicateResolverFunctions(name string) (f []*codegen.Function) {
|
||||||
|
f = append(f, codegen.NewCommentedFunction(
|
||||||
|
r.pkg.Path(),
|
||||||
|
fmt.Sprintf("%s%s", constructorName, name),
|
||||||
|
[]jen.Code{
|
||||||
|
jen.Id("delegate").Id(resolverInterface),
|
||||||
|
jen.Id("predicate").Interface(),
|
||||||
|
},
|
||||||
|
[]jen.Code{
|
||||||
|
jen.Op("*").Id(name),
|
||||||
|
jen.Error(),
|
||||||
|
},
|
||||||
|
[]jen.Code{
|
||||||
|
jen.Commentf("The predicate must satisfy one known predicate function signature, or else we will generate a runtime error instead of silently fail."),
|
||||||
|
jen.Switch(
|
||||||
|
jen.Id("predicate").Assert(jen.Type()),
|
||||||
|
).Block(
|
||||||
|
r.mustAssertToKnownPredicate("predicate"),
|
||||||
|
),
|
||||||
|
jen.Return(
|
||||||
|
jen.Op("&").Id(name).Values(
|
||||||
|
jen.Dict{
|
||||||
|
jen.Id(delegateMember): jen.Id("delegate"),
|
||||||
|
jen.Id(predicateMember): jen.Id("predicate"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
jen.Nil(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
// TODO: Comment
|
||||||
|
fmt.Sprintf("%s%s", constructorName, name)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolverMembers returns the members for the TypeResolver.
|
||||||
|
func (r *ResolverGenerator) resolverMembers() (m []jen.Code) {
|
||||||
|
m = append(m, jen.Id(callbackMember).Index().Interface())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// predicateResolverMembers returns the members for the PredicateTypResolver.
|
||||||
|
func (r *ResolverGenerator) predicateResolverMembers() (m []jen.Code) {
|
||||||
|
m = append(m, jen.Id(delegateMember).Id(resolverInterface))
|
||||||
|
m = append(m, jen.Id(predicateMember).Interface())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustAssertToKnownTypes creates the type assertion switch statement that will
|
||||||
|
// return an error if the parameter named does not match any of the expected
|
||||||
|
// function signatures.
|
||||||
|
func (r *ResolverGenerator) mustAssertToKnownTypes(paramName string) jen.Code {
|
||||||
|
c := jen.Empty()
|
||||||
|
for _, t := range r.types {
|
||||||
|
c = c.Case(
|
||||||
|
jen.Func().Parens(
|
||||||
|
jen.List(
|
||||||
|
jen.Qual("context", "Context"),
|
||||||
|
jen.Qual(t.PublicPackage().Path(), t.InterfaceName()),
|
||||||
|
),
|
||||||
|
).Error(),
|
||||||
|
).Block(
|
||||||
|
jen.Commentf("Do nothing, this callback has a correct signature."),
|
||||||
|
).Line()
|
||||||
|
}
|
||||||
|
c = c.Default().Block(
|
||||||
|
jen.Return(
|
||||||
|
jen.Nil(),
|
||||||
|
jen.Qual("errors", "New").Call(jen.Lit("a callback function is of the wrong signature and would never be called")),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// mustAssertToKnownPredicate ensures the parameter name types-asserts to a
|
// mustAssertToKnownPredicate ensures the parameter name types-asserts to a
|
||||||
|
@ -495,3 +673,26 @@ func (r *ResolverGenerator) asInterface() *codegen.Interface {
|
||||||
// TODO: Comment
|
// TODO: Comment
|
||||||
fmt.Sprintf("%s", activityStreamInterface))
|
fmt.Sprintf("%s", activityStreamInterface))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolverInterface returns the Resolver interface.
|
||||||
|
func (r *ResolverGenerator) resolverInterface() *codegen.Interface {
|
||||||
|
return codegen.NewInterface(
|
||||||
|
r.pkg.Path(),
|
||||||
|
resolverInterface,
|
||||||
|
[]codegen.FunctionSignature{
|
||||||
|
{
|
||||||
|
Name: resolveMethod,
|
||||||
|
Params: []jen.Code{
|
||||||
|
jen.Id("ctx").Qual("context", "Context"),
|
||||||
|
jen.Id("o").Id(activityStreamInterface),
|
||||||
|
},
|
||||||
|
Ret: []jen.Code{
|
||||||
|
jen.Error(),
|
||||||
|
},
|
||||||
|
// TODO: Comment
|
||||||
|
Comment: fmt.Sprintf("%s", resolveMethod),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
//TODO: Comment
|
||||||
|
fmt.Sprintf("%s", resolverInterface))
|
||||||
|
}
|
||||||
|
|
読み込み中…
新しいイシューから参照