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
This commit is contained in:
Colin Cross 2023-12-13 14:47:32 -08:00
parent 516ef4f48e
commit ed49204e85
7 changed files with 213 additions and 121 deletions

View file

@ -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 {

View file

@ -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 {

View file

@ -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
}
}

View file

@ -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)
}

View file

@ -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(""))
}
}

View file

@ -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)
}

View file

@ -4,4 +4,4 @@ type SrcsFileProviderData struct {
SrcPaths []string
}
var SrcsFileProviderKey = NewProvider(SrcsFileProviderData{})
var SrcsFileProviderKey = NewProvider[SrcsFileProviderData]()