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
This commit is contained in:
Colin Cross 2021-04-29 20:16:40 -07:00
parent 5ef7b6608c
commit b1abbada6a
2 changed files with 100 additions and 28 deletions

View file

@ -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,6 +231,7 @@ func processParameter(value parser.Expression, paramName, moduleName string,
paramName, moduleName)}
}
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",
@ -243,6 +253,16 @@ func processParameter(value parser.Expression, paramName, moduleName string,
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

View file

@ -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 {