Add configurable property support to neverallow

Bug: 362579941
Test: m nothing --no-skip-soong-tests
Change-Id: I50b8bf3cc2e3520a12932b0a0e1041e079379590
This commit is contained in:
Cole Faust
2024-08-27 15:47:06 -07:00
parent 08c7f86575
commit 5b35cb9aef

View File

@@ -287,7 +287,7 @@ func neverallowMutator(ctx BottomUpMutatorContext) {
continue continue
} }
if !n.appliesToProperties(properties) { if !n.appliesToProperties(ctx, properties) {
continue continue
} }
@@ -604,9 +604,9 @@ func (r *rule) appliesToModuleType(moduleType string) bool {
return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes) return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
} }
func (r *rule) appliesToProperties(properties []interface{}) bool { func (r *rule) appliesToProperties(ctx BottomUpMutatorContext, properties []interface{}) bool {
includeProps := hasAllProperties(properties, r.props) includeProps := hasAllProperties(ctx, properties, r.props)
excludeProps := hasAnyProperty(properties, r.unlessProps) excludeProps := hasAnyProperty(ctx, properties, r.unlessProps)
return includeProps && !excludeProps return includeProps && !excludeProps
} }
@@ -644,25 +644,25 @@ func fieldNamesForProperties(propertyNames string) []string {
return names return names
} }
func hasAnyProperty(properties []interface{}, props []ruleProperty) bool { func hasAnyProperty(ctx BottomUpMutatorContext, properties []interface{}, props []ruleProperty) bool {
for _, v := range props { for _, v := range props {
if hasProperty(properties, v) { if hasProperty(ctx, properties, v) {
return true return true
} }
} }
return false return false
} }
func hasAllProperties(properties []interface{}, props []ruleProperty) bool { func hasAllProperties(ctx BottomUpMutatorContext, properties []interface{}, props []ruleProperty) bool {
for _, v := range props { for _, v := range props {
if !hasProperty(properties, v) { if !hasProperty(ctx, properties, v) {
return false return false
} }
} }
return true return true
} }
func hasProperty(properties []interface{}, prop ruleProperty) bool { func hasProperty(ctx BottomUpMutatorContext, properties []interface{}, prop ruleProperty) bool {
for _, propertyStruct := range properties { for _, propertyStruct := range properties {
propertiesValue := reflect.ValueOf(propertyStruct).Elem() propertiesValue := reflect.ValueOf(propertyStruct).Elem()
for _, v := range prop.fields { for _, v := range prop.fields {
@@ -679,14 +679,14 @@ func hasProperty(properties []interface{}, prop ruleProperty) bool {
return prop.matcher.Test(value) return prop.matcher.Test(value)
} }
if matchValue(propertiesValue, check) { if matchValue(ctx, propertiesValue, check) {
return true return true
} }
} }
return false return false
} }
func matchValue(value reflect.Value, check func(string) bool) bool { func matchValue(ctx BottomUpMutatorContext, value reflect.Value, check func(string) bool) bool {
if !value.IsValid() { if !value.IsValid() {
return false return false
} }
@@ -698,19 +698,26 @@ func matchValue(value reflect.Value, check func(string) bool) bool {
value = value.Elem() value = value.Elem()
} }
switch value.Kind() { switch v := value.Interface().(type) {
case reflect.String: case string:
return check(value.String()) return check(v)
case reflect.Bool: case bool:
return check(strconv.FormatBool(value.Bool())) return check(strconv.FormatBool(v))
case reflect.Int: case int:
return check(strconv.FormatInt(value.Int(), 10)) return check(strconv.FormatInt((int64)(v), 10))
case reflect.Slice: case []string:
slice, ok := value.Interface().([]string) for _, v := range v {
if !ok { if check(v) {
panic("Can only handle slice of string") return true
}
} }
for _, v := range slice { return false
case proptools.Configurable[string]:
return check(v.GetOrDefault(ctx, ""))
case proptools.Configurable[bool]:
return check(strconv.FormatBool(v.GetOrDefault(ctx, false)))
case proptools.Configurable[[]string]:
for _, v := range v.GetOrDefault(ctx, nil) {
if check(v) { if check(v) {
return true return true
} }