From ed49204e850f58556da5e95a0b6fff1b7dfdbf18 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 13 Dec 2023 14:47:32 -0800 Subject: [PATCH] Use generics for providers API Using generics for the providers API allows a type to be associated with a ProviderKey, resulting in a type-safe API without that doesn't require runtime type assertions by every caller. Unfortunately, Go does not allow generic types in methods, only in functions [1]. This prevents a type-safe API on ModuleContext, and requires moving the API to be functions that take a ModuleContext as a parameter. [1] https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#no-parameterized-methods) Bug: 316410648 Test: provider_test.go Change-Id: Ide91de9f2a2a7d075b05e287c7cc86b395db0edb --- bootstrap/bootstrap.go | 4 +- context.go | 16 ++-- module_ctx.go | 60 ++++++------- provider.go | 181 +++++++++++++++++++++++++++++++--------- provider_test.go | 59 +++++++------ singleton_ctx.go | 12 +-- source_file_provider.go | 2 +- 7 files changed, 213 insertions(+), 121 deletions(-) diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go index 97ed2bd..7465aff 100644 --- a/bootstrap/bootstrap.go +++ b/bootstrap/bootstrap.go @@ -337,7 +337,7 @@ func (g *GoPackage) GenerateBuildActions(ctx blueprint.ModuleContext) { buildGoPackage(ctx, g.pkgRoot, g.properties.PkgPath, g.archiveFile, srcs, genSrcs) - ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs}) + blueprint.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs}) } func (g *GoPackage) Srcs() []string { @@ -534,7 +534,7 @@ func (g *GoBinary) GenerateBuildActions(ctx blueprint.ModuleContext) { Validations: validations, Optional: !g.properties.Default, }) - ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs}) + blueprint.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs}) } func buildGoPluginLoader(ctx blueprint.ModuleContext, pkgPath, pluginSrc string) bool { diff --git a/context.go b/context.go index a197858..ca30874 100644 --- a/context.go +++ b/context.go @@ -4041,17 +4041,13 @@ func (c *Context) ModuleType(logicModule Module) string { // always be considered read-only. It panics if called before the appropriate mutator or // GenerateBuildActions pass for the provider on the module. The value returned may be a deep // copy of the value originally passed to SetProvider. -func (c *Context) ModuleProvider(logicModule Module, provider ProviderKey) interface{} { +func (c *Context) ModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) { module := c.moduleInfo[logicModule] - value, _ := c.provider(module, provider) - return value -} - -// ModuleHasProvider returns true if the provider for the given module has been set. -func (c *Context) ModuleHasProvider(logicModule Module, provider ProviderKey) bool { - module := c.moduleInfo[logicModule] - _, ok := c.provider(module, provider) - return ok + value, ok := c.provider(module, provider.provider()) + if value == nil { + value = provider.provider().zero + } + return value, ok } func (c *Context) BlueprintFile(logicModule Module) string { diff --git a/module_ctx.go b/module_ctx.go index ed03789..fb65755 100644 --- a/module_ctx.go +++ b/module_ctx.go @@ -337,26 +337,26 @@ type BaseModuleContext interface { // not set it returns the zero value of the type of the provider, so the return value can always // be type asserted to the type of the provider. The value returned may be a deep copy of the // value originally passed to SetProvider. - OtherModuleProvider(m Module, provider ProviderKey) interface{} - - // OtherModuleHasProvider returns true if the provider for the given module has been set. - OtherModuleHasProvider(m Module, provider ProviderKey) bool + // + // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead. + OtherModuleProvider(m Module, provider AnyProviderKey) (any, bool) // Provider returns the value for a provider for the current module. If the value is // not set it returns the zero value of the type of the provider, so the return value can always // be type asserted to the type of the provider. It panics if called before the appropriate // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep // copy of the value originally passed to SetProvider. - Provider(provider ProviderKey) interface{} - - // HasProvider returns true if the provider for the current module has been set. - HasProvider(provider ProviderKey) bool + // + // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead. + Provider(provider AnyProviderKey) (any, bool) // SetProvider sets the value for a provider for the current module. It panics if not called // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value // is not of the appropriate type, or if the value has already been set. The value should not // be modified after being passed to SetProvider. - SetProvider(provider ProviderKey, value interface{}) + // + // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead. + SetProvider(provider AnyProviderKey, value any) EarlyGetMissingDependencies() []string } @@ -609,30 +609,30 @@ func (m *baseModuleContext) OtherModuleReverseDependencyVariantExists(name strin return found != nil } -func (m *baseModuleContext) OtherModuleProvider(logicModule Module, provider ProviderKey) interface{} { +func (m *baseModuleContext) OtherModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) { module := m.context.moduleInfo[logicModule] - value, _ := m.context.provider(module, provider) - return value + value, ok := m.context.provider(module, provider.provider()) + if value == nil { + value = provider.provider().zero + } + return value, ok } -func (m *baseModuleContext) OtherModuleHasProvider(logicModule Module, provider ProviderKey) bool { - module := m.context.moduleInfo[logicModule] - _, ok := m.context.provider(module, provider) +func (m *baseModuleContext) Provider(provider AnyProviderKey) (any, bool) { + value, ok := m.context.provider(m.module, provider.provider()) + if value == nil { + value = provider.provider().zero + } + return value, ok +} + +func (m *baseModuleContext) HasProvider(provider AnyProviderKey) bool { + _, ok := m.context.provider(m.module, provider.provider()) return ok } -func (m *baseModuleContext) Provider(provider ProviderKey) interface{} { - value, _ := m.context.provider(m.module, provider) - return value -} - -func (m *baseModuleContext) HasProvider(provider ProviderKey) bool { - _, ok := m.context.provider(m.module, provider) - return ok -} - -func (m *baseModuleContext) SetProvider(provider ProviderKey, value interface{}) { - m.context.setProvider(m.module, provider, value) +func (m *baseModuleContext) SetProvider(provider AnyProviderKey, value interface{}) { + m.context.setProvider(m.module, provider.provider(), value) } func (m *baseModuleContext) GetDirectDep(name string) (Module, DependencyTag) { @@ -979,7 +979,7 @@ type BottomUpMutatorContext interface { // if the value is not of the appropriate type, or if the module is not a newly created // variant of the current module. The value should not be modified after being passed to // SetVariationProvider. - SetVariationProvider(module Module, provider ProviderKey, value interface{}) + SetVariationProvider(module Module, provider AnyProviderKey, value interface{}) } // A Mutator function is called for each Module, and can use @@ -1028,10 +1028,10 @@ func (mctx *mutatorContext) CreateLocalVariations(variationNames ...string) []Mo return mctx.createVariations(variationNames, depChooser, true) } -func (mctx *mutatorContext) SetVariationProvider(module Module, provider ProviderKey, value interface{}) { +func (mctx *mutatorContext) SetVariationProvider(module Module, provider AnyProviderKey, value interface{}) { for _, variant := range mctx.newVariations { if m := variant.module(); m != nil && m.logicModule == module { - mctx.context.setProvider(m, provider, value) + mctx.context.setProvider(m, provider.provider(), value) return } } diff --git a/provider.go b/provider.go index b83e1d4..36411d8 100644 --- a/provider.go +++ b/provider.go @@ -16,7 +16,6 @@ package blueprint import ( "fmt" - "reflect" ) // This file implements Providers, modelled after Bazel @@ -28,8 +27,8 @@ import ( // module, and the value can only be retrieved after GenerateBuildActions for the module. // // Providers are globally registered during init() and given a unique ID. The value of a provider -// for a module is stored in an []interface{} indexed by the ID. If the value of a provider has -// not been set, the value in the []interface{} will be nil. +// for a module is stored in an []any indexed by the ID. If the value of a provider has +// not been set, the value in the []any will be nil. // // If the storage used by the provider value arrays becomes too large: // sizeof([]interface) * number of providers * number of modules that have a provider value set @@ -42,54 +41,64 @@ import ( // necessary for the getters and setters to make deep copies of the values, likely extending // proptools.CloneProperties to do so. -type provider struct { +type typedProviderKey[K any] struct { + providerKey +} + +type providerKey struct { id int - typ reflect.Type - zero interface{} + typ string + zero any mutator string } -type ProviderKey *provider +func (p *providerKey) provider() *providerKey { return p } -var providerRegistry []ProviderKey +type AnyProviderKey interface { + provider() *providerKey +} +type ProviderKey[K any] struct { + *typedProviderKey[K] +} -// NewProvider returns a ProviderKey for the type of the given example value. The example value -// is otherwise unused. +var _ AnyProviderKey = (*providerKey)(nil) +var _ AnyProviderKey = ProviderKey[bool]{} + +var providerRegistry []*providerKey + +// NewProvider returns a ProviderKey for the given type. // // The returned ProviderKey can be used to set a value of the ProviderKey's type for a module // inside GenerateBuildActions for the module, and to get the value from GenerateBuildActions from // any module later in the build graph. -// -// Once Go has generics the exampleValue parameter will not be necessary: -// NewProvider(type T)() ProviderKey(T) -func NewProvider(exampleValue interface{}) ProviderKey { - return NewMutatorProvider(exampleValue, "") +func NewProvider[K any]() ProviderKey[K] { + return NewMutatorProvider[K]("") } -// NewMutatorProvider returns a ProviderKey for the type of the given example value. The example -// value is otherwise unused. +// NewMutatorProvider returns a ProviderKey for the given type. // // The returned ProviderKey can be used to set a value of the ProviderKey's type for a module inside // the given mutator for the module, and to get the value from GenerateBuildActions from any // module later in the build graph in the same mutator, or any module in a later mutator or during // GenerateBuildActions. -// -// Once Go has generics the exampleValue parameter will not be necessary: -// NewMutatorProvider(type T)(mutator string) ProviderKey(T) -func NewMutatorProvider(exampleValue interface{}, mutator string) ProviderKey { +func NewMutatorProvider[K any](mutator string) ProviderKey[K] { checkCalledFromInit() - typ := reflect.TypeOf(exampleValue) - zero := reflect.Zero(typ).Interface() + zero := *new(K) + typ := fmt.Sprintf("%T", *new(K)) - provider := &provider{ - id: len(providerRegistry), - typ: typ, - zero: zero, - mutator: mutator, + provider := ProviderKey[K]{ + typedProviderKey: &typedProviderKey[K]{ + providerKey: providerKey{ + id: len(providerRegistry), + typ: typ, + zero: zero, + mutator: mutator, + }, + }, } - providerRegistry = append(providerRegistry, provider) + providerRegistry = append(providerRegistry, &provider.providerKey) return provider } @@ -113,7 +122,7 @@ func (c *Context) initProviders() { // // Once Go has generics the value parameter can be typed: // setProvider(type T)(m *moduleInfo, provider ProviderKey(T), value T) -func (c *Context) setProvider(m *moduleInfo, provider ProviderKey, value interface{}) { +func (c *Context) setProvider(m *moduleInfo, provider *providerKey, value any) { if provider.mutator == "" { if !m.startedGenerateBuildActions { panic(fmt.Sprintf("Can't set value of provider %s before GenerateBuildActions started", @@ -136,13 +145,8 @@ func (c *Context) setProvider(m *moduleInfo, provider ProviderKey, value interfa } } - if typ := reflect.TypeOf(value); typ != provider.typ { - panic(fmt.Sprintf("Value for provider has incorrect type, wanted %s, got %s", - provider.typ, typ)) - } - if m.providers == nil { - m.providers = make([]interface{}, len(providerRegistry)) + m.providers = make([]any, len(providerRegistry)) } if m.providers[provider.id] != nil { @@ -154,13 +158,11 @@ func (c *Context) setProvider(m *moduleInfo, provider ProviderKey, value interfa // provider returns the value, if any, for a given provider for a module. Verifies that it is // called after the appropriate mutator or GenerateBuildActions pass for the provider on the module. -// If the value for the provider was not set it returns the zero value of the type of the provider, -// which means the return value can always be type-asserted to the type of the provider. The return -// value should always be considered read-only. +// If the value for the provider was not set it returns nil. The return value should always be considered read-only. // // Once Go has generics the return value can be typed and the type assert by callers can be dropped: // provider(type T)(m *moduleInfo, provider ProviderKey(T)) T -func (c *Context) provider(m *moduleInfo, provider ProviderKey) (interface{}, bool) { +func (c *Context) provider(m *moduleInfo, provider *providerKey) (any, bool) { if provider.mutator == "" { if !m.finishedGenerateBuildActions { panic(fmt.Sprintf("Can't get value of provider %s before GenerateBuildActions finished", @@ -180,7 +182,7 @@ func (c *Context) provider(m *moduleInfo, provider ProviderKey) (interface{}, bo } } - return provider.zero, false + return nil, false } func (c *Context) mutatorFinishedForModule(mutator *mutatorInfo, m *moduleInfo) bool { @@ -214,3 +216,100 @@ func (c *Context) mutatorStartedForModule(mutator *mutatorInfo, m *moduleInfo) b return false } + +// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext for use in OtherModuleProvider. +type OtherModuleProviderContext interface { + OtherModuleProvider(m Module, provider AnyProviderKey) (any, bool) +} + +var _ OtherModuleProviderContext = BaseModuleContext(nil) +var _ OtherModuleProviderContext = ModuleContext(nil) +var _ OtherModuleProviderContext = BottomUpMutatorContext(nil) +var _ OtherModuleProviderContext = TopDownMutatorContext(nil) + +// OtherModuleProvider reads the provider for the given module. If the provider has been set the value is +// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned +// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider. +// +// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext. +func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module Module, provider ProviderKey[K]) (K, bool) { + value, ok := ctx.OtherModuleProvider(module, provider) + if !ok { + var k K + return k, false + } + return value.(K), ok +} + +// SingletonModuleProviderContext is a helper interface that is a subset of Context and SingletonContext for use in +// SingletonModuleProvider. +type SingletonModuleProviderContext interface { + ModuleProvider(m Module, provider AnyProviderKey) (any, bool) +} + +var _ SingletonModuleProviderContext = &Context{} +var _ SingletonModuleProviderContext = SingletonContext(nil) + +// SingletonModuleProvider reads the provider for the given module. If the provider has been set the value is +// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned +// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider. +// +// SingletonModuleProviderContext is a helper interface that accepts Context or SingletonContext. +func SingletonModuleProvider[K any](ctx SingletonModuleProviderContext, module Module, provider ProviderKey[K]) (K, bool) { + value, ok := ctx.ModuleProvider(module, provider) + if !ok { + var k K + return k, false + } + return value.(K), ok +} + +// ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext for use in ModuleProvider. +type ModuleProviderContext interface { + Provider(provider AnyProviderKey) (any, bool) +} + +var _ ModuleProviderContext = BaseModuleContext(nil) +var _ ModuleProviderContext = ModuleContext(nil) +var _ ModuleProviderContext = BottomUpMutatorContext(nil) +var _ ModuleProviderContext = TopDownMutatorContext(nil) + +// ModuleProvider reads the provider for the current module. If the provider has been set the value is +// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned +// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider. +// +// ModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext. +func ModuleProvider[K any](ctx ModuleProviderContext, provider ProviderKey[K]) (K, bool) { + value, ok := ctx.Provider(provider) + if !ok { + var k K + return k, false + } + return value.(K), ok +} + +// SetProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext for use in SetProvider. +type SetProviderContext interface { + SetProvider(provider AnyProviderKey, value any) +} + +var _ SetProviderContext = BaseModuleContext(nil) +var _ SetProviderContext = ModuleContext(nil) +var _ SetProviderContext = BottomUpMutatorContext(nil) +var _ SetProviderContext = TopDownMutatorContext(nil) + +// SetProvider sets the value for a provider for the current module. It panics if not called +// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value +// is not of the appropriate type, or if the value has already been set. The value should not +// be modified after being passed to SetProvider. +// +// SetProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or +// TopDownMutatorContext. +func SetProvider[K any](ctx SetProviderContext, provider ProviderKey[K], value K) { + ctx.SetProvider(provider, value) +} diff --git a/provider_test.go b/provider_test.go index 4038eae..8c02a75 100644 --- a/provider_test.go +++ b/provider_test.go @@ -46,31 +46,35 @@ type providerTestGenerateBuildActionsInfo struct { type providerTestUnsetInfo string -var providerTestMutatorInfoProvider = NewMutatorProvider(&providerTestMutatorInfo{}, "provider_mutator") -var providerTestGenerateBuildActionsInfoProvider = NewProvider(&providerTestGenerateBuildActionsInfo{}) -var providerTestUnsetInfoProvider = NewMutatorProvider((providerTestUnsetInfo)(""), "provider_mutator") -var providerTestUnusedMutatorProvider = NewMutatorProvider(&struct{ unused string }{}, "nonexistent_mutator") +var providerTestMutatorInfoProvider = NewMutatorProvider[*providerTestMutatorInfo]("provider_mutator") +var providerTestGenerateBuildActionsInfoProvider = NewProvider[*providerTestGenerateBuildActionsInfo]() +var providerTestUnsetInfoProvider = NewMutatorProvider[providerTestUnsetInfo]("provider_mutator") +var providerTestUnusedMutatorProvider = NewMutatorProvider[*struct{ unused string }]("nonexistent_mutator") func (p *providerTestModule) GenerateBuildActions(ctx ModuleContext) { - unset := ctx.Provider(providerTestUnsetInfoProvider).(providerTestUnsetInfo) + unset, ok := ModuleProvider(ctx, providerTestUnsetInfoProvider) + if ok { + panic(fmt.Errorf("expected false return value for providerTestGenerateBuildActionsInfoProvider before it was set")) + } if unset != "" { - panic(fmt.Sprintf("expected zero value for providerTestGenerateBuildActionsInfoProvider before it was set, got %q", + panic(fmt.Errorf("expected zero value for providerTestGenerateBuildActionsInfoProvider before it was set, got %q", unset)) } - _ = ctx.Provider(providerTestUnusedMutatorProvider) + // Verify reading providerTestUnusedMutatorProvider doesn't panic + _, _ = ModuleProvider(ctx, providerTestUnusedMutatorProvider) - ctx.SetProvider(providerTestGenerateBuildActionsInfoProvider, &providerTestGenerateBuildActionsInfo{ + SetProvider(ctx, providerTestGenerateBuildActionsInfoProvider, &providerTestGenerateBuildActionsInfo{ Value: ctx.ModuleName(), }) - mp := ctx.Provider(providerTestMutatorInfoProvider).(*providerTestMutatorInfo) - if mp != nil { + mp, ok := ModuleProvider(ctx, providerTestMutatorInfoProvider) + if ok { p.mutatorProviderValues = mp.Values } ctx.VisitDirectDeps(func(module Module) { - gbap := ctx.OtherModuleProvider(module, providerTestGenerateBuildActionsInfoProvider).(*providerTestGenerateBuildActionsInfo) + gbap, _ := OtherModuleProvider(ctx, module, providerTestGenerateBuildActionsInfoProvider) if gbap != nil { p.generateBuildActionsProviderValues = append(p.generateBuildActionsProviderValues, gbap.Value) } @@ -87,19 +91,20 @@ func providerTestMutator(ctx BottomUpMutatorContext) { values := []string{strings.ToLower(ctx.ModuleName())} ctx.VisitDirectDeps(func(module Module) { - mp := ctx.OtherModuleProvider(module, providerTestMutatorInfoProvider).(*providerTestMutatorInfo) + mp, _ := OtherModuleProvider(ctx, module, providerTestMutatorInfoProvider) if mp != nil { values = append(values, mp.Values...) } }) - ctx.SetProvider(providerTestMutatorInfoProvider, &providerTestMutatorInfo{ + SetProvider(ctx, providerTestMutatorInfoProvider, &providerTestMutatorInfo{ Values: values, }) } func providerTestAfterMutator(ctx BottomUpMutatorContext) { - _ = ctx.Provider(providerTestMutatorInfoProvider) + // Verify reading providerTestUnusedMutatorProvider doesn't panic + _, _ = ModuleProvider(ctx, providerTestMutatorInfoProvider) } func TestProviders(t *testing.T) { @@ -167,8 +172,8 @@ func TestProviders(t *testing.T) { type invalidProviderUsageMutatorInfo string type invalidProviderUsageGenerateBuildActionsInfo string -var invalidProviderUsageMutatorInfoProvider = NewMutatorProvider(invalidProviderUsageMutatorInfo(""), "mutator_under_test") -var invalidProviderUsageGenerateBuildActionsInfoProvider = NewProvider(invalidProviderUsageGenerateBuildActionsInfo("")) +var invalidProviderUsageMutatorInfoProvider = NewMutatorProvider[invalidProviderUsageMutatorInfo]("mutator_under_test") +var invalidProviderUsageGenerateBuildActionsInfoProvider = NewProvider[invalidProviderUsageGenerateBuildActionsInfo]() type invalidProviderUsageTestModule struct { parent *invalidProviderUsageTestModule @@ -209,11 +214,11 @@ func invalidProviderUsageBeforeMutator(ctx BottomUpMutatorContext) { if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok { if i.properties.Early_mutator_set_of_mutator_provider { // A mutator attempting to set the value of a provider associated with a later mutator. - ctx.SetProvider(invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) + SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) } if i.properties.Early_mutator_get_of_mutator_provider { // A mutator attempting to get the value of a provider associated with a later mutator. - _ = ctx.Provider(invalidProviderUsageMutatorInfoProvider) + _, _ = ModuleProvider(ctx, invalidProviderUsageMutatorInfoProvider) } } } @@ -222,18 +227,18 @@ func invalidProviderUsageMutatorUnderTest(ctx TopDownMutatorContext) { if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok { if i.properties.Early_mutator_set_of_build_actions_provider { // A mutator attempting to set the value of a non-mutator provider. - ctx.SetProvider(invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo("")) + SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo("")) } if i.properties.Early_mutator_get_of_build_actions_provider { // A mutator attempting to get the value of a non-mutator provider. - _ = ctx.Provider(invalidProviderUsageGenerateBuildActionsInfoProvider) + _, _ = ModuleProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider) } if i.properties.Early_module_get_of_mutator_provider { // A mutator attempting to get the value of a provider associated with this mutator on // a module for which this mutator hasn't run. This is a top down mutator so // dependencies haven't run yet. ctx.VisitDirectDeps(func(module Module) { - _ = ctx.OtherModuleProvider(module, invalidProviderUsageMutatorInfoProvider) + _, _ = OtherModuleProvider(ctx, module, invalidProviderUsageMutatorInfoProvider) }) } } @@ -243,11 +248,11 @@ func invalidProviderUsageAfterMutator(ctx BottomUpMutatorContext) { if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok { if i.properties.Late_mutator_set_of_mutator_provider { // A mutator trying to set the value of a provider associated with an earlier mutator. - ctx.SetProvider(invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) + SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) } if i.properties.Late_mutator_set_of_mutator_provider { // A mutator trying to set the value of a provider associated with an earlier mutator. - ctx.SetProvider(invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) + SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) } } } @@ -255,16 +260,16 @@ func invalidProviderUsageAfterMutator(ctx BottomUpMutatorContext) { func (i *invalidProviderUsageTestModule) GenerateBuildActions(ctx ModuleContext) { if i.properties.Late_build_actions_set_of_mutator_provider { // A GenerateBuildActions trying to set the value of a provider associated with a mutator. - ctx.SetProvider(invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) + SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) } if i.properties.Early_module_get_of_build_actions_provider { // A GenerateBuildActions trying to get the value of a provider on a module for which // GenerateBuildActions hasn't run. - _ = ctx.OtherModuleProvider(i.parent, invalidProviderUsageGenerateBuildActionsInfoProvider) + _, _ = OtherModuleProvider(ctx, i.parent, invalidProviderUsageGenerateBuildActionsInfoProvider) } if i.properties.Duplicate_set { - ctx.SetProvider(invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo("")) - ctx.SetProvider(invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo("")) + SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo("")) + SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo("")) } } diff --git a/singleton_ctx.go b/singleton_ctx.go index 176aa25..e600cfd 100644 --- a/singleton_ctx.go +++ b/singleton_ctx.go @@ -52,10 +52,7 @@ type SingletonContext interface { // return value can always be type-asserted to the type of the provider. The return value should // always be considered read-only. It panics if called before the appropriate mutator or // GenerateBuildActions pass for the provider on the module. - ModuleProvider(module Module, provider ProviderKey) interface{} - - // ModuleHasProvider returns true if the provider for the given module has been set. - ModuleHasProvider(m Module, provider ProviderKey) bool + ModuleProvider(module Module, provider AnyProviderKey) (any, bool) // ModuleErrorf reports an error at the line number of the module type in the module definition. ModuleErrorf(module Module, format string, args ...interface{}) @@ -202,15 +199,10 @@ func (s *singletonContext) ModuleType(logicModule Module) string { return s.context.ModuleType(logicModule) } -func (s *singletonContext) ModuleProvider(logicModule Module, provider ProviderKey) interface{} { +func (s *singletonContext) ModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) { return s.context.ModuleProvider(logicModule, provider) } -// ModuleHasProvider returns true if the provider for the given module has been set. -func (s *singletonContext) ModuleHasProvider(logicModule Module, provider ProviderKey) bool { - return s.context.ModuleHasProvider(logicModule, provider) -} - func (s *singletonContext) BlueprintFile(logicModule Module) string { return s.context.BlueprintFile(logicModule) } diff --git a/source_file_provider.go b/source_file_provider.go index 6ee4d09..bf48dc6 100644 --- a/source_file_provider.go +++ b/source_file_provider.go @@ -4,4 +4,4 @@ type SrcsFileProviderData struct { SrcPaths []string } -var SrcsFileProviderKey = NewProvider(SrcsFileProviderData{}) +var SrcsFileProviderKey = NewProvider[SrcsFileProviderData]()