github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/configs/hcl2shim/single_attr_body.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package hcl2shim
     5  
     6  import (
     7  	"fmt"
     8  
     9  	hcl2 "github.com/hashicorp/hcl/v2"
    10  )
    11  
    12  // SingleAttrBody is a weird implementation of hcl2.Body that acts as if
    13  // it has a single attribute whose value is the given expression.
    14  //
    15  // This is used to shim Resource.RawCount and Output.RawConfig to behave
    16  // more like they do in the old HCL loader.
    17  type SingleAttrBody struct {
    18  	Name string
    19  	Expr hcl2.Expression
    20  }
    21  
    22  var _ hcl2.Body = SingleAttrBody{}
    23  
    24  func (b SingleAttrBody) Content(schema *hcl2.BodySchema) (*hcl2.BodyContent, hcl2.Diagnostics) {
    25  	content, all, diags := b.content(schema)
    26  	if !all {
    27  		// This should never happen because this body implementation should only
    28  		// be used by code that is aware that it's using a single-attr body.
    29  		diags = append(diags, &hcl2.Diagnostic{
    30  			Severity: hcl2.DiagError,
    31  			Summary:  "Invalid attribute",
    32  			Detail:   fmt.Sprintf("The correct attribute name is %q.", b.Name),
    33  			Subject:  b.Expr.Range().Ptr(),
    34  		})
    35  	}
    36  	return content, diags
    37  }
    38  
    39  func (b SingleAttrBody) PartialContent(schema *hcl2.BodySchema) (*hcl2.BodyContent, hcl2.Body, hcl2.Diagnostics) {
    40  	content, all, diags := b.content(schema)
    41  	var remain hcl2.Body
    42  	if all {
    43  		// If the request matched the one attribute we represent, then the
    44  		// remaining body is empty.
    45  		remain = hcl2.EmptyBody()
    46  	} else {
    47  		remain = b
    48  	}
    49  	return content, remain, diags
    50  }
    51  
    52  func (b SingleAttrBody) content(schema *hcl2.BodySchema) (*hcl2.BodyContent, bool, hcl2.Diagnostics) {
    53  	ret := &hcl2.BodyContent{}
    54  	all := false
    55  	var diags hcl2.Diagnostics
    56  
    57  	for _, attrS := range schema.Attributes {
    58  		if attrS.Name == b.Name {
    59  			attrs, _ := b.JustAttributes()
    60  			ret.Attributes = attrs
    61  			all = true
    62  		} else if attrS.Required {
    63  			diags = append(diags, &hcl2.Diagnostic{
    64  				Severity: hcl2.DiagError,
    65  				Summary:  "Missing attribute",
    66  				Detail:   fmt.Sprintf("The attribute %q is required.", attrS.Name),
    67  				Subject:  b.Expr.Range().Ptr(),
    68  			})
    69  		}
    70  	}
    71  
    72  	return ret, all, diags
    73  }
    74  
    75  func (b SingleAttrBody) JustAttributes() (hcl2.Attributes, hcl2.Diagnostics) {
    76  	return hcl2.Attributes{
    77  		b.Name: {
    78  			Expr:      b.Expr,
    79  			Name:      b.Name,
    80  			NameRange: b.Expr.Range(),
    81  			Range:     b.Expr.Range(),
    82  		},
    83  	}, nil
    84  }
    85  
    86  func (b SingleAttrBody) MissingItemRange() hcl2.Range {
    87  	return b.Expr.Range()
    88  }