| // Copyright IBM Corp. 2014, 2026 | |
| // SPDX-License-Identifier: BUSL-1.1 | |
| package stackaddrs | |
| import ( | |
| "reflect" | |
| "github.com/hashicorp/terraform/internal/collections" | |
| ) | |
| // Referenceable is a type set containing all address types that can be | |
| // the target of an expression-based reference within a particular stack. | |
| type Referenceable interface { | |
| referenceableSigil() | |
| String() string | |
| } | |
| var _ Referenceable = Component{} | |
| var _ Referenceable = StackCall{} | |
| var _ Referenceable = InputVariable{} | |
| var _ Referenceable = LocalValue{} | |
| var _ Referenceable = ProviderConfigRef{} | |
| var _ Referenceable = TestOnlyGlobal{} | |
| var _ Referenceable = ContextualRef(0) | |
| // ReferenceableUniqueKey returns a unique key for a dynamically-typed | |
| // referenceable address. | |
| // | |
| // Since the type of the target isn't statically known, the resulting unique | |
| // key is not comparable with unique keys of the specific static types | |
| // that implement [Referenceable]. | |
| func ReferenceableUniqueKey(addr Referenceable) collections.UniqueKey[Referenceable] { | |
| // NOTE: This assumes that all distinct referenceable addresses have | |
| // distinct and unique string representations. | |
| return referenceableUniqueKey{ | |
| ty: reflect.TypeOf(addr), | |
| str: addr.String(), | |
| } | |
| } | |
| type referenceableUniqueKey struct { | |
| ty reflect.Type | |
| str string | |
| } | |
| // IsUniqueKey implements collections.UniqueKey. | |
| func (referenceableUniqueKey) IsUniqueKey(Referenceable) {} | |
| type ContextualRef rune | |
| const EachValue = ContextualRef('v') | |
| const EachKey = ContextualRef('k') | |
| const CountIndex = ContextualRef('i') | |
| const Self = ContextualRef('s') | |
| const TerraformApplying = ContextualRef('a') | |
| // String implements Referenceable. | |
| func (e ContextualRef) String() string { | |
| switch e { | |
| case EachKey: | |
| return "each.key" | |
| case EachValue: | |
| return "each.value" | |
| case CountIndex: | |
| return "count.index" | |
| case Self: | |
| return "self" | |
| case TerraformApplying: | |
| return "terraform.applying" | |
| default: | |
| // The four constants in this package are the only valid values of this type | |
| panic("invalid ContextualRef instance") | |
| } | |
| } | |
| // referenceableSigil implements Referenceable. | |
| func (e ContextualRef) referenceableSigil() {} | |
| // AbsReferenceable is a [Referenceable] combined with the stack it would | |
| // be resolved in. | |
| // | |
| // This type can be used only for [Referenceable] types that have stack-wide | |
| // scope. It's not appropriate for referenceable objects with more specific | |
| // scope, such as [ContextualRef], since describing those would require | |
| // information about which specific block they are to be resolved within. | |
| type AbsReferenceable struct { | |
| Stack StackInstance | |
| Item Referenceable | |
| } | |
| func (r AbsReferenceable) UniqueKey() collections.UniqueKey[AbsReferenceable] { | |
| return absReferenceableKey{ | |
| stackKey: r.Stack.UniqueKey(), | |
| itemKey: ReferenceableUniqueKey(r.Item), | |
| } | |
| } | |
| type absReferenceableKey struct { | |
| stackKey collections.UniqueKey[StackInstance] | |
| itemKey collections.UniqueKey[Referenceable] | |
| } | |
| // IsUniqueKey implements collections.UniqueKey. | |
| func (absReferenceableKey) IsUniqueKey(AbsReferenceable) { | |
| panic("unimplemented") | |
| } |