Refactor prebuilt to use srcs supplier function
Previously, prebuilt had two ways to provide the src value, as a pointer to an []string and using reflection. That meant that any code that needed to check the src to use had to understand the two ways of accessing it. This change refactors the code to abstract the origin of the src values being a supplier function. That insulates the callers from having to know the details and makes it easy to add new suppliers in future. Test: m nothing Bug: 142918168 Change-Id: I5cc7517c46cce96924c9f34ba1b046b468f7684a
This commit is contained in:
parent
843f09723b
commit
dcb4bd6fb4
1 changed files with 84 additions and 55 deletions
|
@ -50,12 +50,9 @@ type PrebuiltProperties struct {
|
||||||
|
|
||||||
type Prebuilt struct {
|
type Prebuilt struct {
|
||||||
properties PrebuiltProperties
|
properties PrebuiltProperties
|
||||||
module Module
|
|
||||||
srcs *[]string
|
|
||||||
|
|
||||||
// Metadata for single source Prebuilt modules.
|
srcsSupplier PrebuiltSrcsSupplier
|
||||||
srcProps reflect.Value
|
srcsPropertyName string
|
||||||
srcField reflect.StructField
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Prebuilt) Name(name string) string {
|
func (p *Prebuilt) Name(name string) string {
|
||||||
|
@ -72,31 +69,26 @@ func (p *Prebuilt) ForcePrefer() {
|
||||||
// preference configs. We'll want to add native support for dynamic source cases if we end up having
|
// preference configs. We'll want to add native support for dynamic source cases if we end up having
|
||||||
// more modules like this.
|
// more modules like this.
|
||||||
func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
|
func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
|
||||||
if p.srcs != nil {
|
if p.srcsSupplier != nil {
|
||||||
if len(*p.srcs) == 0 {
|
srcs := p.srcsSupplier()
|
||||||
ctx.PropertyErrorf("srcs", "missing prebuilt source file")
|
|
||||||
|
if len(srcs) == 0 {
|
||||||
|
ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*p.srcs) > 1 {
|
if len(srcs) > 1 {
|
||||||
ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
|
ctx.PropertyErrorf(p.srcsPropertyName, "multiple prebuilt source files")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the singleton source after expanding any filegroup in the
|
// Return the singleton source after expanding any filegroup in the
|
||||||
// sources.
|
// sources.
|
||||||
return PathForModuleSrc(ctx, (*p.srcs)[0])
|
src := srcs[0]
|
||||||
} else {
|
|
||||||
if !p.srcProps.IsValid() {
|
|
||||||
ctx.ModuleErrorf("prebuilt source was not set")
|
|
||||||
}
|
|
||||||
src := p.getSingleSourceFieldValue()
|
|
||||||
if src == "" {
|
|
||||||
ctx.PropertyErrorf(proptools.FieldNameForProperty(p.srcField.Name),
|
|
||||||
"missing prebuilt source file")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return PathForModuleSrc(ctx, src)
|
return PathForModuleSrc(ctx, src)
|
||||||
|
} else {
|
||||||
|
ctx.ModuleErrorf("prebuilt source was not set")
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,18 +96,80 @@ func (p *Prebuilt) UsePrebuilt() bool {
|
||||||
return p.properties.UsePrebuilt
|
return p.properties.UsePrebuilt
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
|
// Called to provide the srcs value for the prebuilt module.
|
||||||
|
//
|
||||||
|
// Return the src value or nil if it is not available.
|
||||||
|
type PrebuiltSrcsSupplier func() []string
|
||||||
|
|
||||||
|
// Initialize the module as a prebuilt module that uses the provided supplier to access the
|
||||||
|
// prebuilt sources of the module.
|
||||||
|
//
|
||||||
|
// The supplier will be called multiple times and must return the same values each time it
|
||||||
|
// is called. If it returns an empty array (or nil) then the prebuilt module will not be used
|
||||||
|
// as a replacement for a source module with the same name even if prefer = true.
|
||||||
|
//
|
||||||
|
// If the Prebuilt.SingleSourcePath() is called on the module then this must return an array
|
||||||
|
// containing exactly one source file.
|
||||||
|
//
|
||||||
|
// The provided property name is used to provide helpful error messages in the event that
|
||||||
|
// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided.
|
||||||
|
func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) {
|
||||||
p := module.Prebuilt()
|
p := module.Prebuilt()
|
||||||
module.AddProperties(&p.properties)
|
module.AddProperties(&p.properties)
|
||||||
p.srcs = srcs
|
|
||||||
|
if srcsSupplier == nil {
|
||||||
|
panic(fmt.Errorf("srcsSupplier must not be nil"))
|
||||||
|
}
|
||||||
|
if srcsPropertyName == "" {
|
||||||
|
panic(fmt.Errorf("srcsPropertyName must not be empty"))
|
||||||
|
}
|
||||||
|
|
||||||
|
p.srcsSupplier = srcsSupplier
|
||||||
|
p.srcsPropertyName = srcsPropertyName
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
|
||||||
|
if srcs == nil {
|
||||||
|
panic(fmt.Errorf("srcs must not be nil"))
|
||||||
|
}
|
||||||
|
|
||||||
|
srcsSupplier := func() []string {
|
||||||
|
return *srcs
|
||||||
|
}
|
||||||
|
|
||||||
|
InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) {
|
func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) {
|
||||||
p := module.Prebuilt()
|
srcPropsValue := reflect.ValueOf(srcProps).Elem()
|
||||||
module.AddProperties(&p.properties)
|
srcStructField, _ := srcPropsValue.Type().FieldByName(srcField)
|
||||||
p.srcProps = reflect.ValueOf(srcProps).Elem()
|
if !srcPropsValue.IsValid() || srcStructField.Name == "" {
|
||||||
p.srcField, _ = p.srcProps.Type().FieldByName(srcField)
|
panic(fmt.Errorf("invalid single source prebuilt %+v", module))
|
||||||
p.checkSingleSourceProperties()
|
}
|
||||||
|
|
||||||
|
if srcPropsValue.Kind() != reflect.Struct && srcPropsValue.Kind() != reflect.Interface {
|
||||||
|
panic(fmt.Errorf("invalid single source prebuilt %+v", srcProps))
|
||||||
|
}
|
||||||
|
|
||||||
|
srcFieldIndex := srcStructField.Index
|
||||||
|
srcPropertyName := proptools.PropertyNameForField(srcField)
|
||||||
|
|
||||||
|
srcsSupplier := func() []string {
|
||||||
|
value := srcPropsValue.FieldByIndex(srcFieldIndex)
|
||||||
|
if value.Kind() == reflect.Ptr {
|
||||||
|
value = value.Elem()
|
||||||
|
}
|
||||||
|
if value.Kind() != reflect.String {
|
||||||
|
panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one but was %d %q", srcPropertyName, value.Kind(), value))
|
||||||
|
}
|
||||||
|
src := value.String()
|
||||||
|
if src == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return []string{src}
|
||||||
|
}
|
||||||
|
|
||||||
|
InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcPropertyName)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PrebuiltInterface interface {
|
type PrebuiltInterface interface {
|
||||||
|
@ -152,7 +206,7 @@ func PrebuiltMutator(ctx BottomUpMutatorContext) {
|
||||||
func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
|
func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
|
||||||
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
|
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
|
||||||
p := m.Prebuilt()
|
p := m.Prebuilt()
|
||||||
if p.srcs == nil && !p.srcProps.IsValid() {
|
if p.srcsSupplier == nil {
|
||||||
panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
|
panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
|
||||||
}
|
}
|
||||||
if !p.properties.SourceExists {
|
if !p.properties.SourceExists {
|
||||||
|
@ -191,11 +245,7 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
|
||||||
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
|
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
|
||||||
// will be used if it is marked "prefer" or if the source module is disabled.
|
// will be used if it is marked "prefer" or if the source module is disabled.
|
||||||
func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
|
func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
|
||||||
if p.srcs != nil && len(*p.srcs) == 0 {
|
if p.srcsSupplier != nil && len(p.srcsSupplier()) == 0 {
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.srcProps.IsValid() && p.getSingleSourceFieldValue() == "" {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,24 +260,3 @@ func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
|
||||||
func (p *Prebuilt) SourceExists() bool {
|
func (p *Prebuilt) SourceExists() bool {
|
||||||
return p.properties.SourceExists
|
return p.properties.SourceExists
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Prebuilt) checkSingleSourceProperties() {
|
|
||||||
if !p.srcProps.IsValid() || p.srcField.Name == "" {
|
|
||||||
panic(fmt.Errorf("invalid single source prebuilt %+v", p))
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.srcProps.Kind() != reflect.Struct && p.srcProps.Kind() != reflect.Interface {
|
|
||||||
panic(fmt.Errorf("invalid single source prebuilt %+v", p.srcProps))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Prebuilt) getSingleSourceFieldValue() string {
|
|
||||||
value := p.srcProps.FieldByIndex(p.srcField.Index)
|
|
||||||
if value.Kind() == reflect.Ptr {
|
|
||||||
value = value.Elem()
|
|
||||||
}
|
|
||||||
if value.Kind() != reflect.String {
|
|
||||||
panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one", p.srcField.Name))
|
|
||||||
}
|
|
||||||
return value.String()
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue