zclsyntax: Body.JustAttributes implementation

This commit is contained in:
Martin Atkins 2017-06-03 07:29:48 -07:00
parent aacf36abfd
commit da1f9950a6
2 changed files with 169 additions and 1 deletions

View File

@ -1,6 +1,8 @@
package zclsyntax
import (
"fmt"
"github.com/zclconf/go-zcl/zcl"
)
@ -27,6 +29,11 @@ type Body struct {
Attributes Attributes
Blocks Blocks
// These are used with PartialContent to produce a "remaining items"
// body to return. They are nil on all bodies fresh out of the parser.
hiddenAttrs map[string]struct{}
hiddenBlocks map[string]struct{}
SrcRange zcl.Range
EndRange zcl.Range // Final token of the body, for reporting missing items
}
@ -52,7 +59,34 @@ func (b *Body) PartialContent(schema *zcl.BodySchema) (*zcl.BodyContent, zcl.Bod
}
func (b *Body) JustAttributes() (zcl.Attributes, zcl.Diagnostics) {
panic("Body.JustAttributes not yet implemented")
attrs := make(zcl.Attributes)
var diags zcl.Diagnostics
if len(b.Blocks) > 0 {
example := b.Blocks[0]
diags = append(diags, &zcl.Diagnostic{
Severity: zcl.DiagError,
Summary: fmt.Sprintf("Unexpected %s block", example.Type),
Detail: "Blocks are not allowed here.",
Context: &example.TypeRange,
})
// we will continue processing anyway, and return the attributes
// we are able to find so that certain analyses can still be done
// in the face of errors.
}
if b.Attributes == nil {
return attrs, diags
}
for name, attr := range b.Attributes {
if _, hidden := b.hiddenAttrs[name]; hidden {
continue
}
attrs[name] = attr.AsZCLAttribute()
}
return attrs, diags
}
func (b *Body) MissingItemRange() zcl.Range {
@ -105,6 +139,17 @@ func (a *Attribute) Range() zcl.Range {
return a.SrcRange
}
// AsZCLAttribute returns the block data expressed as a *zcl.Attribute.
func (a *Attribute) AsZCLAttribute() *zcl.Attribute {
return &zcl.Attribute{
Name: a.Name,
Expr: a.Expr,
Range: a.SrcRange,
NameRange: a.NameRange,
}
}
// Blocks is the list of nested blocks within a body.
type Blocks []*Block

View File

@ -0,0 +1,123 @@
package zclsyntax
import (
"fmt"
"reflect"
"testing"
"github.com/kylelemons/godebug/pretty"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-zcl/zcl"
)
func TestBodyJustAttributes(t *testing.T) {
tests := []struct {
body *Body
want zcl.Attributes
diagCount int
}{
{
&Body{},
zcl.Attributes{},
0,
},
{
&Body{
Attributes: Attributes{},
},
zcl.Attributes{},
0,
},
{
&Body{
Attributes: Attributes{
"foo": &Attribute{
Name: "foo",
Expr: &LiteralValueExpr{
Val: cty.StringVal("bar"),
},
},
},
},
zcl.Attributes{
"foo": &zcl.Attribute{
Name: "foo",
Expr: &LiteralValueExpr{
Val: cty.StringVal("bar"),
},
},
},
0,
},
{
&Body{
Attributes: Attributes{
"foo": &Attribute{
Name: "foo",
Expr: &LiteralValueExpr{
Val: cty.StringVal("bar"),
},
},
},
Blocks: Blocks{
{
Type: "foo",
},
},
},
zcl.Attributes{
"foo": &zcl.Attribute{
Name: "foo",
Expr: &LiteralValueExpr{
Val: cty.StringVal("bar"),
},
},
},
1, // blocks are not allowed here
},
{
&Body{
Attributes: Attributes{
"foo": &Attribute{
Name: "foo",
Expr: &LiteralValueExpr{
Val: cty.StringVal("bar"),
},
},
},
hiddenAttrs: map[string]struct{}{
"foo": struct{}{},
},
},
zcl.Attributes{},
0,
},
}
prettyConfig := &pretty.Config{
Diffable: true,
IncludeUnexported: true,
PrintStringers: true,
}
for i, test := range tests {
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
got, diags := test.body.JustAttributes()
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.Error())
}
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf(
"wrong result\nbody: %s\ndiff: %s",
prettyConfig.Sprint(test.body),
prettyConfig.Compare(test.want, got),
)
}
})
}
}