Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4dc0702c authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

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

parents bb96b56b 66dd5c09
Loading
Loading
Loading
Loading
+54 −33
Original line number Diff line number Diff line
@@ -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]))
			}
		} else {
			*values = append(*values, v.Field(index[0]))
		}
		return
	}
	for _, x := range index {

	// 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)
		}
		return
	}
		v = v.Field(x)
	fieldsByIndex(v.Field(index[0]), index[1:], values)
	return
}
	return v

func isSliceOfStruct(v reflect.Value) bool {
	return v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Struct
}

var pathPropertyIndexesCache OncePer
+35 −2
Original line number Diff line number Diff line
@@ -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)