refactor(container)!: rename Scope -> ModuleKey (#11073)
## Description This renames `container.Scope` to `container.ModuleKey` to make it more consistent with the usage of scope for modules. It also renames all usages of `constructor` (in docs and variable name) to `provider` for consistency. --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
This commit is contained in:
parent
7baa4f3e05
commit
24c97d529f
@ -14,7 +14,7 @@ type container struct {
|
||||
|
||||
resolvers map[reflect.Type]resolver
|
||||
|
||||
scopes map[string]Scope
|
||||
moduleKeys map[string]*moduleKey
|
||||
|
||||
resolveStack []resolveFrame
|
||||
callerStack []Location
|
||||
@ -30,15 +30,15 @@ func newContainer(cfg *debugConfig) *container {
|
||||
return &container{
|
||||
debugConfig: cfg,
|
||||
resolvers: map[reflect.Type]resolver{},
|
||||
scopes: map[string]Scope{},
|
||||
moduleKeys: map[string]*moduleKey{},
|
||||
callerStack: nil,
|
||||
callerMap: map[Location]bool{},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *container) call(constructor *ProviderDescriptor, scope Scope) ([]reflect.Value, error) {
|
||||
loc := constructor.Location
|
||||
graphNode, err := c.locationGraphNode(loc, scope)
|
||||
func (c *container) call(provider *ProviderDescriptor, moduleKey *moduleKey) ([]reflect.Value, error) {
|
||||
loc := provider.Location
|
||||
graphNode, err := c.locationGraphNode(loc, moduleKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -53,9 +53,9 @@ func (c *container) call(constructor *ProviderDescriptor, scope Scope) ([]reflec
|
||||
|
||||
c.logf("Resolving dependencies for %s", loc)
|
||||
c.indentLogger()
|
||||
inVals := make([]reflect.Value, len(constructor.Inputs))
|
||||
for i, in := range constructor.Inputs {
|
||||
val, err := c.resolve(in, scope, loc)
|
||||
inVals := make([]reflect.Value, len(provider.Inputs))
|
||||
for i, in := range provider.Inputs {
|
||||
val, err := c.resolve(in, moduleKey, loc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -67,9 +67,9 @@ func (c *container) call(constructor *ProviderDescriptor, scope Scope) ([]reflec
|
||||
delete(c.callerMap, loc)
|
||||
c.callerStack = c.callerStack[0 : len(c.callerStack)-1]
|
||||
|
||||
out, err := constructor.Fn(inVals)
|
||||
out, err := provider.Fn(inVals)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error calling constructor %s", loc)
|
||||
return nil, errors.Wrapf(err, "error calling provider %s", loc)
|
||||
}
|
||||
|
||||
markGraphNodeAsUsed(graphNode)
|
||||
@ -83,7 +83,7 @@ func (c *container) getResolver(typ reflect.Type) (resolver, error) {
|
||||
}
|
||||
|
||||
elemType := typ
|
||||
if isAutoGroupSliceType(elemType) || isOnePerScopeMapType(elemType) {
|
||||
if isAutoGroupSliceType(elemType) || isOnePerModuleMapType(elemType) {
|
||||
elemType = elemType.Elem()
|
||||
}
|
||||
|
||||
@ -108,48 +108,48 @@ func (c *container) getResolver(typ reflect.Type) (resolver, error) {
|
||||
|
||||
c.resolvers[elemType] = r
|
||||
c.resolvers[sliceType] = &sliceGroupResolver{r}
|
||||
} else if isOnePerScopeType(elemType) {
|
||||
c.logf("Registering resolver for one-per-scope type %v", elemType)
|
||||
} else if isOnePerModuleType(elemType) {
|
||||
c.logf("Registering resolver for one-per-module type %v", elemType)
|
||||
mapType := reflect.MapOf(stringType, elemType)
|
||||
|
||||
typeGraphNode, err = c.typeGraphNode(mapType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
typeGraphNode.SetComment("one-per-scope")
|
||||
typeGraphNode.SetComment("one-per-module")
|
||||
|
||||
r := &onePerScopeResolver{
|
||||
r := &onePerModuleResolver{
|
||||
typ: elemType,
|
||||
mapType: mapType,
|
||||
providers: map[Scope]*simpleProvider{},
|
||||
idxMap: map[Scope]int{},
|
||||
providers: map[*moduleKey]*simpleProvider{},
|
||||
idxMap: map[*moduleKey]int{},
|
||||
graphNode: typeGraphNode,
|
||||
}
|
||||
|
||||
c.resolvers[elemType] = r
|
||||
c.resolvers[mapType] = &mapOfOnePerScopeResolver{r}
|
||||
c.resolvers[mapType] = &mapOfOnePerModuleResolver{r}
|
||||
}
|
||||
|
||||
return c.resolvers[typ], nil
|
||||
}
|
||||
|
||||
func (c *container) addNode(constructor *ProviderDescriptor, scope Scope) (interface{}, error) {
|
||||
constructorGraphNode, err := c.locationGraphNode(constructor.Location, scope)
|
||||
func (c *container) addNode(provider *ProviderDescriptor, key *moduleKey) (interface{}, error) {
|
||||
providerGraphNode, err := c.locationGraphNode(provider.Location, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasScopeParam := false
|
||||
for _, in := range constructor.Inputs {
|
||||
hasModuleKeyParam := false
|
||||
for _, in := range provider.Inputs {
|
||||
typ := in.Type
|
||||
if typ == scopeType {
|
||||
hasScopeParam = true
|
||||
if typ == moduleKeyType {
|
||||
hasModuleKeyParam = true
|
||||
}
|
||||
|
||||
if isAutoGroupType(typ) {
|
||||
return nil, fmt.Errorf("auto-group type %v can't be used as an input parameter", typ)
|
||||
} else if isOnePerScopeType(typ) {
|
||||
return nil, fmt.Errorf("one-per-scope type %v can't be used as an input parameter", typ)
|
||||
} else if isOnePerModuleType(typ) {
|
||||
return nil, fmt.Errorf("one-per-module type %v can't be used as an input parameter", typ)
|
||||
}
|
||||
|
||||
vr, err := c.getResolver(typ)
|
||||
@ -167,25 +167,25 @@ func (c *container) addNode(constructor *ProviderDescriptor, scope Scope) (inter
|
||||
}
|
||||
}
|
||||
|
||||
c.addGraphEdge(typeGraphNode, constructorGraphNode)
|
||||
c.addGraphEdge(typeGraphNode, providerGraphNode)
|
||||
}
|
||||
|
||||
if scope != nil || !hasScopeParam {
|
||||
c.logf("Registering %s", constructor.Location.String())
|
||||
if key != nil || !hasModuleKeyParam {
|
||||
c.logf("Registering %s", provider.Location.String())
|
||||
c.indentLogger()
|
||||
defer c.dedentLogger()
|
||||
|
||||
sp := &simpleProvider{
|
||||
provider: constructor,
|
||||
scope: scope,
|
||||
provider: provider,
|
||||
moduleKey: key,
|
||||
}
|
||||
|
||||
for i, out := range constructor.Outputs {
|
||||
for i, out := range provider.Outputs {
|
||||
typ := out.Type
|
||||
|
||||
// one-per-scope maps can't be used as a return type
|
||||
if isOnePerScopeMapType(typ) {
|
||||
return nil, fmt.Errorf("%v cannot be used as a return type because %v is a one-per-scope type",
|
||||
// one-per-module maps can't be used as a return type
|
||||
if isOnePerModuleMapType(typ) {
|
||||
return nil, fmt.Errorf("%v cannot be used as a return type because %v is a one-per-module type",
|
||||
typ, typ.Elem())
|
||||
}
|
||||
|
||||
@ -221,30 +221,30 @@ func (c *container) addNode(constructor *ProviderDescriptor, scope Scope) (inter
|
||||
c.resolvers[typ] = vr
|
||||
}
|
||||
|
||||
c.addGraphEdge(constructorGraphNode, vr.typeGraphNode())
|
||||
c.addGraphEdge(providerGraphNode, vr.typeGraphNode())
|
||||
}
|
||||
|
||||
return sp, nil
|
||||
} else {
|
||||
c.logf("Registering scope provider: %s", constructor.Location.String())
|
||||
c.logf("Registering module-scoped provider: %s", provider.Location.String())
|
||||
c.indentLogger()
|
||||
defer c.dedentLogger()
|
||||
|
||||
node := &scopeDepProvider{
|
||||
provider: constructor,
|
||||
calledForScope: map[Scope]bool{},
|
||||
valueMap: map[Scope][]reflect.Value{},
|
||||
node := &moduleDepProvider{
|
||||
provider: provider,
|
||||
calledForModule: map[*moduleKey]bool{},
|
||||
valueMap: map[*moduleKey][]reflect.Value{},
|
||||
}
|
||||
|
||||
for i, out := range constructor.Outputs {
|
||||
for i, out := range provider.Outputs {
|
||||
typ := out.Type
|
||||
|
||||
c.logf("Registering resolver for scoped type %v", typ)
|
||||
c.logf("Registering resolver for module-scoped type %v", typ)
|
||||
|
||||
existing, ok := c.resolvers[typ]
|
||||
if ok {
|
||||
return nil, errors.Errorf("duplicate provision of type %v by scoped provider %s\n\talready provided by %s",
|
||||
typ, constructor.Location, existing.describeLocation())
|
||||
return nil, errors.Errorf("duplicate provision of type %v by module-scoped provider %s\n\talready provided by %s",
|
||||
typ, provider.Location, existing.describeLocation())
|
||||
}
|
||||
|
||||
typeGraphNode, err := c.typeGraphNode(typ)
|
||||
@ -252,15 +252,15 @@ func (c *container) addNode(constructor *ProviderDescriptor, scope Scope) (inter
|
||||
return reflect.Value{}, err
|
||||
}
|
||||
|
||||
c.resolvers[typ] = &scopeDepResolver{
|
||||
c.resolvers[typ] = &moduleDepResolver{
|
||||
typ: typ,
|
||||
idxInValues: i,
|
||||
node: node,
|
||||
valueMap: map[Scope]reflect.Value{},
|
||||
valueMap: map[*moduleKey]reflect.Value{},
|
||||
graphNode: typeGraphNode,
|
||||
}
|
||||
|
||||
c.addGraphEdge(constructorGraphNode, typeGraphNode)
|
||||
c.addGraphEdge(providerGraphNode, typeGraphNode)
|
||||
}
|
||||
|
||||
return node, nil
|
||||
@ -296,7 +296,7 @@ func (c *container) supply(value reflect.Value, location Location) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *container) resolve(in ProviderInput, scope Scope, caller Location) (reflect.Value, error) {
|
||||
func (c *container) resolve(in ProviderInput, moduleKey *moduleKey, caller Location) (reflect.Value, error) {
|
||||
c.resolveStack = append(c.resolveStack, resolveFrame{loc: caller, typ: in.Type})
|
||||
|
||||
typeGraphNode, err := c.typeGraphNode(in.Type)
|
||||
@ -304,13 +304,13 @@ func (c *container) resolve(in ProviderInput, scope Scope, caller Location) (ref
|
||||
return reflect.Value{}, err
|
||||
}
|
||||
|
||||
if in.Type == scopeType {
|
||||
if scope == nil {
|
||||
return reflect.Value{}, errors.Errorf("trying to resolve %T for %s but not inside of any scope", scope, caller)
|
||||
if in.Type == moduleKeyType {
|
||||
if moduleKey == nil {
|
||||
return reflect.Value{}, errors.Errorf("trying to resolve %T for %s but not inside of any module's scope", moduleKey, caller)
|
||||
}
|
||||
c.logf("Providing Scope %s", scope.Name())
|
||||
c.logf("Providing ModuleKey %s", moduleKey.name)
|
||||
markGraphNodeAsUsed(typeGraphNode)
|
||||
return reflect.ValueOf(scope), nil
|
||||
return reflect.ValueOf(ModuleKey{moduleKey}), nil
|
||||
}
|
||||
|
||||
vr, err := c.getResolver(in.Type)
|
||||
@ -329,7 +329,7 @@ func (c *container) resolve(in ProviderInput, scope Scope, caller Location) (ref
|
||||
in.Type, caller, c.formatResolveStack())
|
||||
}
|
||||
|
||||
res, err := vr.resolve(c, scope, caller)
|
||||
res, err := vr.resolve(c, moduleKey, caller)
|
||||
if err != nil {
|
||||
markGraphNodeAsFailed(typeGraphNode)
|
||||
return reflect.Value{}, err
|
||||
@ -364,7 +364,7 @@ func (c *container) run(invoker interface{}) error {
|
||||
|
||||
sn, ok := node.(*simpleProvider)
|
||||
if !ok {
|
||||
return errors.Errorf("cannot run scoped provider as an invoker")
|
||||
return errors.Errorf("cannot run module-scoped provider as an invoker")
|
||||
}
|
||||
|
||||
c.logf("Building container")
|
||||
@ -377,12 +377,12 @@ func (c *container) run(invoker interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c container) createOrGetScope(name string) Scope {
|
||||
if s, ok := c.scopes[name]; ok {
|
||||
func (c container) createOrGetModuleKey(name string) *moduleKey {
|
||||
if s, ok := c.moduleKeys[name]; ok {
|
||||
return s
|
||||
}
|
||||
s := newScope(name)
|
||||
c.scopes[name] = s
|
||||
s := &moduleKey{name}
|
||||
c.moduleKeys[name] = s
|
||||
return s
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ type Handler struct {
|
||||
Handle func()
|
||||
}
|
||||
|
||||
func (Handler) IsOnePerScopeType() {}
|
||||
func (Handler) IsOnePerModuleType() {}
|
||||
|
||||
type Command struct {
|
||||
Run func()
|
||||
@ -42,15 +42,15 @@ type Command struct {
|
||||
|
||||
func (Command) IsAutoGroupType() {}
|
||||
|
||||
func ProvideKVStoreKey(scope container.Scope) KVStoreKey {
|
||||
return KVStoreKey{name: scope.Name()}
|
||||
func ProvideKVStoreKey(moduleKey container.ModuleKey) KVStoreKey {
|
||||
return KVStoreKey{name: moduleKey.Name()}
|
||||
}
|
||||
|
||||
func ProvideModuleKey(scope container.Scope) (ModuleKey, error) {
|
||||
return ModuleKey(scope.Name()), nil
|
||||
func ProvideModuleKey(moduleKey container.ModuleKey) (ModuleKey, error) {
|
||||
return ModuleKey(moduleKey.Name()), nil
|
||||
}
|
||||
|
||||
func ProvideMsgClientA(_ container.Scope, key ModuleKey) MsgClientA {
|
||||
func ProvideMsgClientA(_ container.ModuleKey, key ModuleKey) MsgClientA {
|
||||
return MsgClientA{key}
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ type BProvides struct {
|
||||
Commands []Command
|
||||
}
|
||||
|
||||
func (ModuleB) Provide(dependencies BDependencies, _ container.Scope) (BProvides, Handler, error) {
|
||||
func (ModuleB) Provide(dependencies BDependencies, _ container.ModuleKey) (BProvides, Handler, error) {
|
||||
return BProvides{
|
||||
KeeperB: KeeperB{
|
||||
key: dependencies.Key,
|
||||
@ -109,8 +109,8 @@ func TestScenario(t *testing.T) {
|
||||
ProvideModuleKey,
|
||||
ProvideMsgClientA,
|
||||
),
|
||||
container.ProvideWithScope("a", wrapMethod0(ModuleA{})),
|
||||
container.ProvideWithScope("b", wrapMethod0(ModuleB{})),
|
||||
container.ProvideInModule("a", wrapMethod0(ModuleA{})),
|
||||
container.ProvideInModule("b", wrapMethod0(ModuleB{})),
|
||||
))
|
||||
}
|
||||
|
||||
@ -215,11 +215,11 @@ func TestSimple(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
func TestScoped(t *testing.T) {
|
||||
func TestModuleScoped(t *testing.T) {
|
||||
require.Error(t,
|
||||
container.Run(func(int) {},
|
||||
container.Provide(
|
||||
func(container.Scope) int { return 0 },
|
||||
func(container.ModuleKey) int { return 0 },
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -227,10 +227,10 @@ func TestScoped(t *testing.T) {
|
||||
require.Error(t,
|
||||
container.Run(func(float64) {},
|
||||
container.Provide(
|
||||
func(container.Scope) int { return 0 },
|
||||
func(container.ModuleKey) int { return 0 },
|
||||
func() int { return 1 },
|
||||
),
|
||||
container.ProvideWithScope("a",
|
||||
container.ProvideInModule("a",
|
||||
func(x int) float64 { return float64(x) },
|
||||
),
|
||||
),
|
||||
@ -240,9 +240,9 @@ func TestScoped(t *testing.T) {
|
||||
container.Run(func(float64) {},
|
||||
container.Provide(
|
||||
func() int { return 0 },
|
||||
func(container.Scope) int { return 1 },
|
||||
func(container.ModuleKey) int { return 1 },
|
||||
),
|
||||
container.ProvideWithScope("a",
|
||||
container.ProvideInModule("a",
|
||||
func(x int) float64 { return float64(x) },
|
||||
),
|
||||
),
|
||||
@ -251,10 +251,10 @@ func TestScoped(t *testing.T) {
|
||||
require.Error(t,
|
||||
container.Run(func(float64) {},
|
||||
container.Provide(
|
||||
func(container.Scope) int { return 0 },
|
||||
func(container.Scope) int { return 1 },
|
||||
func(container.ModuleKey) int { return 0 },
|
||||
func(container.ModuleKey) int { return 1 },
|
||||
),
|
||||
container.ProvideWithScope("a",
|
||||
container.ProvideInModule("a",
|
||||
func(x int) float64 { return float64(x) },
|
||||
),
|
||||
),
|
||||
@ -263,9 +263,9 @@ func TestScoped(t *testing.T) {
|
||||
require.NoError(t,
|
||||
container.Run(func(float64) {},
|
||||
container.Provide(
|
||||
func(container.Scope) int { return 0 },
|
||||
func(container.ModuleKey) int { return 0 },
|
||||
),
|
||||
container.ProvideWithScope("a",
|
||||
container.ProvideInModule("a",
|
||||
func(x int) float64 { return float64(x) },
|
||||
),
|
||||
),
|
||||
@ -274,9 +274,9 @@ func TestScoped(t *testing.T) {
|
||||
require.Error(t,
|
||||
container.Run(func(float64) {},
|
||||
container.Provide(
|
||||
func(container.Scope) int { return 0 },
|
||||
func(container.ModuleKey) int { return 0 },
|
||||
),
|
||||
container.ProvideWithScope("",
|
||||
container.ProvideInModule("",
|
||||
func(x int) float64 { return float64(x) },
|
||||
),
|
||||
),
|
||||
@ -285,45 +285,45 @@ func TestScoped(t *testing.T) {
|
||||
require.NoError(t,
|
||||
container.Run(func(float64, float32) {},
|
||||
container.Provide(
|
||||
func(container.Scope) int { return 0 },
|
||||
func(container.ModuleKey) int { return 0 },
|
||||
),
|
||||
container.ProvideWithScope("a",
|
||||
container.ProvideInModule("a",
|
||||
func(x int) float64 { return float64(x) },
|
||||
func(x int) float32 { return float32(x) },
|
||||
),
|
||||
),
|
||||
"use scope dep twice",
|
||||
"use module dep twice",
|
||||
)
|
||||
}
|
||||
|
||||
type OnePerScopeInt int
|
||||
type OnePerModuleInt int
|
||||
|
||||
func (OnePerScopeInt) IsOnePerScopeType() {}
|
||||
func (OnePerModuleInt) IsOnePerModuleType() {}
|
||||
|
||||
func TestOnePerScope(t *testing.T) {
|
||||
func TestOnePerModule(t *testing.T) {
|
||||
require.Error(t,
|
||||
container.Run(
|
||||
func(OnePerScopeInt) {},
|
||||
func(OnePerModuleInt) {},
|
||||
),
|
||||
"bad input type",
|
||||
)
|
||||
|
||||
require.NoError(t,
|
||||
container.Run(
|
||||
func(x map[string]OnePerScopeInt, y string) {
|
||||
require.Equal(t, map[string]OnePerScopeInt{
|
||||
func(x map[string]OnePerModuleInt, y string) {
|
||||
require.Equal(t, map[string]OnePerModuleInt{
|
||||
"a": 3,
|
||||
"b": 4,
|
||||
}, x)
|
||||
require.Equal(t, "7", y)
|
||||
},
|
||||
container.ProvideWithScope("a",
|
||||
func() OnePerScopeInt { return 3 },
|
||||
container.ProvideInModule("a",
|
||||
func() OnePerModuleInt { return 3 },
|
||||
),
|
||||
container.ProvideWithScope("b",
|
||||
func() OnePerScopeInt { return 4 },
|
||||
container.ProvideInModule("b",
|
||||
func() OnePerModuleInt { return 4 },
|
||||
),
|
||||
container.Provide(func(x map[string]OnePerScopeInt) string {
|
||||
container.Provide(func(x map[string]OnePerModuleInt) string {
|
||||
sum := 0
|
||||
for _, v := range x {
|
||||
sum += int(v)
|
||||
@ -335,10 +335,10 @@ func TestOnePerScope(t *testing.T) {
|
||||
|
||||
require.Error(t,
|
||||
container.Run(
|
||||
func(map[string]OnePerScopeInt) {},
|
||||
container.ProvideWithScope("a",
|
||||
func() OnePerScopeInt { return 0 },
|
||||
func() OnePerScopeInt { return 0 },
|
||||
func(map[string]OnePerModuleInt) {},
|
||||
container.ProvideInModule("a",
|
||||
func() OnePerModuleInt { return 0 },
|
||||
func() OnePerModuleInt { return 0 },
|
||||
),
|
||||
),
|
||||
"duplicate",
|
||||
@ -346,9 +346,9 @@ func TestOnePerScope(t *testing.T) {
|
||||
|
||||
require.Error(t,
|
||||
container.Run(
|
||||
func(map[string]OnePerScopeInt) {},
|
||||
func(map[string]OnePerModuleInt) {},
|
||||
container.Provide(
|
||||
func() OnePerScopeInt { return 0 },
|
||||
func() OnePerModuleInt { return 0 },
|
||||
),
|
||||
),
|
||||
"out of scope",
|
||||
@ -356,9 +356,9 @@ func TestOnePerScope(t *testing.T) {
|
||||
|
||||
require.Error(t,
|
||||
container.Run(
|
||||
func(map[string]OnePerScopeInt) {},
|
||||
func(map[string]OnePerModuleInt) {},
|
||||
container.Provide(
|
||||
func() map[string]OnePerScopeInt { return nil },
|
||||
func() map[string]OnePerModuleInt { return nil },
|
||||
),
|
||||
),
|
||||
"bad return type",
|
||||
@ -366,7 +366,7 @@ func TestOnePerScope(t *testing.T) {
|
||||
|
||||
require.NoError(t,
|
||||
container.Run(
|
||||
func(map[string]OnePerScopeInt) {},
|
||||
func(map[string]OnePerModuleInt) {},
|
||||
),
|
||||
"no providers",
|
||||
)
|
||||
|
||||
@ -193,8 +193,8 @@ func (c *debugConfig) addFileVisualizer(filename string, format string) {
|
||||
})
|
||||
}
|
||||
|
||||
func (c *debugConfig) locationGraphNode(location Location, scope Scope) (*cgraph.Node, error) {
|
||||
graph := c.scopeSubGraph(scope)
|
||||
func (c *debugConfig) locationGraphNode(location Location, key *moduleKey) (*cgraph.Node, error) {
|
||||
graph := c.moduleSubGraph(key)
|
||||
node, found, err := c.findOrCreateGraphNode(graph, location.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -241,12 +241,12 @@ func (c *debugConfig) findOrCreateGraphNode(subGraph *cgraph.Graph, name string)
|
||||
return node, false, nil
|
||||
}
|
||||
|
||||
func (c *debugConfig) scopeSubGraph(scope Scope) *cgraph.Graph {
|
||||
func (c *debugConfig) moduleSubGraph(key *moduleKey) *cgraph.Graph {
|
||||
graph := c.graph
|
||||
if scope != nil {
|
||||
gname := fmt.Sprintf("cluster_%s", scope.Name())
|
||||
if key != nil {
|
||||
gname := fmt.Sprintf("cluster_%s", key.name)
|
||||
graph = c.graph.SubGraph(gname, 1)
|
||||
graph.SetLabel(fmt.Sprintf("Scope: %s", scope.Name()))
|
||||
graph.SetLabel(fmt.Sprintf("ModuleKey: %s", key.name))
|
||||
}
|
||||
return graph
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fogleman/gg v1.3.0 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
github.com/corona10/goimagehash v1.0.2 h1:pUfB0LnsJASMPGEZLj7tGY251vF+qLGqOgEP4rUs6kA=
|
||||
github.com/corona10/goimagehash v1.0.2/go.mod h1:/l9umBhvcHQXVtQO1V6Gp1yD20STawkhRnnX0D1bvVI=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/goccy/go-graphviz v0.0.9 h1:s/FMMJ1Joj6La3S5ApO3Jk2cwM4LpXECC2muFx3IPQQ=
|
||||
|
||||
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
// AutoGroupType marks a type which automatically gets grouped together. For an AutoGroupType T,
|
||||
// T and []T can be declared as output parameters for constructors as many times within the container
|
||||
// T and []T can be declared as output parameters for providers as many times within the container
|
||||
// as desired. All of the provided values for T can be retrieved by declaring an
|
||||
// []T input parameter.
|
||||
type AutoGroupType interface {
|
||||
@ -46,7 +46,7 @@ func (g *groupResolver) describeLocation() string {
|
||||
return fmt.Sprintf("auto-group type %v", g.typ)
|
||||
}
|
||||
|
||||
func (g *sliceGroupResolver) resolve(c *container, _ Scope, caller Location) (reflect.Value, error) {
|
||||
func (g *sliceGroupResolver) resolve(c *container, _ *moduleKey, caller Location) (reflect.Value, error) {
|
||||
// Log
|
||||
c.logf("Providing auto-group type slice %v to %s from:", g.sliceType, caller.Name())
|
||||
c.indentLogger()
|
||||
@ -80,7 +80,7 @@ func (g *sliceGroupResolver) resolve(c *container, _ Scope, caller Location) (re
|
||||
return g.values, nil
|
||||
}
|
||||
|
||||
func (g *groupResolver) resolve(_ *container, _ Scope, _ Location) (reflect.Value, error) {
|
||||
func (g *groupResolver) resolve(_ *container, _ *moduleKey, _ Location) (reflect.Value, error) {
|
||||
return reflect.Value{}, errors.Errorf("%v is an auto-group type and cannot be used as an input value, instead use %v", g.typ, g.sliceType)
|
||||
}
|
||||
|
||||
|
||||
57
container/module_dep.go
Normal file
57
container/module_dep.go
Normal file
@ -0,0 +1,57 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/goccy/go-graphviz/cgraph"
|
||||
)
|
||||
|
||||
type moduleDepProvider struct {
|
||||
provider *ProviderDescriptor
|
||||
calledForModule map[*moduleKey]bool
|
||||
valueMap map[*moduleKey][]reflect.Value
|
||||
}
|
||||
|
||||
type moduleDepResolver struct {
|
||||
typ reflect.Type
|
||||
idxInValues int
|
||||
node *moduleDepProvider
|
||||
valueMap map[*moduleKey]reflect.Value
|
||||
graphNode *cgraph.Node
|
||||
}
|
||||
|
||||
func (s moduleDepResolver) describeLocation() string {
|
||||
return s.node.provider.Location.String()
|
||||
}
|
||||
|
||||
func (s moduleDepResolver) resolve(ctr *container, moduleKey *moduleKey, caller Location) (reflect.Value, error) {
|
||||
// Log
|
||||
ctr.logf("Providing %v from %s to %s", s.typ, s.node.provider.Location, caller.Name())
|
||||
|
||||
// Resolve
|
||||
if val, ok := s.valueMap[moduleKey]; ok {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
if !s.node.calledForModule[moduleKey] {
|
||||
values, err := ctr.call(s.node.provider, moduleKey)
|
||||
if err != nil {
|
||||
return reflect.Value{}, err
|
||||
}
|
||||
|
||||
s.node.valueMap[moduleKey] = values
|
||||
s.node.calledForModule[moduleKey] = true
|
||||
}
|
||||
|
||||
value := s.node.valueMap[moduleKey][s.idxInValues]
|
||||
s.valueMap[moduleKey] = value
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (s moduleDepResolver) addNode(p *simpleProvider, _ int) error {
|
||||
return duplicateDefinitionError(s.typ, p.provider.Location, s.node.provider.Location.String())
|
||||
}
|
||||
|
||||
func (s moduleDepResolver) typeGraphNode() *cgraph.Node {
|
||||
return s.graphNode
|
||||
}
|
||||
31
container/module_key.go
Normal file
31
container/module_key.go
Normal file
@ -0,0 +1,31 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// ModuleKey is a special type used to scope a provider to a "module".
|
||||
//
|
||||
// Special module-scoped providers can be used with Provide by declaring a
|
||||
// provider with an input parameter of type ModuleKey. These providers
|
||||
// may construct a unique value of a dependency for each module and will
|
||||
// be called at most once per module.
|
||||
//
|
||||
// Providers passed to ProvideInModule can also declare an input parameter
|
||||
// of type ModuleKey to retrieve their module key but these providers will be
|
||||
// called at most once.
|
||||
type ModuleKey struct {
|
||||
*moduleKey
|
||||
}
|
||||
|
||||
type moduleKey struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (k ModuleKey) Name() string {
|
||||
return k.name
|
||||
}
|
||||
|
||||
var moduleKeyType = reflect.TypeOf(ModuleKey{})
|
||||
|
||||
var stringType = reflect.TypeOf("")
|
||||
106
container/one_per_module.go
Normal file
106
container/one_per_module.go
Normal file
@ -0,0 +1,106 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/goccy/go-graphviz/cgraph"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// OnePerModuleType marks a type which
|
||||
// can have up to one value per module. All of the values for a one-per-module type T
|
||||
// and their respective modules, can be retrieved by declaring an input parameter map[string]T.
|
||||
type OnePerModuleType interface {
|
||||
// IsOnePerModuleType is a marker function just indicates that this is a one-per-module type.
|
||||
IsOnePerModuleType()
|
||||
}
|
||||
|
||||
var onePerModuleTypeType = reflect.TypeOf((*OnePerModuleType)(nil)).Elem()
|
||||
|
||||
func isOnePerModuleType(t reflect.Type) bool {
|
||||
return t.Implements(onePerModuleTypeType)
|
||||
}
|
||||
|
||||
func isOnePerModuleMapType(typ reflect.Type) bool {
|
||||
return typ.Kind() == reflect.Map && isOnePerModuleType(typ.Elem()) && typ.Key().Kind() == reflect.String
|
||||
}
|
||||
|
||||
type onePerModuleResolver struct {
|
||||
typ reflect.Type
|
||||
mapType reflect.Type
|
||||
providers map[*moduleKey]*simpleProvider
|
||||
idxMap map[*moduleKey]int
|
||||
resolved bool
|
||||
values reflect.Value
|
||||
graphNode *cgraph.Node
|
||||
}
|
||||
|
||||
type mapOfOnePerModuleResolver struct {
|
||||
*onePerModuleResolver
|
||||
}
|
||||
|
||||
func (o *onePerModuleResolver) resolve(_ *container, _ *moduleKey, _ Location) (reflect.Value, error) {
|
||||
return reflect.Value{}, errors.Errorf("%v is a one-per-module type and thus can't be used as an input parameter, instead use %v", o.typ, o.mapType)
|
||||
}
|
||||
|
||||
func (o *onePerModuleResolver) describeLocation() string {
|
||||
return fmt.Sprintf("one-per-module type %v", o.typ)
|
||||
}
|
||||
|
||||
func (o *mapOfOnePerModuleResolver) resolve(c *container, _ *moduleKey, caller Location) (reflect.Value, error) {
|
||||
// Log
|
||||
c.logf("Providing one-per-module type map %v to %s from:", o.mapType, caller.Name())
|
||||
c.indentLogger()
|
||||
for key, node := range o.providers {
|
||||
c.logf("%s: %s", key.name, node.provider.Location)
|
||||
}
|
||||
c.dedentLogger()
|
||||
|
||||
// Resolve
|
||||
if !o.resolved {
|
||||
res := reflect.MakeMap(o.mapType)
|
||||
for key, node := range o.providers {
|
||||
values, err := node.resolveValues(c)
|
||||
if err != nil {
|
||||
return reflect.Value{}, err
|
||||
}
|
||||
idx := o.idxMap[key]
|
||||
if len(values) < idx {
|
||||
return reflect.Value{}, errors.Errorf("expected value of type %T at index %d", o.typ, idx)
|
||||
}
|
||||
value := values[idx]
|
||||
res.SetMapIndex(reflect.ValueOf(key.name), value)
|
||||
}
|
||||
|
||||
o.values = res
|
||||
o.resolved = true
|
||||
}
|
||||
|
||||
return o.values, nil
|
||||
}
|
||||
|
||||
func (o *onePerModuleResolver) addNode(n *simpleProvider, i int) error {
|
||||
if n.moduleKey == nil {
|
||||
return errors.Errorf("cannot define a provider with one-per-module dependency %v which isn't provided in a module", o.typ)
|
||||
}
|
||||
|
||||
if existing, ok := o.providers[n.moduleKey]; ok {
|
||||
return errors.Errorf("duplicate provision for one-per-module type %v in module %s: %s\n\talready provided by %s",
|
||||
o.typ, n.moduleKey.name, n.provider.Location, existing.provider.Location)
|
||||
}
|
||||
|
||||
o.providers[n.moduleKey] = n
|
||||
o.idxMap[n.moduleKey] = i
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *mapOfOnePerModuleResolver) addNode(s *simpleProvider, _ int) error {
|
||||
return errors.Errorf("%v is a one-per-module type and thus %v can't be used as an output parameter in %s", o.typ, o.mapType, s.provider.Location)
|
||||
}
|
||||
|
||||
func (o onePerModuleResolver) typeGraphNode() *cgraph.Node {
|
||||
return o.graphNode
|
||||
}
|
||||
@ -1,106 +0,0 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/goccy/go-graphviz/cgraph"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// OnePerScopeType marks a type which
|
||||
// can have up to one value per scope. All of the values for a one-per-scope type T
|
||||
// and their respective scopes, can be retrieved by declaring an input parameter map[string]T.
|
||||
type OnePerScopeType interface {
|
||||
// IsOnePerScopeType is a marker function just indicates that this is a one-per-scope type.
|
||||
IsOnePerScopeType()
|
||||
}
|
||||
|
||||
var onePerScopeTypeType = reflect.TypeOf((*OnePerScopeType)(nil)).Elem()
|
||||
|
||||
func isOnePerScopeType(t reflect.Type) bool {
|
||||
return t.Implements(onePerScopeTypeType)
|
||||
}
|
||||
|
||||
func isOnePerScopeMapType(typ reflect.Type) bool {
|
||||
return typ.Kind() == reflect.Map && isOnePerScopeType(typ.Elem()) && typ.Key().Kind() == reflect.String
|
||||
}
|
||||
|
||||
type onePerScopeResolver struct {
|
||||
typ reflect.Type
|
||||
mapType reflect.Type
|
||||
providers map[Scope]*simpleProvider
|
||||
idxMap map[Scope]int
|
||||
resolved bool
|
||||
values reflect.Value
|
||||
graphNode *cgraph.Node
|
||||
}
|
||||
|
||||
type mapOfOnePerScopeResolver struct {
|
||||
*onePerScopeResolver
|
||||
}
|
||||
|
||||
func (o *onePerScopeResolver) resolve(_ *container, _ Scope, _ Location) (reflect.Value, error) {
|
||||
return reflect.Value{}, errors.Errorf("%v is a one-per-scope type and thus can't be used as an input parameter, instead use %v", o.typ, o.mapType)
|
||||
}
|
||||
|
||||
func (o *onePerScopeResolver) describeLocation() string {
|
||||
return fmt.Sprintf("one-per-scope type %v", o.typ)
|
||||
}
|
||||
|
||||
func (o *mapOfOnePerScopeResolver) resolve(c *container, _ Scope, caller Location) (reflect.Value, error) {
|
||||
// Log
|
||||
c.logf("Providing one-per-scope type map %v to %s from:", o.mapType, caller.Name())
|
||||
c.indentLogger()
|
||||
for scope, node := range o.providers {
|
||||
c.logf("%s: %s", scope.Name(), node.provider.Location)
|
||||
}
|
||||
c.dedentLogger()
|
||||
|
||||
// Resolve
|
||||
if !o.resolved {
|
||||
res := reflect.MakeMap(o.mapType)
|
||||
for scope, node := range o.providers {
|
||||
values, err := node.resolveValues(c)
|
||||
if err != nil {
|
||||
return reflect.Value{}, err
|
||||
}
|
||||
idx := o.idxMap[scope]
|
||||
if len(values) < idx {
|
||||
return reflect.Value{}, errors.Errorf("expected value of type %T at index %d", o.typ, idx)
|
||||
}
|
||||
value := values[idx]
|
||||
res.SetMapIndex(reflect.ValueOf(scope.Name()), value)
|
||||
}
|
||||
|
||||
o.values = res
|
||||
o.resolved = true
|
||||
}
|
||||
|
||||
return o.values, nil
|
||||
}
|
||||
|
||||
func (o *onePerScopeResolver) addNode(n *simpleProvider, i int) error {
|
||||
if n.scope == nil {
|
||||
return errors.Errorf("cannot define a constructor with one-per-scope dependency %v which isn't provided in a scope", o.typ)
|
||||
}
|
||||
|
||||
if existing, ok := o.providers[n.scope]; ok {
|
||||
return errors.Errorf("duplicate provision for one-per-scope type %v in scope %s: %s\n\talready provided by %s",
|
||||
o.typ, n.scope.Name(), n.provider.Location, existing.provider.Location)
|
||||
}
|
||||
|
||||
o.providers[n.scope] = n
|
||||
o.idxMap[n.scope] = i
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *mapOfOnePerScopeResolver) addNode(s *simpleProvider, _ int) error {
|
||||
return errors.Errorf("%v is a one-per-scope type and thus %v can't be used as an output parameter in %s", o.typ, o.mapType, s.provider.Location)
|
||||
}
|
||||
|
||||
func (o onePerScopeResolver) typeGraphNode() *cgraph.Node {
|
||||
return o.graphNode
|
||||
}
|
||||
@ -12,35 +12,35 @@ type Option interface {
|
||||
}
|
||||
|
||||
// Provide creates a container option which registers the provided dependency
|
||||
// injection constructors. Each constructor will be called at most once with the
|
||||
// exception of scoped constructors which are called at most once per scope
|
||||
// (see Scope).
|
||||
func Provide(constructors ...interface{}) Option {
|
||||
// injection providers. Each provider will be called at most once with the
|
||||
// exception of module-scoped providers which are called at most once per module
|
||||
// (see ModuleKey).
|
||||
func Provide(providers ...interface{}) Option {
|
||||
return containerOption(func(ctr *container) error {
|
||||
return provide(ctr, nil, constructors)
|
||||
return provide(ctr, nil, providers)
|
||||
})
|
||||
}
|
||||
|
||||
// ProvideWithScope creates a container option which registers the provided dependency
|
||||
// injection constructors that are to be run in the provided scope. Each constructor
|
||||
// ProvideInModule creates a container option which registers the provided dependency
|
||||
// injection providers that are to be run in the named module. Each provider
|
||||
// will be called at most once.
|
||||
func ProvideWithScope(scopeName string, constructors ...interface{}) Option {
|
||||
func ProvideInModule(moduleName string, providers ...interface{}) Option {
|
||||
return containerOption(func(ctr *container) error {
|
||||
if scopeName == "" {
|
||||
return errors.Errorf("expected non-empty scope name")
|
||||
if moduleName == "" {
|
||||
return errors.Errorf("expected non-empty module name")
|
||||
}
|
||||
|
||||
return provide(ctr, ctr.createOrGetScope(scopeName), constructors)
|
||||
return provide(ctr, ctr.createOrGetModuleKey(moduleName), providers)
|
||||
})
|
||||
}
|
||||
|
||||
func provide(ctr *container, scope Scope, constructors []interface{}) error {
|
||||
for _, c := range constructors {
|
||||
func provide(ctr *container, key *moduleKey, providers []interface{}) error {
|
||||
for _, c := range providers {
|
||||
rc, err := ExtractProviderDescriptor(c)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
_, err = ctr.addNode(&rc, scope)
|
||||
_, err = ctr.addNode(&rc, key)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ProviderDescriptor defines a special constructor type that is defined by
|
||||
// ProviderDescriptor defines a special provider type that is defined by
|
||||
// reflection. It should be passed as a value to the Provide function.
|
||||
// Ex:
|
||||
// option.Provide(ProviderDescriptor{ ... })
|
||||
@ -17,10 +17,10 @@ type ProviderDescriptor struct {
|
||||
// Outputs defines the out parameter types to Fn.
|
||||
Outputs []ProviderOutput
|
||||
|
||||
// Fn defines the constructor function.
|
||||
// Fn defines the provider function.
|
||||
Fn func([]reflect.Value) ([]reflect.Value, error)
|
||||
|
||||
// Location defines the source code location to be used for this constructor
|
||||
// Location defines the source code location to be used for this provider
|
||||
// in error messages.
|
||||
Location Location
|
||||
}
|
||||
@ -44,7 +44,7 @@ func ExtractProviderDescriptor(provider interface{}) (ProviderDescriptor, error)
|
||||
}
|
||||
}
|
||||
|
||||
return expandStructArgsConstructor(rctr)
|
||||
return expandStructArgsProvider(rctr)
|
||||
}
|
||||
|
||||
func doExtractProviderDescriptor(ctr interface{}) (ProviderDescriptor, error) {
|
||||
@ -57,7 +57,7 @@ func doExtractProviderDescriptor(ctr interface{}) (ProviderDescriptor, error) {
|
||||
loc := LocationFromPC(val.Pointer())
|
||||
|
||||
if typ.IsVariadic() {
|
||||
return ProviderDescriptor{}, errors.Errorf("variadic function can't be used as a constructor: %s", loc)
|
||||
return ProviderDescriptor{}, errors.Errorf("variadic function can't be used as a provider: %s", loc)
|
||||
}
|
||||
|
||||
numIn := typ.NumIn()
|
||||
|
||||
@ -24,7 +24,7 @@ type StructOut struct {
|
||||
Y []byte
|
||||
}
|
||||
|
||||
func TestExtractConstructorInfo(t *testing.T) {
|
||||
func TestExtractProviderDescriptor(t *testing.T) {
|
||||
var (
|
||||
intType = reflect.TypeOf(0)
|
||||
int16Type = reflect.TypeOf(int16(0))
|
||||
|
||||
@ -8,7 +8,7 @@ import (
|
||||
|
||||
type resolver interface {
|
||||
addNode(*simpleProvider, int) error
|
||||
resolve(*container, Scope, Location) (reflect.Value, error)
|
||||
resolve(*container, *moduleKey, Location) (reflect.Value, error)
|
||||
describeLocation() string
|
||||
typeGraphNode() *cgraph.Node
|
||||
}
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Scope is a special type used to define a provider scope.
|
||||
//
|
||||
// Special scoped constructors can be used with Provide by declaring a
|
||||
// constructor with an input parameter of type Scope. These constructors
|
||||
// should construct an unique value for each dependency based on scope and will
|
||||
// be called at most once per scope.
|
||||
//
|
||||
// Constructors passed to ProvideWithScope can also declare an input parameter
|
||||
// of type Scope to retrieve their scope but these constructors will be called at most once.
|
||||
type Scope interface {
|
||||
isScope()
|
||||
|
||||
// Name returns the name of the scope which is unique within a container.
|
||||
Name() string
|
||||
}
|
||||
|
||||
// NewScope creates a new scope with the provided name. Only one scope with a
|
||||
// given name can be created per container.
|
||||
func newScope(name string) Scope {
|
||||
return &scope{name: name}
|
||||
}
|
||||
|
||||
type scope struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (s *scope) Name() string {
|
||||
return s.name
|
||||
}
|
||||
|
||||
func (s *scope) isScope() {}
|
||||
|
||||
var scopeType = reflect.TypeOf((*Scope)(nil)).Elem()
|
||||
|
||||
var stringType = reflect.TypeOf("")
|
||||
@ -1,57 +0,0 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/goccy/go-graphviz/cgraph"
|
||||
)
|
||||
|
||||
type scopeDepProvider struct {
|
||||
provider *ProviderDescriptor
|
||||
calledForScope map[Scope]bool
|
||||
valueMap map[Scope][]reflect.Value
|
||||
}
|
||||
|
||||
type scopeDepResolver struct {
|
||||
typ reflect.Type
|
||||
idxInValues int
|
||||
node *scopeDepProvider
|
||||
valueMap map[Scope]reflect.Value
|
||||
graphNode *cgraph.Node
|
||||
}
|
||||
|
||||
func (s scopeDepResolver) describeLocation() string {
|
||||
return s.node.provider.Location.String()
|
||||
}
|
||||
|
||||
func (s scopeDepResolver) resolve(ctr *container, scope Scope, caller Location) (reflect.Value, error) {
|
||||
// Log
|
||||
ctr.logf("Providing %v from %s to %s", s.typ, s.node.provider.Location, caller.Name())
|
||||
|
||||
// Resolve
|
||||
if val, ok := s.valueMap[scope]; ok {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
if !s.node.calledForScope[scope] {
|
||||
values, err := ctr.call(s.node.provider, scope)
|
||||
if err != nil {
|
||||
return reflect.Value{}, err
|
||||
}
|
||||
|
||||
s.node.valueMap[scope] = values
|
||||
s.node.calledForScope[scope] = true
|
||||
}
|
||||
|
||||
value := s.node.valueMap[scope][s.idxInValues]
|
||||
s.valueMap[scope] = value
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (s scopeDepResolver) addNode(p *simpleProvider, _ int) error {
|
||||
return duplicateDefinitionError(s.typ, p.provider.Location, s.node.provider.Location.String())
|
||||
}
|
||||
|
||||
func (s scopeDepResolver) typeGraphNode() *cgraph.Node {
|
||||
return s.graphNode
|
||||
}
|
||||
@ -7,10 +7,10 @@ import (
|
||||
)
|
||||
|
||||
type simpleProvider struct {
|
||||
provider *ProviderDescriptor
|
||||
called bool
|
||||
values []reflect.Value
|
||||
scope Scope
|
||||
provider *ProviderDescriptor
|
||||
called bool
|
||||
values []reflect.Value
|
||||
moduleKey *moduleKey
|
||||
}
|
||||
|
||||
type simpleResolver struct {
|
||||
@ -28,7 +28,7 @@ func (s *simpleResolver) describeLocation() string {
|
||||
|
||||
func (s *simpleProvider) resolveValues(ctr *container) ([]reflect.Value, error) {
|
||||
if !s.called {
|
||||
values, err := ctr.call(s.provider, s.scope)
|
||||
values, err := ctr.call(s.provider, s.moduleKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -39,7 +39,7 @@ func (s *simpleProvider) resolveValues(ctr *container) ([]reflect.Value, error)
|
||||
return s.values, nil
|
||||
}
|
||||
|
||||
func (s *simpleResolver) resolve(c *container, _ Scope, caller Location) (reflect.Value, error) {
|
||||
func (s *simpleResolver) resolve(c *container, _ *moduleKey, caller Location) (reflect.Value, error) {
|
||||
// Log
|
||||
c.logf("Providing %v from %s to %s", s.typ, s.node.provider.Location, caller.Name())
|
||||
|
||||
|
||||
@ -35,11 +35,11 @@ type isOut interface{ isOut() }
|
||||
|
||||
var isOutType = reflect.TypeOf((*isOut)(nil)).Elem()
|
||||
|
||||
func expandStructArgsConstructor(constructor ProviderDescriptor) (ProviderDescriptor, error) {
|
||||
func expandStructArgsProvider(provider ProviderDescriptor) (ProviderDescriptor, error) {
|
||||
var foundStructArgs bool
|
||||
var newIn []ProviderInput
|
||||
|
||||
for _, in := range constructor.Inputs {
|
||||
for _, in := range provider.Inputs {
|
||||
if in.Type.AssignableTo(isInType) {
|
||||
foundStructArgs = true
|
||||
inTypes, err := structArgsInTypes(in.Type)
|
||||
@ -53,7 +53,7 @@ func expandStructArgsConstructor(constructor ProviderDescriptor) (ProviderDescri
|
||||
}
|
||||
|
||||
var newOut []ProviderOutput
|
||||
for _, out := range constructor.Outputs {
|
||||
for _, out := range provider.Outputs {
|
||||
if out.Type.AssignableTo(isOutType) {
|
||||
foundStructArgs = true
|
||||
newOut = append(newOut, structArgsOutTypes(out.Type)...)
|
||||
@ -66,18 +66,18 @@ func expandStructArgsConstructor(constructor ProviderDescriptor) (ProviderDescri
|
||||
return ProviderDescriptor{
|
||||
Inputs: newIn,
|
||||
Outputs: newOut,
|
||||
Fn: expandStructArgsFn(constructor),
|
||||
Location: constructor.Location,
|
||||
Fn: expandStructArgsFn(provider),
|
||||
Location: provider.Location,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return constructor, nil
|
||||
return provider, nil
|
||||
}
|
||||
|
||||
func expandStructArgsFn(constructor ProviderDescriptor) func(inputs []reflect.Value) ([]reflect.Value, error) {
|
||||
fn := constructor.Fn
|
||||
inParams := constructor.Inputs
|
||||
outParams := constructor.Outputs
|
||||
func expandStructArgsFn(provider ProviderDescriptor) func(inputs []reflect.Value) ([]reflect.Value, error) {
|
||||
fn := provider.Fn
|
||||
inParams := provider.Inputs
|
||||
outParams := provider.Outputs
|
||||
return func(inputs []reflect.Value) ([]reflect.Value, error) {
|
||||
j := 0
|
||||
inputs1 := make([]reflect.Value, len(inParams))
|
||||
|
||||
@ -21,7 +21,7 @@ func (s supplyResolver) addNode(provider *simpleProvider, _ int) error {
|
||||
return duplicateDefinitionError(s.typ, provider.provider.Location, s.loc.String())
|
||||
}
|
||||
|
||||
func (s supplyResolver) resolve(c *container, _ Scope, caller Location) (reflect.Value, error) {
|
||||
func (s supplyResolver) resolve(c *container, _ *moduleKey, caller Location) (reflect.Value, error) {
|
||||
c.logf("Supplying %v from %s to %s", s.typ, s.loc, caller.Name())
|
||||
return s.value, nil
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user