Merge "Remove unnecessary used names before reporting" into main am: 2f0f395cc9 am: 79e4baab88

Original change: https://android-review.googlesource.com/c/platform/build/blueprint/+/2810185

Change-Id: I2357012eec65f3eba246a1aeb4dde17b5728cea8
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Zi Wang 2024-01-05 00:36:23 +00:00 committed by Automerger Merge Worker
commit b0cce0bde8
2 changed files with 104 additions and 1 deletions

View file

@ -108,6 +108,7 @@ func UnpackProperties(properties []*parser.Property, objects ...interface{}) (ma
func (ctx *unpackContext) reportUnusedNames(unusedNames []string) []error {
sort.Strings(unusedNames)
unusedNames = removeUnnecessaryUnusedNames(unusedNames)
var lastReported string
for _, name := range unusedNames {
// if 'foo' has been reported, ignore 'foo\..*' and 'foo\[.*'
@ -125,6 +126,23 @@ func (ctx *unpackContext) reportUnusedNames(unusedNames []string) []error {
return ctx.errs
}
// When property a.b.c is not used, (also there is no a.* or a.b.* used)
// "a", "a.b" and "a.b.c" are all in unusedNames.
// removeUnnecessaryUnusedNames only keeps the last "a.b.c" as the real unused
// name.
func removeUnnecessaryUnusedNames(names []string) []string {
if len(names) == 0 {
return names
}
var simplifiedNames []string
for index, name := range names {
if index == len(names)-1 || !strings.HasPrefix(names[index+1], name) {
simplifiedNames = append(simplifiedNames, name)
}
}
return simplifiedNames
}
func (ctx *unpackContext) buildPropertyMap(prefix string, properties []*parser.Property) bool {
nOldErrors := len(ctx.errs)
for _, property := range properties {

View file

@ -17,7 +17,6 @@ package proptools
import (
"bytes"
"reflect"
"testing"
"github.com/google/blueprint/parser"
@ -962,6 +961,37 @@ func TestUnpackErrors(t *testing.T) {
`<input>:3:16: can't assign string value to list property "map_list"`,
},
},
{
name: "non-existent property",
input: `
m {
foo: {
foo_prop1: true,
foo_prop2: false,
foo_prop3: true,
},
bar: {
bar_prop: false,
},
baz: true,
exist: false,
}
`,
output: []interface{}{
&struct {
Foo struct {
Foo_prop1 bool
}
Exist bool
}{},
},
errors: []string{
`<input>:5:16: unrecognized property "foo.foo_prop2"`,
`<input>:6:16: unrecognized property "foo.foo_prop3"`,
`<input>:9:15: unrecognized property "bar.bar_prop"`,
`<input>:11:9: unrecognized property "baz"`,
},
},
}
for _, testCase := range testCases {
@ -1196,3 +1226,58 @@ func BenchmarkUnpackProperties(b *testing.B) {
run(b, props, bp)
})
}
func TestRemoveUnnecessaryUnusedNames(t *testing.T) {
testCases := []struct {
name string
input []string
output []string
}{
{
name: "no unused names",
input: []string{},
output: []string{},
},
{
name: "only one unused name",
input: []string{"a.b.c"},
output: []string{"a.b.c"},
},
{
name: "unused names in a chain",
input: []string{"a", "a.b", "a.b.c"},
output: []string{"a.b.c"},
},
{
name: "unused names unrelated",
input: []string{"a.b.c", "s.t", "x.y"},
output: []string{"a.b.c", "s.t", "x.y"},
},
{
name: "unused names partially related one",
input: []string{"a.b", "a.b.c", "a.b.d"},
output: []string{"a.b.c", "a.b.d"},
},
{
name: "unused names partially related two",
input: []string{"a", "a.b.c", "a.c"},
output: []string{"a.b.c", "a.c"},
},
{
name: "unused names partially related three",
input: []string{"a.b.c", "b.c", "c"},
output: []string{"a.b.c", "b.c", "c"},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
simplifiedNames := removeUnnecessaryUnusedNames(testCase.input)
if !reflect.DeepEqual(simplifiedNames, testCase.output) {
t.Errorf("test case: %s", testCase.name)
t.Errorf(" input: %s", testCase.input)
t.Errorf(" expect: %s", testCase.output)
t.Errorf(" got: %s", simplifiedNames)
}
})
}
}