hcldec: Improved context for expression diagnostics

The two cases where we decode attribute values should include the
expression and EvalContext in any diagnostics they generate so that the
calling application can give hints about the types and values of variables
that are used within the expression.

This also includes some adjustments to the returned source ranges so that
both cases are consistent with one another and so that both indicate
the entire expression as the Subject and include the attribute name in
the Context. Including the whole expression in the range ensures that
when there's a problem inside a tuple or object constructor, for example,
we'll show the line containing the problem and not just the opening [
or { symbol.
This commit is contained in:
Martin Atkins 2019-12-10 16:10:24 -08:00
parent fc57429f63
commit c22ad7a9a6
1 changed files with 11 additions and 6 deletions

View File

@ -204,8 +204,10 @@ func (s *AttrSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ct
"Inappropriate value for attribute %q: %s.",
s.Name, err.Error(),
),
Subject: attr.Expr.StartRange().Ptr(),
Context: hcl.RangeBetween(attr.NameRange, attr.Expr.StartRange()).Ptr(),
Subject: attr.Expr.Range().Ptr(),
Context: hcl.RangeBetween(attr.NameRange, attr.Expr.Range()).Ptr(),
Expression: attr.Expr,
EvalContext: ctx,
})
// We'll return an unknown value of the _correct_ type so that the
// incomplete result can still be used for some analysis use-cases.
@ -1227,10 +1229,13 @@ func (s *BlockAttrsSpec) decode(content *hcl.BodyContent, blockLabels []blockLab
attrVal, err := convert.Convert(attrVal, s.ElementType)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid attribute value",
Detail: fmt.Sprintf("Invalid value for attribute of %q block: %s.", s.TypeName, err),
Subject: attr.Expr.Range().Ptr(),
Severity: hcl.DiagError,
Summary: "Invalid attribute value",
Detail: fmt.Sprintf("Invalid value for attribute of %q block: %s.", s.TypeName, err),
Subject: attr.Expr.Range().Ptr(),
Context: hcl.RangeBetween(attr.NameRange, attr.Expr.Range()).Ptr(),
Expression: attr.Expr,
EvalContext: ctx,
})
attrVal = cty.UnknownVal(s.ElementType)
}