From 468c47ee72a9b6f129a71b6ba84749d192124f2b Mon Sep 17 00:00:00 2001 From: James Pogran Date: Mon, 12 Aug 2024 12:25:53 -0400 Subject: [PATCH] Implement collection of object attributes origins This commit adds the collection of origins for object attributes. If an object attribute has an OriginForTarget, it will be collected and returned as part of the object reference origins. --- decoder/expr_object_ref_origins.go | 58 ++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/decoder/expr_object_ref_origins.go b/decoder/expr_object_ref_origins.go index 71bab1fd..c117a6e1 100644 --- a/decoder/expr_object_ref_origins.go +++ b/decoder/expr_object_ref_origins.go @@ -6,6 +6,7 @@ package decoder import ( "context" + "github.com/hashicorp/hcl-lang/lang" "github.com/hashicorp/hcl-lang/reference" "github.com/hashicorp/hcl-lang/schema" "github.com/hashicorp/hcl/v2" @@ -54,7 +55,64 @@ func (obj Object) ReferenceOrigins(ctx context.Context, allowSelfRefs bool) refe origins = append(origins, elemExpr.ReferenceOrigins(ctx, allowSelfRefs)...) } } + + if aSchema != nil && aSchema.OriginForTarget != nil { + address, ok := resolveObjectAddress(attrName, aSchema.OriginForTarget.Address) + if !ok { + continue + } + + origins = append(origins, reference.PathOrigin{ + Range: item.Key.Range(), + TargetAddr: address, + TargetPath: aSchema.OriginForTarget.Path, + Constraints: reference.OriginConstraints{ + { + OfScopeId: aSchema.OriginForTarget.Constraints.ScopeId, + OfType: aSchema.OriginForTarget.Constraints.Type, + }, + }, + }) + } } return origins } + +func resolveObjectAddress(attrName string, addr schema.Address) (lang.Address, bool) { + // This function is a simplified version of the original resolveAttributeAddress + // because we don't have an attribute to pass + + address := make(lang.Address, 0) + + if len(addr) == 0 { + return lang.Address{}, false + } + + for i, s := range addr { + var stepName string + + switch step := s.(type) { + case schema.StaticStep: + stepName = step.Name + case schema.AttrNameStep: + stepName = attrName + // TODO: AttrValueStep? Currently no use case for it + default: + // unknown step + return lang.Address{}, false + } + + if i == 0 { + address = append(address, lang.RootStep{ + Name: stepName, + }) + continue + } + address = append(address, lang.AttrStep{ + Name: stepName, + }) + } + + return address, true +}