hcl/json: catch and reject duplicate attrs in JustAttributes

Previously this was handled in the parser, but the parser now permits
multiple properties with the same name and so we must handle this at the
decoder level instead.
This commit is contained in:
Martin Atkins 2018-02-17 15:22:27 -08:00
parent 23fc060132
commit 8c3aa9a6d4
2 changed files with 48 additions and 4 deletions

View File

@ -192,6 +192,17 @@ func (b *body) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
if _, hidden := b.hiddenAttrs[name]; hidden {
continue
}
if existing, exists := attrs[name]; exists {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Duplicate attribute definition",
Detail: fmt.Sprintf("The attribute %q was already defined at %s.", name, existing.Range),
Subject: &jsonAttr.NameRange,
})
continue
}
attrs[name] = &hcl.Attribute{
Name: name,
Expr: &expression{src: jsonAttr.Value},

View File

@ -1096,12 +1096,14 @@ func TestJustAttributes(t *testing.T) {
// We test most of the functionality already in TestBodyPartialContent, so
// this test focuses on the handling of extraneous attributes.
tests := []struct {
src string
want hcl.Attributes
src string
want hcl.Attributes
diagCount int
}{
{
`{}`,
map[string]*hcl.Attribute{},
0,
},
{
`{"foo": true}`,
@ -1130,10 +1132,41 @@ func TestJustAttributes(t *testing.T) {
},
},
},
0,
},
{
`{"//": "comment that should be ignored"}`,
map[string]*hcl.Attribute{},
0,
},
{
`{"foo": true, "foo": true}`,
map[string]*hcl.Attribute{
"foo": {
Name: "foo",
Expr: &expression{
src: &booleanVal{
Value: true,
SrcRange: hcl.Range{
Filename: "test.json",
Start: hcl.Pos{Byte: 8, Line: 1, Column: 9},
End: hcl.Pos{Byte: 12, Line: 1, Column: 13},
},
},
},
Range: hcl.Range{
Filename: "test.json",
Start: hcl.Pos{Byte: 1, Line: 1, Column: 2},
End: hcl.Pos{Byte: 12, Line: 1, Column: 13},
},
NameRange: hcl.Range{
Filename: "test.json",
Start: hcl.Pos{Byte: 1, Line: 1, Column: 2},
End: hcl.Pos{Byte: 6, Line: 1, Column: 7},
},
},
},
1, // attribute foo was already defined
},
}
@ -1144,8 +1177,8 @@ func TestJustAttributes(t *testing.T) {
t.Fatalf("Parse produced diagnostics: %s", diags)
}
got, diags := file.Body.JustAttributes()
if len(diags) != 0 {
t.Errorf("Wrong number of diagnostics %d; want %d", len(diags), 0)
if len(diags) != test.diagCount {
t.Errorf("Wrong number of diagnostics %d; want %d", len(diags), test.diagCount)
for _, diag := range diags {
t.Logf(" - %s", diag)
}