hcldec: New function ChildBlockTypes
This function returns a map describing all of the child block types declared inside a spec. This can be used for recursive decoding of bodies using the low-level HCL API, though in most cases callers should just use Decode which does recursive decoding of an entire nested structure in a single call.
This commit is contained in:
parent
45c6cc83f0
commit
130b3c5105
@ -51,3 +51,28 @@ func ImpliedType(spec Spec) cty.Type {
|
||||
func SourceRange(body hcl.Body, spec Spec) hcl.Range {
|
||||
return sourceRange(body, nil, spec)
|
||||
}
|
||||
|
||||
// ChildBlockTypes returns a map of all of the child block types declared
|
||||
// by the given spec, with block type names as keys and the associated
|
||||
// nested body specs as values.
|
||||
func ChildBlockTypes(spec Spec) map[string]Spec {
|
||||
ret := map[string]Spec{}
|
||||
|
||||
// visitSameBodyChildren walks through the spec structure, calling
|
||||
// the given callback for each descendent spec encountered. We are
|
||||
// interested in the specs that reference attributes and blocks.
|
||||
var visit visitFunc
|
||||
visit = func(s Spec) {
|
||||
if bs, ok := s.(blockSpec); ok {
|
||||
for _, blockS := range bs.blockHeaderSchemata() {
|
||||
ret[blockS.Type] = bs.nestedSpec()
|
||||
}
|
||||
}
|
||||
|
||||
s.visitSameBodyChildren(visit)
|
||||
}
|
||||
|
||||
visit(spec)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ type attrSpec interface {
|
||||
// blockSpec is implemented by specs that require blocks from the body.
|
||||
type blockSpec interface {
|
||||
blockHeaderSchemata() []hcl.BlockHeaderSchema
|
||||
nestedSpec() Spec
|
||||
}
|
||||
|
||||
// specNeedingVariables is implemented by specs that can use variables
|
||||
@ -298,6 +299,11 @@ func (s *BlockSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {
|
||||
}
|
||||
}
|
||||
|
||||
// blockSpec implementation
|
||||
func (s *BlockSpec) nestedSpec() Spec {
|
||||
return s.Nested
|
||||
}
|
||||
|
||||
// specNeedingVariables implementation
|
||||
func (s *BlockSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {
|
||||
var childBlock *hcl.Block
|
||||
@ -409,6 +415,11 @@ func (s *BlockListSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {
|
||||
}
|
||||
}
|
||||
|
||||
// blockSpec implementation
|
||||
func (s *BlockListSpec) nestedSpec() Spec {
|
||||
return s.Nested
|
||||
}
|
||||
|
||||
// specNeedingVariables implementation
|
||||
func (s *BlockListSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {
|
||||
var ret []hcl.Traversal
|
||||
@ -519,6 +530,11 @@ func (s *BlockSetSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {
|
||||
}
|
||||
}
|
||||
|
||||
// blockSpec implementation
|
||||
func (s *BlockSetSpec) nestedSpec() Spec {
|
||||
return s.Nested
|
||||
}
|
||||
|
||||
// specNeedingVariables implementation
|
||||
func (s *BlockSetSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {
|
||||
var ret []hcl.Traversal
|
||||
@ -631,6 +647,11 @@ func (s *BlockMapSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {
|
||||
}
|
||||
}
|
||||
|
||||
// blockSpec implementation
|
||||
func (s *BlockMapSpec) nestedSpec() Spec {
|
||||
return s.Nested
|
||||
}
|
||||
|
||||
// specNeedingVariables implementation
|
||||
func (s *BlockMapSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {
|
||||
var ret []hcl.Traversal
|
||||
|
@ -1,14 +1,21 @@
|
||||
package hcldec
|
||||
|
||||
// Verify that all of our spec types implement the necessary interfaces
|
||||
var objectSpecAsSpec Spec = ObjectSpec(nil)
|
||||
var tupleSpecAsSpec Spec = TupleSpec(nil)
|
||||
var attrSpecAsSpec Spec = (*AttrSpec)(nil)
|
||||
var literalSpecAsSpec Spec = (*LiteralSpec)(nil)
|
||||
var exprSpecAsSpec Spec = (*ExprSpec)(nil)
|
||||
var blockSpecAsSpec Spec = (*BlockSpec)(nil)
|
||||
var blockListSpecAsSpec Spec = (*BlockListSpec)(nil)
|
||||
var blockSetSpecAsSpec Spec = (*BlockSetSpec)(nil)
|
||||
var blockMapSpecAsSpec Spec = (*BlockMapSpec)(nil)
|
||||
var blockLabelSpecAsSpec Spec = (*BlockLabelSpec)(nil)
|
||||
var defaultSpecAsSpec Spec = (*DefaultSpec)(nil)
|
||||
var _ Spec = ObjectSpec(nil)
|
||||
var _ Spec = TupleSpec(nil)
|
||||
var _ Spec = (*AttrSpec)(nil)
|
||||
var _ Spec = (*LiteralSpec)(nil)
|
||||
var _ Spec = (*ExprSpec)(nil)
|
||||
var _ Spec = (*BlockSpec)(nil)
|
||||
var _ Spec = (*BlockListSpec)(nil)
|
||||
var _ Spec = (*BlockSetSpec)(nil)
|
||||
var _ Spec = (*BlockMapSpec)(nil)
|
||||
var _ Spec = (*BlockLabelSpec)(nil)
|
||||
var _ Spec = (*DefaultSpec)(nil)
|
||||
|
||||
var _ attrSpec = (*AttrSpec)(nil)
|
||||
|
||||
var _ blockSpec = (*BlockSpec)(nil)
|
||||
var _ blockSpec = (*BlockListSpec)(nil)
|
||||
var _ blockSpec = (*BlockSetSpec)(nil)
|
||||
var _ blockSpec = (*BlockMapSpec)(nil)
|
||||
|
Loading…
Reference in New Issue
Block a user