Skip to content

Commit

Permalink
decoder: Collect 'any' type by inferring type from expression
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Mar 20, 2023
1 parent 1f0ef80 commit 27cea4c
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 66 deletions.
17 changes: 17 additions & 0 deletions decoder/expr_literal_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package decoder
import (
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl/v2"
"github.com/zclconf/go-cty/cty"
)

type LiteralType struct {
Expand All @@ -11,3 +12,19 @@ type LiteralType struct {

pathCtx *PathContext
}

func (lt LiteralType) InferType() (cty.Type, bool) {
consType, ok := lt.cons.ConstraintType()
if !ok {
return consType, false
}

if consType == cty.DynamicPseudoType && !isEmptyExpression(lt.expr) {
val, diags := lt.expr.Value(nil)
if !diags.HasErrors() {
consType = val.Type()
}
}

return consType, true
}
8 changes: 8 additions & 0 deletions decoder/expr_literal_type_ref_targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@ import (
"github.com/hashicorp/hcl-lang/reference"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/zclconf/go-cty/cty"
)

func (lt LiteralType) ReferenceTargets(ctx context.Context, targetCtx *TargetContext) reference.Targets {
typ := lt.cons.Type

if typ == cty.DynamicPseudoType {
val, diags := lt.expr.Value(nil)
if !diags.HasErrors() {
typ = val.Type()
}
}

// Primitive types can only be collected if they have parent address
if typ.IsPrimitiveType() && targetCtx != nil && len(targetCtx.ParentAddress) > 0 {
return reference.Targets{
Expand Down
4 changes: 4 additions & 0 deletions decoder/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ type ReferenceTargetsExpression interface {
ReferenceTargets(ctx context.Context, targetCtx *TargetContext) reference.Targets
}

type CanInferTypeExpression interface {
InferType() (cty.Type, bool)
}

// TargetContext describes context for collecting reference targets
type TargetContext struct {
// FriendlyName is (optional) human-readable name of the expression
Expand Down
29 changes: 22 additions & 7 deletions decoder/reference_targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -701,17 +701,32 @@ func (d *PathDecoder) collectInferredReferenceTargetsForBody(addr lang.Address,
selfRefBodyRangePtr = content.RangePtr
}

rawAttributes, _ := body.JustAttributes()

for name, aSchema := range bodySchema.Attributes {
var attrType cty.Type
if aSchema.Constraint != nil {
var ok bool
cons, ok := aSchema.Constraint.(schema.TypeAwareConstraint)
if !ok {
continue
}
attrType, ok = cons.ConstraintType()
if !ok {
continue
rawAttr, ok := rawAttributes[name]
if ok {
// try to infer type if attribute is declared
expr, ok := newExpression(d.pathCtx, rawAttr.Expr, aSchema.Constraint).(CanInferTypeExpression)
if !ok {
continue
}
attrType, ok = expr.InferType()
if !ok {
continue
}
} else {
cons, ok := aSchema.Constraint.(schema.TypeAwareConstraint)
if !ok {
continue
}
attrType, ok = cons.ConstraintType()
if !ok {
continue
}
}
} else {
var ok bool
Expand Down
118 changes: 59 additions & 59 deletions decoder/reference_targets_collect_hcl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4331,9 +4331,9 @@ module "different" {
ScopeId: lang.ScopeId("local"),
AsExprType: true,
},
Expr: schema.ExprConstraints{
schema.TraversalExpr{OfType: cty.DynamicPseudoType},
schema.LiteralTypeExpr{Type: cty.DynamicPseudoType},
Constraint: schema.OneOf{
schema.Reference{OfType: cty.DynamicPseudoType},
schema.LiteralType{Type: cty.DynamicPseudoType},
},
},
},
Expand Down Expand Up @@ -4484,7 +4484,7 @@ module "different" {
Addr: lang.Address{
lang.RootStep{Name: "local"},
lang.AttrStep{Name: "top_obj"},
lang.AttrStep{Name: "second"},
lang.AttrStep{Name: "fourth"},
},
Type: cty.Object(map[string]cty.Type{
"attr": cty.String,
Expand All @@ -4493,63 +4493,63 @@ module "different" {
RangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 6,
Line: 12,
Column: 5,
Byte: 66,
Byte: 145,
},
End: hcl.Pos{
Line: 8,
Line: 14,
Column: 6,
Byte: 101,
Byte: 180,
},
},
DefRangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 6,
Line: 12,
Column: 5,
Byte: 66,
Byte: 145,
},
End: hcl.Pos{
Line: 6,
Line: 12,
Column: 11,
Byte: 72,
Byte: 151,
},
},
NestedTargets: reference.Targets{
{
Addr: lang.Address{
lang.RootStep{Name: "local"},
lang.AttrStep{Name: "top_obj"},
lang.AttrStep{Name: "second"},
lang.AttrStep{Name: "fourth"},
lang.AttrStep{Name: "attr"},
},
Type: cty.String,
ScopeId: lang.ScopeId("local"),
RangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 7,
Line: 13,
Column: 7,
Byte: 83,
Byte: 162,
},
End: hcl.Pos{
Line: 7,
Line: 13,
Column: 19,
Byte: 95,
Byte: 174,
},
},
DefRangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 7,
Line: 13,
Column: 7,
Byte: 83,
Byte: 162,
},
End: hcl.Pos{
Line: 7,
Line: 13,
Column: 11,
Byte: 87,
Byte: 166,
},
},
},
Expand All @@ -4559,7 +4559,7 @@ module "different" {
Addr: lang.Address{
lang.RootStep{Name: "local"},
lang.AttrStep{Name: "top_obj"},
lang.AttrStep{Name: "third"},
lang.AttrStep{Name: "second"},
},
Type: cty.Object(map[string]cty.Type{
"attr": cty.String,
Expand All @@ -4568,63 +4568,63 @@ module "different" {
RangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 9,
Line: 6,
Column: 5,
Byte: 106,
Byte: 66,
},
End: hcl.Pos{
Line: 11,
Line: 8,
Column: 6,
Byte: 140,
Byte: 101,
},
},
DefRangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 9,
Line: 6,
Column: 5,
Byte: 106,
Byte: 66,
},
End: hcl.Pos{
Line: 9,
Column: 10,
Byte: 111,
Line: 6,
Column: 11,
Byte: 72,
},
},
NestedTargets: reference.Targets{
{
Addr: lang.Address{
lang.RootStep{Name: "local"},
lang.AttrStep{Name: "top_obj"},
lang.AttrStep{Name: "third"},
lang.AttrStep{Name: "second"},
lang.AttrStep{Name: "attr"},
},
Type: cty.String,
ScopeId: lang.ScopeId("local"),
RangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 10,
Line: 7,
Column: 7,
Byte: 122,
Byte: 83,
},
End: hcl.Pos{
Line: 10,
Line: 7,
Column: 19,
Byte: 134,
Byte: 95,
},
},
DefRangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 10,
Line: 7,
Column: 7,
Byte: 122,
Byte: 83,
},
End: hcl.Pos{
Line: 10,
Line: 7,
Column: 11,
Byte: 126,
Byte: 87,
},
},
},
Expand All @@ -4634,7 +4634,7 @@ module "different" {
Addr: lang.Address{
lang.RootStep{Name: "local"},
lang.AttrStep{Name: "top_obj"},
lang.AttrStep{Name: "fourth"},
lang.AttrStep{Name: "third"},
},
Type: cty.Object(map[string]cty.Type{
"attr": cty.String,
Expand All @@ -4643,63 +4643,63 @@ module "different" {
RangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 12,
Line: 9,
Column: 5,
Byte: 145,
Byte: 106,
},
End: hcl.Pos{
Line: 14,
Line: 11,
Column: 6,
Byte: 180,
Byte: 140,
},
},
DefRangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 12,
Line: 9,
Column: 5,
Byte: 145,
Byte: 106,
},
End: hcl.Pos{
Line: 12,
Column: 11,
Byte: 151,
Line: 9,
Column: 10,
Byte: 111,
},
},
NestedTargets: reference.Targets{
{
Addr: lang.Address{
lang.RootStep{Name: "local"},
lang.AttrStep{Name: "top_obj"},
lang.AttrStep{Name: "fourth"},
lang.AttrStep{Name: "third"},
lang.AttrStep{Name: "attr"},
},
Type: cty.String,
ScopeId: lang.ScopeId("local"),
RangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 13,
Line: 10,
Column: 7,
Byte: 162,
Byte: 122,
},
End: hcl.Pos{
Line: 13,
Line: 10,
Column: 19,
Byte: 174,
Byte: 134,
},
},
DefRangePtr: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{
Line: 13,
Line: 10,
Column: 7,
Byte: 162,
Byte: 122,
},
End: hcl.Pos{
Line: 13,
Line: 10,
Column: 11,
Byte: 166,
Byte: 126,
},
},
},
Expand Down

0 comments on commit 27cea4c

Please sign in to comment.