opentofu/config/hcl2shim/single_attr_body.go
Martin Atkins 71e989ba3e config/hcl2shim: make some of the HCL2 shim functions public
The value-conversion machinery is also needed in the main "terraform"
package to help us populate our HCL2 evaluation scope, so a subset of the
shim functions move here into a new package where they can be public.

Some of them remain private within the config package since they depend
on some other symbols in the config package, and they are not needed
by outside callers anyway.
2017-10-16 17:54:02 -07:00

86 lines
2.2 KiB
Go

package hcl2shim
import (
"fmt"
hcl2 "github.com/hashicorp/hcl2/hcl"
)
// SingleAttrBody is a weird implementation of hcl2.Body that acts as if
// it has a single attribute whose value is the given expression.
//
// This is used to shim Resource.RawCount and Output.RawConfig to behave
// more like they do in the old HCL loader.
type SingleAttrBody struct {
Name string
Expr hcl2.Expression
}
var _ hcl2.Body = SingleAttrBody{}
func (b SingleAttrBody) Content(schema *hcl2.BodySchema) (*hcl2.BodyContent, hcl2.Diagnostics) {
content, all, diags := b.content(schema)
if !all {
// This should never happen because this body implementation should only
// be used by code that is aware that it's using a single-attr body.
diags = append(diags, &hcl2.Diagnostic{
Severity: hcl2.DiagError,
Summary: "Invalid attribute",
Detail: fmt.Sprintf("The correct attribute name is %q.", b.Name),
Subject: b.Expr.Range().Ptr(),
})
}
return content, diags
}
func (b SingleAttrBody) PartialContent(schema *hcl2.BodySchema) (*hcl2.BodyContent, hcl2.Body, hcl2.Diagnostics) {
content, all, diags := b.content(schema)
var remain hcl2.Body
if all {
// If the request matched the one attribute we represent, then the
// remaining body is empty.
remain = hcl2.EmptyBody()
} else {
remain = b
}
return content, remain, diags
}
func (b SingleAttrBody) content(schema *hcl2.BodySchema) (*hcl2.BodyContent, bool, hcl2.Diagnostics) {
ret := &hcl2.BodyContent{}
all := false
var diags hcl2.Diagnostics
for _, attrS := range schema.Attributes {
if attrS.Name == b.Name {
attrs, _ := b.JustAttributes()
ret.Attributes = attrs
all = true
} else if attrS.Required {
diags = append(diags, &hcl2.Diagnostic{
Severity: hcl2.DiagError,
Summary: "Missing attribute",
Detail: fmt.Sprintf("The attribute %q is required.", attrS.Name),
Subject: b.Expr.Range().Ptr(),
})
}
}
return ret, all, diags
}
func (b SingleAttrBody) JustAttributes() (hcl2.Attributes, hcl2.Diagnostics) {
return hcl2.Attributes{
b.Name: {
Expr: b.Expr,
Name: b.Name,
NameRange: b.Expr.Range(),
Range: b.Expr.Range(),
},
}, nil
}
func (b SingleAttrBody) MissingItemRange() hcl2.Range {
return b.Expr.Range()
}