From b1abbada6a08139651419bb48048add0b58eb3af Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 29 Apr 2021 20:16:40 -0700 Subject: [PATCH] Add support for setting string property in bpmodify Add a -str argument to set a property to a string value. Bug: 186723288 Test: bpmodify_test.go Change-Id: I490e3be182693c8720020814da579e6e788b3d9f --- bpmodify/bpmodify.go | 92 +++++++++++++++++++++++++++------------ bpmodify/bpmodify_test.go | 36 +++++++++++++++ 2 files changed, 100 insertions(+), 28 deletions(-) diff --git a/bpmodify/bpmodify.go b/bpmodify/bpmodify.go index 0190f19..29d28f0 100644 --- a/bpmodify/bpmodify.go +++ b/bpmodify/bpmodify.go @@ -30,6 +30,8 @@ var ( targetedProperty = new(qualifiedProperty) addIdents = new(identSet) removeIdents = new(identSet) + + setString *string ) func init() { @@ -38,6 +40,7 @@ func init() { flag.Var(targetedProperty, "property", "fully qualified `name` of property to modify (default \"deps\")") flag.Var(addIdents, "a", "comma or whitespace separated list of identifiers to add") flag.Var(removeIdents, "r", "comma or whitespace separated list of identifiers to remove") + flag.Var(stringPtrFlag{&setString}, "str", "set a string property") flag.Usage = usage } @@ -147,14 +150,18 @@ func processModule(module *parser.Module, moduleName string, return false, []error{err} } if prop == nil { - if len(addIdents.idents) == 0 { + if len(addIdents.idents) > 0 { + // We are adding something to a non-existing list prop, so we need to create it first. + prop, modified, err = createRecursiveProperty(module, targetedProperty.name(), targetedProperty.prefixes(), &parser.List{}) + } else if setString != nil { + // We setting a non-existent string property, so we need to create it first. + prop, modified, err = createRecursiveProperty(module, targetedProperty.name(), targetedProperty.prefixes(), &parser.String{}) + } else { // We cannot find an existing prop, and we aren't adding anything to the prop, // which means we must be removing something from a non-existing prop, // which means this is a noop. return false, nil } - // Else we are adding something to a non-existing prop, so we need to create it first. - prop, modified, err = createRecursiveProperty(module, targetedProperty.name(), targetedProperty.prefixes()) if err != nil { // Here should be unreachable, but still handle it for completeness. return false, []error{err} @@ -166,16 +173,18 @@ func processModule(module *parser.Module, moduleName string, } func getRecursiveProperty(module *parser.Module, name string, prefixes []string) (prop *parser.Property, err error) { - prop, _, err = getOrCreateRecursiveProperty(module, name, prefixes, false) + prop, _, err = getOrCreateRecursiveProperty(module, name, prefixes, nil) return prop, err } -func createRecursiveProperty(module *parser.Module, name string, prefixes []string) (prop *parser.Property, modified bool, err error) { - return getOrCreateRecursiveProperty(module, name, prefixes, true) +func createRecursiveProperty(module *parser.Module, name string, prefixes []string, + empty parser.Expression) (prop *parser.Property, modified bool, err error) { + + return getOrCreateRecursiveProperty(module, name, prefixes, empty) } func getOrCreateRecursiveProperty(module *parser.Module, name string, prefixes []string, - createIfNotFound bool) (prop *parser.Property, modified bool, err error) { + empty parser.Expression) (prop *parser.Property, modified bool, err error) { m := &module.Map for i, prefix := range prefixes { if prop, found := m.GetProperty(prefix); found { @@ -187,7 +196,7 @@ func getOrCreateRecursiveProperty(module *parser.Module, name string, prefixes [ return nil, false, fmt.Errorf("Expected property %q to be a map, found %s", strings.Join(prefixes[:i+1], "."), prop.Value.Type()) } - } else if createIfNotFound { + } else if empty != nil { mm := &parser.Map{} m.Properties = append(m.Properties, &parser.Property{Name: prefix, Value: mm}) m = mm @@ -201,8 +210,8 @@ func getOrCreateRecursiveProperty(module *parser.Module, name string, prefixes [ if prop, found := m.GetProperty(name); found { // We've found a property in the AST, which must mean we didn't modify the AST. return prop, false, nil - } else if createIfNotFound { - prop = &parser.Property{Name: name, Value: &parser.List{}} + } else if empty != nil { + prop = &parser.Property{Name: name, Value: empty} m.Properties = append(m.Properties, prop) return prop, true, nil } else { @@ -222,26 +231,37 @@ func processParameter(value parser.Expression, paramName, moduleName string, paramName, moduleName)} } - list, ok := value.(*parser.List) - if !ok { - return false, []error{fmt.Errorf("expected parameter %s in module %s to be list, found %s", - paramName, moduleName, value.Type().String())} - } + if len(addIdents.idents) > 0 || len(removeIdents.idents) > 0 { + list, ok := value.(*parser.List) + if !ok { + return false, []error{fmt.Errorf("expected parameter %s in module %s to be list, found %s", + paramName, moduleName, value.Type().String())} + } - wasSorted := parser.ListIsSorted(list) + wasSorted := parser.ListIsSorted(list) - for _, a := range addIdents.idents { - m := parser.AddStringToList(list, a) - modified = modified || m - } + for _, a := range addIdents.idents { + m := parser.AddStringToList(list, a) + modified = modified || m + } - for _, r := range removeIdents.idents { - m := parser.RemoveStringFromList(list, r) - modified = modified || m - } + for _, r := range removeIdents.idents { + m := parser.RemoveStringFromList(list, r) + modified = modified || m + } - if (wasSorted || *sortLists) && modified { - parser.SortList(file, list) + if (wasSorted || *sortLists) && modified { + parser.SortList(file, list) + } + } else if setString != nil { + str, ok := value.(*parser.String) + if !ok { + return false, []error{fmt.Errorf("expected parameter %s in module %s to be string, found %s", + paramName, moduleName, value.Type().String())} + } + + str.Value = *setString + modified = true } return modified, nil @@ -304,8 +324,8 @@ func main() { return } - if len(addIdents.idents) == 0 && len(removeIdents.idents) == 0 { - report(fmt.Errorf("-a or -r parameter is required")) + if len(addIdents.idents) == 0 && len(removeIdents.idents) == 0 && setString == nil { + report(fmt.Errorf("-a, -r or -str parameter is required")) return } @@ -352,6 +372,22 @@ func diff(b1, b2 []byte) (data []byte, err error) { } +type stringPtrFlag struct { + s **string +} + +func (f stringPtrFlag) Set(s string) error { + *f.s = &s + return nil +} + +func (f stringPtrFlag) String() string { + if f.s == nil || *f.s == nil { + return "" + } + return **f.s +} + type identSet struct { idents []string all bool diff --git a/bpmodify/bpmodify_test.go b/bpmodify/bpmodify_test.go index 7ccd06e..a92d439 100644 --- a/bpmodify/bpmodify_test.go +++ b/bpmodify/bpmodify_test.go @@ -19,6 +19,7 @@ import ( "testing" "github.com/google/blueprint/parser" + "github.com/google/blueprint/proptools" ) var testCases = []struct { @@ -28,6 +29,7 @@ var testCases = []struct { property string addSet string removeSet string + setString *string }{ { name: "add", @@ -249,6 +251,39 @@ var testCases = []struct { property: "deps", addSet: "bar-v10-bar", }, + { + name: "set string", + input: ` + cc_foo { + name: "foo", + } + `, + output: ` + cc_foo { + name: "foo", + foo: "bar", + } + `, + property: "foo", + setString: proptools.StringPtr("bar"), + }, + { + name: "set existing string", + input: ` + cc_foo { + name: "foo", + foo: "baz", + } + `, + output: ` + cc_foo { + name: "foo", + foo: "bar", + } + `, + property: "foo", + setString: proptools.StringPtr("bar"), + }, } func simplifyModuleDefinition(def string) string { @@ -265,6 +300,7 @@ func TestProcessModule(t *testing.T) { targetedProperty.Set(testCase.property) addIdents.Set(testCase.addSet) removeIdents.Set(testCase.removeSet) + setString = testCase.setString inAst, errs := parser.ParseAndEval("", strings.NewReader(testCase.input), parser.NewScope(nil)) if len(errs) > 0 {