Merge "android:path attribute is respected for fields in a slice of struct"

This commit is contained in:
Treehugger Robot 2021-02-24 00:54:56 +00:00 committed by Gerrit Code Review
commit 4dc0702ce2
2 changed files with 89 additions and 35 deletions

View file

@ -76,8 +76,9 @@ func pathPropertiesForPropertyStruct(ps interface{}) []string {
var ret []string
for _, i := range pathPropertyIndexes {
// Turn an index into a field.
sv := fieldByIndex(v, i)
var values []reflect.Value
fieldsByIndex(v, i, &values)
for _, sv := range values {
if !sv.IsValid() {
// Skip properties inside a nil pointer.
continue
@ -102,26 +103,46 @@ func pathPropertiesForPropertyStruct(ps interface{}) []string {
v.Type().FieldByIndex(i).Name, v.Type(), sv.Type()))
}
}
}
return ret
}
// fieldByIndex is like reflect.Value.FieldByIndex, but returns an invalid reflect.Value when
// traversing a nil pointer to a struct.
func fieldByIndex(v reflect.Value, index []int) reflect.Value {
// fieldsByIndex is similar to reflect.Value.FieldByIndex, but is more robust: it doesn't track
// nil pointers and it returns multiple values when there's slice of struct.
func fieldsByIndex(v reflect.Value, index []int, values *[]reflect.Value) {
// leaf case
if len(index) == 1 {
return v.Field(index[0])
if isSliceOfStruct(v) {
for i := 0; i < v.Len(); i++ {
*values = append(*values, v.Index(i).Field(index[0]))
}
for _, x := range index {
} else {
*values = append(*values, v.Field(index[0]))
}
return
}
// recursion
if v.Kind() == reflect.Ptr {
// don't track nil pointer
if v.IsNil() {
return reflect.Value{}
return
}
v = v.Elem()
} else if isSliceOfStruct(v) {
// do the recursion for all elements
for i := 0; i < v.Len(); i++ {
fieldsByIndex(v.Index(i).Field(index[0]), index[1:], values)
}
v = v.Field(x)
return
}
return v
fieldsByIndex(v.Field(index[0]), index[1:], values)
return
}
func isSliceOfStruct(v reflect.Value) bool {
return v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Struct
}
var pathPropertyIndexesCache OncePer

View file

@ -33,12 +33,21 @@ type pathDepsMutatorTestModule struct {
Foo string `android:"path"`
}
// nested slices of struct
props3 struct {
X []struct {
Y []struct {
Z []string `android:"path"`
}
}
}
sourceDeps []string
}
func pathDepsMutatorTestModuleFactory() Module {
module := &pathDepsMutatorTestModule{}
module.AddProperties(&module.props, &module.props2)
module.AddProperties(&module.props, &module.props2, &module.props3)
InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
return module
}
@ -73,8 +82,20 @@ func TestPathDepsMutator(t *testing.T) {
bar: [":b"],
baz: ":c{.bar}",
qux: ":d",
x: [
{
y: [
{
z: [":x", ":y"],
},
{
z: [":z"],
},
],
},
],
}`,
deps: []string{"a", "b", "c"},
deps: []string{"a", "b", "c", "x", "y", "z"},
},
{
name: "arch variant",
@ -113,6 +134,18 @@ func TestPathDepsMutator(t *testing.T) {
filegroup {
name: "d",
}
filegroup {
name: "x",
}
filegroup {
name: "y",
}
filegroup {
name: "z",
}
`
config := TestArchConfig(buildDir, nil, bp, nil)