Generate generic ToType function.

このコミットが含まれているのは:
Cory Slep 2019-02-15 22:47:59 +01:00
コミット 272d7239f3
9個のファイルの変更259行の追加270行の削除

ファイルの表示

@ -1103,7 +1103,7 @@ func (c *Converter) propertyPackageFiles(pg *gen.PropertyGenerator, vocabName st
// resolverFiles creates the files necessary for the resolvers.
func (c *Converter) resolverFiles(pkg gen.Package, manGen *gen.ManagerGenerator, root vocabulary) (files []*File, e error) {
rg := gen.NewResolverGenerator(root.allTypeArray(), manGen, pkg)
jsonRes, typeRes, typePredRes, errDefs, isUnFn, iFaces := rg.Definition()
jsonRes, typeRes, typePredRes, errDefs, fns, iFaces := rg.Definition()
// Utils
file := jen.NewFilePath(pkg.Path())
for _, errDef := range errDefs {
@ -1112,7 +1112,9 @@ func (c *Converter) resolverFiles(pkg gen.Package, manGen *gen.ManagerGenerator,
for _, iFace := range iFaces {
file.Add(iFace.Definition()).Line()
}
file.Add(isUnFn.Definition())
for _, fn := range fns {
file.Add(fn.Definition()).Line()
}
files = append(files, &File{
F: file,
FileName: "gen_resolver_utils.go",

ファイルの表示

@ -44,7 +44,7 @@ type ResolverGenerator struct {
cachedErrPredicateUnmatched jen.Code
cachedErrCannotTypeAssert jen.Code
cachedErrCannotTypeAssertPredicate jen.Code
cachedIsUnFn *codegen.Function
cachedFns []*codegen.Function
cachedASInterface *codegen.Interface
cachedResolverInterface *codegen.Interface
}
@ -67,7 +67,7 @@ func NewResolverGenerator(
// Definition returns the TypeResolver and PredicateTypeResolver.
//
// This function signature is pure garbage and yet I keep heaping it on.
func (r *ResolverGenerator) Definition() (jsonRes, typeRes, typePredRes *codegen.Struct, errs []jen.Code, isUnFn *codegen.Function, iFaces []*codegen.Interface) {
func (r *ResolverGenerator) Definition() (jsonRes, typeRes, typePredRes *codegen.Struct, errs []jen.Code, fns []*codegen.Function, iFaces []*codegen.Interface) {
r.cacheOnce.Do(func() {
r.cachedJSON = codegen.NewStruct(
fmt.Sprintf("%s resolves a JSON-deserialized map into "+
@ -139,7 +139,7 @@ func (r *ResolverGenerator) Definition() (jsonRes, typeRes, typePredRes *codegen
r.cachedErrPredicateUnmatched = r.errorPredicateUnmatched()
r.cachedErrCannotTypeAssert = r.errorCannotTypeAssert()
r.cachedErrCannotTypeAssertPredicate = r.errorCannotTypeAssertPredicate()
r.cachedIsUnFn = r.isUnFn()
r.cachedFns = r.fns()
r.cachedASInterface = r.asInterface()
r.cachedResolverInterface = r.resolverInterface()
})
@ -149,7 +149,7 @@ func (r *ResolverGenerator) Definition() (jsonRes, typeRes, typePredRes *codegen
r.cachedErrPredicateUnmatched,
r.cachedErrCannotTypeAssert,
r.cachedErrCannotTypeAssertPredicate,
}, r.cachedIsUnFn, []*codegen.Interface{
}, r.cachedFns, []*codegen.Interface{
r.cachedASInterface,
r.cachedResolverInterface,
}
@ -205,28 +205,75 @@ func (r *ResolverGenerator) errorPredicateUnmatched() jen.Code {
).Line().Var().Id(errorPredicateUnmatched).Error().Op("=").Qual("errors", "New").Call(jen.Lit("activity stream did not match type demanded by predicate"))
}
// isUnFn returns a function that returns true if an error is one dealing with
// Unmatched or Unhandled errors.
func (r *ResolverGenerator) isUnFn() *codegen.Function {
return codegen.NewCommentedFunction(
r.pkg.Path(),
isUnFnName,
[]jen.Code{
jen.Err().Error(),
},
[]jen.Code{
jen.Bool(),
},
[]jen.Code{
jen.Return(
jen.Err().Op("==").Id(errorPredicateUnmatched).Op(
"||",
).Err().Op("==").Id(errorUnhandled).Op(
"||",
).Err().Op("==").Id(errorNoMatch),
),
},
fmt.Sprintf("%s is true when the error indicates that a Resolver was unsuccessful due to the ActivityStreams value not matching its callbacks or predicates.", isUnFnName))
// fns returns all utility functions.
func (r *ResolverGenerator) fns() []*codegen.Function {
allTypeFns := make([]jen.Code, 0)
for _, t := range r.types {
allTypeFns = append(allTypeFns, jen.Func().Params(
jen.Id("ctx").Qual("context", "Context"),
jen.Id("i").Qual(t.PublicPackage().Path(), t.InterfaceName()),
).Error().Block(
jen.Id("t").Op("=").Id("i"),
jen.Return(jen.Nil()),
))
}
return []*codegen.Function{
codegen.NewCommentedFunction(
r.pkg.Path(),
isUnFnName,
[]jen.Code{
jen.Err().Error(),
},
[]jen.Code{
jen.Bool(),
},
[]jen.Code{
jen.Return(
jen.Err().Op("==").Id(errorPredicateUnmatched).Op(
"||",
).Err().Op("==").Id(errorUnhandled).Op(
"||",
).Err().Op("==").Id(errorNoMatch),
),
},
fmt.Sprintf("%s is true when the error indicates that a Resolver was unsuccessful due to the ActivityStreams value not matching its callbacks or predicates.", isUnFnName)),
codegen.NewCommentedFunction(
r.types[0].PublicPackage().Path(),
fmt.Sprintf("To%s", typeInterfaceName),
[]jen.Code{
jen.Id("c").Qual("context", "Context"),
jen.Id("m").Map(jen.String()).Interface(),
},
[]jen.Code{
jen.Id("t").Qual(r.types[0].PublicPackage().Path(), typeInterfaceName),
jen.Err().Error(),
},
[]jen.Code{
jen.Var().Id("r").Op("*").Qual(r.pkg.Path(), jsonResolverStructName),
jen.List(
jen.Id("r"),
jen.Err(),
).Op("=").Qual(
r.pkg.Path(),
fmt.Sprintf("%s%s", constructorName, jsonResolverStructName),
).Call(
jen.List(
allTypeFns...,
),
),
jen.If(
jen.Err().Op("!=").Nil(),
).Block(
jen.Return(),
),
jen.Err().Op("=").Id("r").Dot(resolveMethod).Call(
jen.Id("c"),
jen.Id("m"),
),
jen.Return(),
},
fmt.Sprintf("To%s attempts to resolve the generic JSON map into a Type.", typeInterfaceName)),
}
}
// jsonResolverMethods returns the methods for the TypeResolver.

ファイルの表示

@ -171,7 +171,7 @@ func (b *baseActor) PostInbox(c context.Context, w http.ResponseWriter, r *http.
if err = json.Unmarshal(raw, &m); err != nil {
return true, err
}
asValue, err := toType(c, m)
asValue, err := streams.ToType(c, m)
if err != nil && !streams.IsUnmatchedErr(err) {
return true, err
} else if streams.IsUnmatchedErr(err) {
@ -302,7 +302,7 @@ func (b *baseActor) PostOutbox(c context.Context, w http.ResponseWriter, r *http
// not known to go-fed. This prevents accidentally wrapping an Activity
// type unknown to go-fed in a Create below. Instead,
// streams.ErrUnhandledType will be returned here.
asValue, err := toType(c, m)
asValue, err := streams.ToType(c, m)
if err != nil && !streams.IsUnmatchedErr(err) {
return true, err
} else if streams.IsUnmatchedErr(err) {

ファイルの表示

@ -246,7 +246,7 @@ func (w FederatingWrappedCallbacks) create(c context.Context, a vocab.ActivitySt
if err = json.Unmarshal(b, &m); err != nil {
return err
}
t, err = toType(c, m)
t, err = streams.ToType(c, m)
if err != nil {
return err
}
@ -505,7 +505,7 @@ func (w FederatingWrappedCallbacks) accept(c context.Context, a vocab.ActivitySt
if err = json.Unmarshal(b, &m); err != nil {
return err
}
t, err = toType(c, m)
t, err = streams.ToType(c, m)
if err != nil {
return err
}

ファイルの表示

@ -13,240 +13,6 @@ func IsAnActivityType(value vocab.Type) bool {
return value.GetTypeName() == "Activity" || streams.ActivityStreamsActivityIsExtendedBy(value)
}
// toAsType converts a generic map[string]interface{} into a known Type.
//
// Returns errors under the same conditions as streams.JSONResolver does.
func toType(c context.Context, m map[string]interface{}) (a vocab.Type, e error) {
var r *streams.JSONResolver
// Every time new types are added, need to update this list. It looks
// painful, but in practice VIM macros make it easier to manage.
//
// TODO: Somehow generate this more easily.
r, e = streams.NewJSONResolver(
func(ctx context.Context, i vocab.ActivityStreamsAccept) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsActivity) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsAdd) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsAnnounce) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsApplication) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsArrive) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsArticle) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsAudio) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsBlock) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsCollection) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsCollectionPage) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsCreate) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsDelete) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsDislike) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsDocument) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsEvent) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsFlag) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsFollow) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsGroup) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsIgnore) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsImage) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsIntransitiveActivity) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsInvite) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsJoin) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsLeave) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsLike) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsLink) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsListen) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsMention) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsMove) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsNote) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsObject) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsOffer) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsOrderedCollection) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsOrderedCollectionPage) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsOrganization) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsPage) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsPerson) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsPlace) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsProfile) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsQuestion) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsRead) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsReject) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsRelationship) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsRemove) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsService) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsTentativeAccept) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsTentativeReject) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsTombstone) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsTravel) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsUndo) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsUpdate) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsVideo) error {
a = i
return nil
},
func(ctx context.Context, i vocab.ActivityStreamsView) error {
a = i
return nil
},
)
if e != nil {
return
}
e = r.Resolve(c, m)
return
}
// addToCreate adds the object to the Create activity.
func addToCreate(ctx context.Context, c vocab.ActivityStreamsCreate, o vocab.Type) error {
obj := c.GetActivityStreamsObject()

ファイルの表示

@ -543,7 +543,7 @@ func (a *sideEffectActor) hasInboxForwardingValues(c context.Context, inboxIRI *
if err = json.Unmarshal(b, &m); err != nil {
return false, err
}
t, err := toType(c, m)
t, err := streams.ToType(c, m)
if err != nil {
// Do not fail the entire process if we cannot handle
// the type.
@ -729,7 +729,7 @@ func (a *sideEffectActor) dereferenceForResolvingInboxes(c context.Context, t Tr
if err = json.Unmarshal(resp, &m); err != nil {
return
}
actor, err = toType(c, m)
actor, err = streams.ToType(c, m)
if err != nil {
return
}

ファイルの表示

@ -322,7 +322,7 @@ func (w SocialWrappedCallbacks) update(c context.Context, a vocab.ActivityStream
delete(m, k)
}
}
newT, err := toType(c, m)
newT, err := streams.ToType(c, m)
if err != nil {
return err
}

ファイルの表示

@ -799,7 +799,7 @@ func mustHaveActivityActorsMatchObjectActors(c context.Context,
if err = json.Unmarshal(b, &m); err != nil {
return err
}
t, err = toType(c, m)
t, err = streams.ToType(c, m)
if err != nil {
return err
}

ファイルの表示

@ -3,6 +3,7 @@ package streams
import (
"context"
"errors"
vocab "github.com/go-fed/activity/streams/vocab"
)
// ErrNoCallbackMatch indicates a Resolver could not match the ActivityStreams value to a callback function.
@ -42,3 +43,176 @@ type Resolver interface {
func IsUnmatchedErr(err error) bool {
return err == ErrPredicateUnmatched || err == ErrUnhandledType || err == ErrNoCallbackMatch
}
// ToType attempts to resolve the generic JSON map into a Type.
func ToType(c context.Context, m map[string]interface{}) (t vocab.Type, err error) {
var r *JSONResolver
r, err = NewJSONResolver(func(ctx context.Context, i vocab.ActivityStreamsAccept) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsActivity) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsAdd) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsAnnounce) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsApplication) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsArrive) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsArticle) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsAudio) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsBlock) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsCollection) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsCollectionPage) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsCreate) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsDelete) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsDislike) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsDocument) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsEvent) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsFlag) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsFollow) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsGroup) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsIgnore) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsImage) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsIntransitiveActivity) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsInvite) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsJoin) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsLeave) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsLike) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsLink) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsListen) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsMention) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsMove) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsNote) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsObject) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsOffer) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsOrderedCollection) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsOrderedCollectionPage) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsOrganization) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsPage) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsPerson) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsPlace) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsProfile) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsQuestion) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsRead) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsReject) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsRelationship) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsRemove) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsService) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsTentativeAccept) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsTentativeReject) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsTombstone) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsTravel) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsUndo) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsUpdate) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsVideo) error {
t = i
return nil
}, func(ctx context.Context, i vocab.ActivityStreamsView) error {
t = i
return nil
})
if err != nil {
return
}
err = r.Resolve(c, m)
return
}