Skip to content

Commit

Permalink
Finish reference target collection for all constraints (#239)
Browse files Browse the repository at this point in the history
* decoder: Finish implementing reference targets for List

* decoder: Finish implementing reference targets for Set

* decoder: Finish implementing reference targets for Tuple

* decoder: Avoid collecting non-addressable attributes as targets in List

* decoder: Avoid collecting non-addressable attributes as targets in Tuple

* decoder: Finish implementing reference targets for Map

* decoder: Finish implementing reference targets for Object

* decoder: Collect undeclared attributes in Object as targets too

* decoder: Use AttrStep syntax to target Object attributes if possible

* decoder: Account for (Def)Ranges of attributes

* decoder: Collect primitive type targets correctly in LiteralType

* decoder: Collect 'any' type by inferring it from value (LiteralType/OneOf)

* decoder: fix block body inferred target collection

* decoder: Account for JSON in ref. targets for LiteralType

* decoder: Account for JSON keys in rawObjectKey

* decoder: Account for JSON when collecting targets for Map/Object

* decoder: Add tests for reference targets (OneOf)

* decoder: Account for legacy JSON syntax in Reference

* schema: Fix typo in validation error

* decoder: Only pass TargetContext when there are targets to collect

* decoder: Add tests for reference targets (List)

* decoder: Add tests for reference targets (Set)

* decoder: Add tests for reference targets (Tuple)

* decoder: Add tests for reference targets (Object)

* decoder: Add tests for reference targets (Map)

* decoder: Add tests for reference targets (LiteralType)
  • Loading branch information
radeksimko authored Mar 30, 2023
1 parent 1e612ae commit 4644fb0
Show file tree
Hide file tree
Showing 22 changed files with 9,434 additions and 148 deletions.
75 changes: 65 additions & 10 deletions decoder/expr_list_ref_targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,33 @@ import (

"github.com/hashicorp/hcl-lang/lang"
"github.com/hashicorp/hcl-lang/reference"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl/v2"
"github.com/zclconf/go-cty/cty"
)

func (list List) ReferenceTargets(ctx context.Context, targetCtx *TargetContext) reference.Targets {
eType, ok := list.expr.(*hclsyntax.TupleConsExpr)
if !ok {
elems, diags := hcl.ExprList(list.expr)
if diags.HasErrors() {
return reference.Targets{}
}

if len(eType.Exprs) == 0 || list.cons.Elem == nil {
if list.cons.Elem == nil {
return reference.Targets{}
}

targets := make(reference.Targets, 0)

// TODO: collect parent target for the whole list
// See https://github.com/hashicorp/hcl-lang/issues/228
elemTargets := make(reference.Targets, 0)

for i, elemExpr := range eType.Exprs {
for i, elemExpr := range elems {
expr := newExpression(list.pathCtx, elemExpr, list.cons.Elem)
if e, ok := expr.(ReferenceTargetsExpression); ok {
if targetCtx == nil {
// collect any targets inside the expression
// if attribute itself isn't targetable
elemTargets = append(elemTargets, e.ReferenceTargets(ctx, nil)...)
continue
}

elemCtx := targetCtx.Copy()
elemCtx.ParentAddress = append(elemCtx.ParentAddress, lang.IndexStep{
Key: cty.NumberIntVal(int64(i)),
Expand All @@ -37,8 +42,58 @@ func (list List) ReferenceTargets(ctx context.Context, targetCtx *TargetContext)
})
}

targets = append(targets, e.ReferenceTargets(ctx, elemCtx)...)
elemTargets = append(elemTargets, e.ReferenceTargets(ctx, elemCtx)...)
}
}

targets := make(reference.Targets, 0)

if targetCtx != nil {
// collect target for the whole list

var rangePtr *hcl.Range
if targetCtx.ParentRangePtr != nil {
rangePtr = targetCtx.ParentRangePtr
} else {
rangePtr = list.expr.Range().Ptr()
}

// type-aware
elemCons, ok := list.cons.Elem.(schema.TypeAwareConstraint)
if targetCtx.AsExprType && ok {
elemType, ok := elemCons.ConstraintType()
if ok {
targets = append(targets, reference.Target{
Addr: targetCtx.ParentAddress,
Name: targetCtx.FriendlyName,
Type: cty.List(elemType),
ScopeId: targetCtx.ScopeId,
RangePtr: rangePtr,
DefRangePtr: targetCtx.ParentDefRangePtr,
NestedTargets: elemTargets,
LocalAddr: targetCtx.ParentLocalAddress,
TargetableFromRangePtr: targetCtx.TargetableFromRangePtr,
})
}
}

// type-unaware
if targetCtx.AsReference {
targets = append(targets, reference.Target{
Addr: targetCtx.ParentAddress,
Name: targetCtx.FriendlyName,
ScopeId: targetCtx.ScopeId,
RangePtr: rangePtr,
DefRangePtr: targetCtx.ParentDefRangePtr,
NestedTargets: elemTargets,
LocalAddr: targetCtx.ParentLocalAddress,
TargetableFromRangePtr: targetCtx.TargetableFromRangePtr,
})
}
} else {
// treat element targets as 1st class ones
// if the list itself isn't targetable
targets = elemTargets
}

return targets
Expand Down
Loading

0 comments on commit 4644fb0

Please sign in to comment.