* hcl2template/addrs.ParseRef will parse a reference and tell for example if we are referring to a variable and its name, for now it can only do that and in the future it improved when we need to most of it is from the TF code. This is used to tell wether a variable vas referenced in a variable validation condition; for now. * Added Validations blocks to the hcl2 Variable struct and code to parse/validate that.
94 lines
2.5 KiB
Go
94 lines
2.5 KiB
Go
package addrs
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
)
|
|
|
|
// Reference describes a reference to an address with source location
|
|
// information.
|
|
type Reference struct {
|
|
Subject Referenceable
|
|
SourceRange hcl.Range
|
|
Remaining hcl.Traversal
|
|
}
|
|
|
|
// ParseRef attempts to extract a referencable address from the prefix of the
|
|
// given traversal, which must be an absolute traversal or this function
|
|
// will panic.
|
|
//
|
|
// If no error diagnostics are returned, the returned reference includes the
|
|
// address that was extracted, the source range it was extracted from, and any
|
|
// remaining relative traversal that was not consumed as part of the
|
|
// reference.
|
|
//
|
|
// If error diagnostics are returned then the Reference value is invalid and
|
|
// must not be used.
|
|
func ParseRef(traversal hcl.Traversal) (*Reference, hcl.Diagnostics) {
|
|
ref, diags := parseRef(traversal)
|
|
|
|
// Normalize a little to make life easier for callers.
|
|
if ref != nil {
|
|
if len(ref.Remaining) == 0 {
|
|
ref.Remaining = nil
|
|
}
|
|
}
|
|
|
|
return ref, diags
|
|
}
|
|
|
|
func parseRef(traversal hcl.Traversal) (*Reference, hcl.Diagnostics) {
|
|
var diags hcl.Diagnostics
|
|
|
|
root := traversal.RootName()
|
|
rootRange := traversal[0].SourceRange()
|
|
|
|
switch root {
|
|
|
|
case "var":
|
|
name, rng, remain, diags := parseSingleAttrRef(traversal)
|
|
return &Reference{
|
|
Subject: InputVariable{Name: name},
|
|
SourceRange: rng,
|
|
Remaining: remain,
|
|
}, diags
|
|
|
|
default:
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Unhandled reference type",
|
|
Detail: `Currently parseRef can only parse "var" references.`,
|
|
Subject: &rootRange,
|
|
})
|
|
}
|
|
return nil, diags
|
|
}
|
|
|
|
func parseSingleAttrRef(traversal hcl.Traversal) (string, hcl.Range, hcl.Traversal, hcl.Diagnostics) {
|
|
var diags hcl.Diagnostics
|
|
|
|
root := traversal.RootName()
|
|
rootRange := traversal[0].SourceRange()
|
|
|
|
if len(traversal) < 2 {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Invalid reference",
|
|
Detail: fmt.Sprintf("The %q object cannot be accessed directly. Instead, access one of its attributes.", root),
|
|
Subject: &rootRange,
|
|
})
|
|
return "", hcl.Range{}, nil, diags
|
|
}
|
|
if attrTrav, ok := traversal[1].(hcl.TraverseAttr); ok {
|
|
return attrTrav.Name, hcl.RangeBetween(rootRange, attrTrav.SrcRange), traversal[2:], diags
|
|
}
|
|
diags = diags.Append(&hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Invalid reference",
|
|
Detail: fmt.Sprintf("The %q object does not support this operation.", root),
|
|
Subject: traversal[1].SourceRange().Ptr(),
|
|
})
|
|
return "", hcl.Range{}, nil, diags
|
|
}
|