Export ConfigurableCase and add constructors

Some soong code sets arch-variant properties in order to control a
module's default behavior. I'll make this continue to work, but long
term the arch-variant properties should be replaced with selects,
so expose an API for creating select statements in soong code.

Bug: 323382414
Test: m nothing --no-skip-soong-tests
Change-Id: I6c65d6e112b6f826f1027777b6fdf36915d34b1d
This commit is contained in:
Cole Faust 2024-04-23 13:50:40 -07:00
parent d7474dd743
commit 185cb44bef
4 changed files with 94 additions and 53 deletions

View file

@ -14,6 +14,7 @@
package proptools
import (
"fmt"
"reflect"
"slices"
"strconv"
@ -152,13 +153,33 @@ func (v *configurablePatternType) String() string {
}
}
type configurablePattern struct {
type ConfigurablePattern struct {
typ configurablePatternType
stringValue string
boolValue bool
}
func (p *configurablePattern) matchesValue(v ConfigurableValue) bool {
func NewStringConfigurablePattern(s string) ConfigurablePattern {
return ConfigurablePattern{
typ: configurablePatternTypeString,
stringValue: s,
}
}
func NewBoolConfigurablePattern(b bool) ConfigurablePattern {
return ConfigurablePattern{
typ: configurablePatternTypeBool,
boolValue: b,
}
}
func NewDefaultConfigurablePattern() ConfigurablePattern {
return ConfigurablePattern{
typ: configurablePatternTypeDefault,
}
}
func (p *ConfigurablePattern) matchesValue(v ConfigurableValue) bool {
if p.typ == configurablePatternTypeDefault {
return true
}
@ -178,7 +199,7 @@ func (p *configurablePattern) matchesValue(v ConfigurableValue) bool {
}
}
func (p *configurablePattern) matchesValueType(v ConfigurableValue) bool {
func (p *ConfigurablePattern) matchesValueType(v ConfigurableValue) bool {
if p.typ == configurablePatternTypeDefault {
return true
}
@ -188,25 +209,32 @@ func (p *configurablePattern) matchesValueType(v ConfigurableValue) bool {
return p.typ == v.typ.patternType()
}
type configurableCase[T ConfigurableElements] struct {
patterns []configurablePattern
type ConfigurableCase[T ConfigurableElements] struct {
patterns []ConfigurablePattern
value *T
}
func (c *configurableCase[T]) Clone() configurableCase[T] {
return configurableCase[T]{
func (c *ConfigurableCase[T]) Clone() ConfigurableCase[T] {
return ConfigurableCase[T]{
patterns: slices.Clone(c.patterns),
value: copyConfiguredValue(c.value),
}
}
type configurableCaseReflection interface {
initialize(patterns []configurablePattern, value interface{})
initialize(patterns []ConfigurablePattern, value interface{})
}
var _ configurableCaseReflection = &configurableCase[string]{}
var _ configurableCaseReflection = &ConfigurableCase[string]{}
func (c *configurableCase[T]) initialize(patterns []configurablePattern, value interface{}) {
func NewConfigurableCase[T ConfigurableElements](patterns []ConfigurablePattern, value *T) ConfigurableCase[T] {
return ConfigurableCase[T]{
patterns: patterns,
value: value,
}
}
func (c *ConfigurableCase[T]) initialize(patterns []ConfigurablePattern, value interface{}) {
c.patterns = patterns
c.value = value.(*T)
}
@ -217,13 +245,13 @@ func configurableCaseType(configuredType reflect.Type) reflect.Type {
// current reflection apis unfortunately
switch configuredType.Kind() {
case reflect.String:
return reflect.TypeOf(configurableCase[string]{})
return reflect.TypeOf(ConfigurableCase[string]{})
case reflect.Bool:
return reflect.TypeOf(configurableCase[bool]{})
return reflect.TypeOf(ConfigurableCase[bool]{})
case reflect.Slice:
switch configuredType.Elem().Kind() {
case reflect.String:
return reflect.TypeOf(configurableCase[[]string]{})
return reflect.TypeOf(ConfigurableCase[[]string]{})
}
}
panic("unimplemented")
@ -259,13 +287,26 @@ type Configurable[T ConfigurableElements] struct {
marker configurableMarker
propertyName string
conditions []ConfigurableCondition
cases []configurableCase[T]
cases []ConfigurableCase[T]
appendWrapper *appendWrapper[T]
}
// Ignore the warning about the unused marker variable, it's used via reflection
var _ configurableMarker = Configurable[string]{}.marker
func NewConfigurable[T ConfigurableElements](conditions []ConfigurableCondition, cases []ConfigurableCase[T]) Configurable[T] {
for _, c := range cases {
if len(c.patterns) != len(conditions) {
panic(fmt.Sprintf("All configurables cases must have as many patterns as the configurable has conditions. Expected: %d, found: %d", len(conditions), len(c.patterns)))
}
}
return Configurable[T]{
conditions: conditions,
cases: cases,
appendWrapper: &appendWrapper[T]{},
}
}
// appendWrapper exists so that we can set the value of append
// from a non-pointer method receiver. (setAppend)
type appendWrapper[T ConfigurableElements] struct {
@ -424,7 +465,7 @@ var _ configurablePtrReflection = &Configurable[string]{}
func (c *Configurable[T]) initialize(propertyName string, conditions []ConfigurableCondition, cases any) {
c.propertyName = propertyName
c.conditions = conditions
c.cases = cases.([]configurableCase[T])
c.cases = cases.([]ConfigurableCase[T])
c.appendWrapper = &appendWrapper[T]{}
}
@ -468,7 +509,7 @@ func (c *Configurable[T]) clone() *Configurable[T] {
conditionsCopy := make([]ConfigurableCondition, len(c.conditions))
copy(conditionsCopy, c.conditions)
casesCopy := make([]configurableCase[T], len(c.cases))
casesCopy := make([]ConfigurableCase[T], len(c.cases))
for i, case_ := range c.cases {
casesCopy[i] = case_.Clone()
}

View file

@ -1265,8 +1265,8 @@ func appendPropertiesTestCases() []appendPropertyTestCase {
"foo",
},
}},
cases: []configurableCase[[]string]{{
patterns: []configurablePattern{{
cases: []ConfigurableCase[[]string]{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "a",
}},
@ -1283,8 +1283,8 @@ func appendPropertiesTestCases() []appendPropertyTestCase {
"bar",
},
}},
cases: []configurableCase[[]string]{{
patterns: []configurablePattern{{
cases: []ConfigurableCase[[]string]{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "b",
}},
@ -1302,8 +1302,8 @@ func appendPropertiesTestCases() []appendPropertyTestCase {
"foo",
},
}},
cases: []configurableCase[[]string]{{
patterns: []configurablePattern{{
cases: []ConfigurableCase[[]string]{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "a",
}},
@ -1317,8 +1317,8 @@ func appendPropertiesTestCases() []appendPropertyTestCase {
"bar",
},
}},
cases: []configurableCase[[]string]{{
patterns: []configurablePattern{{
cases: []ConfigurableCase[[]string]{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "b",
}},
@ -1342,8 +1342,8 @@ func appendPropertiesTestCases() []appendPropertyTestCase {
"foo",
},
}},
cases: []configurableCase[[]string]{{
patterns: []configurablePattern{{
cases: []ConfigurableCase[[]string]{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "a",
}},
@ -1360,8 +1360,8 @@ func appendPropertiesTestCases() []appendPropertyTestCase {
"bar",
},
}},
cases: []configurableCase[[]string]{{
patterns: []configurablePattern{{
cases: []ConfigurableCase[[]string]{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "b",
}},
@ -1378,8 +1378,8 @@ func appendPropertiesTestCases() []appendPropertyTestCase {
"bar",
},
}},
cases: []configurableCase[[]string]{{
patterns: []configurablePattern{{
cases: []ConfigurableCase[[]string]{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "b",
}},
@ -1394,8 +1394,8 @@ func appendPropertiesTestCases() []appendPropertyTestCase {
"foo",
},
}},
cases: []configurableCase[[]string]{{
patterns: []configurablePattern{{
cases: []ConfigurableCase[[]string]{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "a",
}},

View file

@ -356,7 +356,7 @@ func (ctx *unpackContext) unpackToConfigurable(propertyName string, property *pa
}
result := Configurable[string]{
propertyName: property.Name,
cases: []configurableCase[string]{{
cases: []ConfigurableCase[string]{{
value: &v.Value,
}},
appendWrapper: &appendWrapper[string]{},
@ -373,7 +373,7 @@ func (ctx *unpackContext) unpackToConfigurable(propertyName string, property *pa
}
result := Configurable[bool]{
propertyName: property.Name,
cases: []configurableCase[bool]{{
cases: []ConfigurableCase[bool]{{
value: &v.Value,
}},
appendWrapper: &appendWrapper[bool]{},
@ -407,7 +407,7 @@ func (ctx *unpackContext) unpackToConfigurable(propertyName string, property *pa
}
result := Configurable[[]string]{
propertyName: property.Name,
cases: []configurableCase[[]string]{{
cases: []ConfigurableCase[[]string]{{
value: &value,
}},
appendWrapper: &appendWrapper[[]string]{},
@ -446,7 +446,7 @@ func (ctx *unpackContext) unpackToConfigurable(propertyName string, property *pa
Value: c.Value,
}
patterns := make([]configurablePattern, len(c.Patterns))
patterns := make([]ConfigurablePattern, len(c.Patterns))
for i, pat := range c.Patterns {
switch pat := pat.(type) {
case *parser.String:

View file

@ -734,7 +734,7 @@ var validUnpackTestCases = []struct {
}{
Foo: Configurable[string]{
propertyName: "foo",
cases: []configurableCase[string]{{
cases: []ConfigurableCase[string]{{
value: StringPtr("bar"),
}},
appendWrapper: &appendWrapper[string]{},
@ -755,7 +755,7 @@ var validUnpackTestCases = []struct {
}{
Foo: Configurable[bool]{
propertyName: "foo",
cases: []configurableCase[bool]{{
cases: []ConfigurableCase[bool]{{
value: BoolPtr(true),
}},
appendWrapper: &appendWrapper[bool]{},
@ -776,7 +776,7 @@ var validUnpackTestCases = []struct {
}{
Foo: Configurable[[]string]{
propertyName: "foo",
cases: []configurableCase[[]string]{{
cases: []ConfigurableCase[[]string]{{
value: &[]string{"a", "b"},
}},
appendWrapper: &appendWrapper[[]string]{},
@ -808,23 +808,23 @@ var validUnpackTestCases = []struct {
"my_variable",
},
}},
cases: []configurableCase[string]{
cases: []ConfigurableCase[string]{
{
patterns: []configurablePattern{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "a",
}},
value: StringPtr("a2"),
},
{
patterns: []configurablePattern{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "b",
}},
value: StringPtr("b2"),
},
{
patterns: []configurablePattern{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeDefault,
}},
value: StringPtr("c2"),
@ -863,23 +863,23 @@ var validUnpackTestCases = []struct {
"my_variable",
},
}},
cases: []configurableCase[string]{
cases: []ConfigurableCase[string]{
{
patterns: []configurablePattern{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "a",
}},
value: StringPtr("a2"),
},
{
patterns: []configurablePattern{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "b",
}},
value: StringPtr("b2"),
},
{
patterns: []configurablePattern{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeDefault,
}},
value: StringPtr("c2"),
@ -895,23 +895,23 @@ var validUnpackTestCases = []struct {
"my_2nd_variable",
},
}},
cases: []configurableCase[string]{
cases: []ConfigurableCase[string]{
{
patterns: []configurablePattern{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "d",
}},
value: StringPtr("d2"),
},
{
patterns: []configurablePattern{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeString,
stringValue: "e",
}},
value: StringPtr("e2"),
},
{
patterns: []configurablePattern{{
patterns: []ConfigurablePattern{{
typ: configurablePatternTypeDefault,
}},
value: StringPtr("f2"),
@ -941,7 +941,7 @@ var validUnpackTestCases = []struct {
}{
Foo: Configurable[string]{
propertyName: "foo",
cases: []configurableCase[string]{
cases: []ConfigurableCase[string]{
{
value: StringPtr("asdf"),
},
@ -950,7 +950,7 @@ var validUnpackTestCases = []struct {
},
Bar: Configurable[bool]{
propertyName: "bar",
cases: []configurableCase[bool]{
cases: []ConfigurableCase[bool]{
{
value: BoolPtr(true),
},