4 "github.com/hashicorp/hcl2/hcl"
5 "github.com/zclconf/go-cty/cty"
8 // Decode interprets the given body using the given specification and returns
9 // the resulting value. If the given body is not valid per the spec, error
10 // diagnostics are returned and the returned value is likely to be incomplete.
12 // The ctx argument may be nil, in which case any references to variables or
13 // functions will produce error diagnostics.
14 func Decode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
15 val, _, diags := decode(body, nil, ctx, spec, false)
19 // PartialDecode is like Decode except that it permits "leftover" items in
20 // the top-level body, which are returned as a new body to allow for
21 // further processing.
23 // Any descendent block bodies are _not_ decoded partially and thus must
24 // be fully described by the given specification.
25 func PartialDecode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Body, hcl.Diagnostics) {
26 return decode(body, nil, ctx, spec, true)
29 // ImpliedType returns the value type that should result from decoding the
31 func ImpliedType(spec Spec) cty.Type {
32 return impliedType(spec)
35 // SourceRange interprets the given body using the given specification and
36 // then returns the source range of the value that would be used to
39 // This can be used if application-level validation detects value errors, to
40 // obtain a reasonable SourceRange to use for generated diagnostics. It works
41 // best when applied to specific body items (e.g. using AttrSpec, BlockSpec, ...)
42 // as opposed to entire bodies using ObjectSpec, TupleSpec. The result will
43 // be less useful the broader the specification, so e.g. a spec that returns
44 // the entirety of all of the blocks of a given type is likely to be
45 // _particularly_ arbitrary and useless.
47 // If the given body is not valid per the given spec, the result is best-effort
48 // and may not actually be something ideal. It's expected that an application
49 // will already have used Decode or PartialDecode earlier and thus had an
50 // opportunity to detect and report spec violations.
51 func SourceRange(body hcl.Body, spec Spec) hcl.Range {
52 return sourceRange(body, nil, spec)
55 // ChildBlockTypes returns a map of all of the child block types declared
56 // by the given spec, with block type names as keys and the associated
57 // nested body specs as values.
58 func ChildBlockTypes(spec Spec) map[string]Spec {
59 ret := map[string]Spec{}
61 // visitSameBodyChildren walks through the spec structure, calling
62 // the given callback for each descendent spec encountered. We are
63 // interested in the specs that reference attributes and blocks.
65 visit = func(s Spec) {
66 if bs, ok := s.(blockSpec); ok {
67 for _, blockS := range bs.blockHeaderSchemata() {
68 nested := bs.nestedSpec()
69 if nested != nil { // nil can be returned to dynamically opt out of this interface
70 ret[blockS.Type] = nested
75 s.visitSameBodyChildren(visit)