This fixes a bug in the flattener so that objects are flattened as one list object

This commit is contained in:
Sander van Harmelen 2015-11-19 17:37:23 +01:00
parent 2deb1d1db2
commit 2f117c801c
2 changed files with 67 additions and 26 deletions

View File

@ -1,8 +1,6 @@
package parser package parser
import ( import "github.com/hashicorp/hcl/hcl/ast"
"github.com/hashicorp/hcl/hcl/ast"
)
// flattenObjects takes an AST node, walks it, and flattens // flattenObjects takes an AST node, walks it, and flattens
func flattenObjects(node ast.Node) { func flattenObjects(node ast.Node) {
@ -60,25 +58,14 @@ func flattenListType(
// Great! We have a match go through all the items and flatten // Great! We have a match go through all the items and flatten
for _, elem := range ot.List { for _, elem := range ot.List {
// This won't fail since we verified it earlier // Add it to the frontier so that we can recurse
ot := elem.(*ast.ObjectType) frontier = append(frontier, &ast.ObjectItem{
Keys: item.Keys,
// Go over all the subitems and merge them in Assign: item.Assign,
for _, subitem := range ot.List.Items { Val: elem,
// Copy the new key LeadComment: item.LeadComment,
keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys)) LineComment: item.LineComment,
copy(keys, item.Keys) })
copy(keys[len(item.Keys):], subitem.Keys)
// Add it to the frontier so that we can recurse
frontier = append(frontier, &ast.ObjectItem{
Keys: keys,
Assign: item.Assign,
Val: subitem.Val,
LeadComment: item.LeadComment,
LineComment: item.LineComment,
})
}
} }
return items, frontier return items, frontier

View File

@ -178,6 +178,60 @@ func TestObjectType(t *testing.T) {
} }
} }
func TestFlattenObjects(t *testing.T) {
var literals = []struct {
src string
nodeType []ast.Node
}{
{
`{
"foo": [
{
"foo": "svh",
"bar": "fatih"
}
]
}`,
[]ast.Node{
&ast.ObjectType{},
&ast.LiteralType{},
&ast.LiteralType{},
&ast.ListType{},
},
},
}
for _, l := range literals {
t.Logf("Testing:\n%s\n", l.src)
f, err := Parse([]byte(l.src))
if err != nil {
t.Error(err)
}
// the first object is always an ObjectList so just assert that one
// so we can use it as such
obj, ok := f.Node.(*ast.ObjectList)
if !ok {
t.Errorf("node should be *ast.ObjectList, got: %T", f.Node)
}
// check if the types are correct
var i int
for _, item := range obj.Items {
equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
i++
if obj, ok := item.Val.(*ast.ObjectType); ok {
for _, item := range obj.List.Items {
equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
i++
}
}
}
}
}
func TestObjectKey(t *testing.T) { func TestObjectKey(t *testing.T) {
keys := []struct { keys := []struct {
exp []token.Type exp []token.Type
@ -225,6 +279,10 @@ func TestParse(t *testing.T) {
Name string Name string
Err bool Err bool
}{ }{
{
"array.json",
false,
},
{ {
"basic.json", "basic.json",
false, false,
@ -233,10 +291,6 @@ func TestParse(t *testing.T) {
"object.json", "object.json",
false, false,
}, },
{
"array.json",
false,
},
{ {
"types.json", "types.json",
false, false,