github.com/hashicorp/hcl/v2@v2.20.0/ext/dynblock/unknown_body.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package dynblock 5 6 import ( 7 "github.com/hashicorp/hcl/v2" 8 "github.com/zclconf/go-cty/cty" 9 ) 10 11 // unknownBody is a funny body that just reports everything inside it as 12 // unknown. It uses a given other body as a sort of template for what attributes 13 // and blocks are inside -- including source location information -- but 14 // subsitutes unknown values of unknown type for all attributes. 15 // 16 // This rather odd process is used to handle expansion of dynamic blocks whose 17 // for_each expression is unknown. Since a block cannot itself be unknown, 18 // we instead arrange for everything _inside_ the block to be unknown instead, 19 // to give the best possible approximation. 20 type unknownBody struct { 21 template hcl.Body 22 } 23 24 var _ hcl.Body = unknownBody{} 25 26 // hcldec.UnkownBody impl 27 func (b unknownBody) Unknown() bool { 28 return true 29 } 30 31 func (b unknownBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) { 32 content, diags := b.template.Content(schema) 33 content = b.fixupContent(content) 34 35 // We're intentionally preserving the diagnostics reported from the 36 // inner body so that we can still report where the template body doesn't 37 // match the requested schema. 38 return content, diags 39 } 40 41 func (b unknownBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) { 42 content, remain, diags := b.template.PartialContent(schema) 43 content = b.fixupContent(content) 44 remain = unknownBody{remain} // remaining content must also be wrapped 45 46 // We're intentionally preserving the diagnostics reported from the 47 // inner body so that we can still report where the template body doesn't 48 // match the requested schema. 49 return content, remain, diags 50 } 51 52 func (b unknownBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) { 53 attrs, diags := b.template.JustAttributes() 54 attrs = b.fixupAttrs(attrs) 55 56 // We're intentionally preserving the diagnostics reported from the 57 // inner body so that we can still report where the template body doesn't 58 // match the requested schema. 59 return attrs, diags 60 } 61 62 func (b unknownBody) MissingItemRange() hcl.Range { 63 return b.template.MissingItemRange() 64 } 65 66 func (b unknownBody) fixupContent(got *hcl.BodyContent) *hcl.BodyContent { 67 ret := &hcl.BodyContent{} 68 ret.Attributes = b.fixupAttrs(got.Attributes) 69 if len(got.Blocks) > 0 { 70 ret.Blocks = make(hcl.Blocks, 0, len(got.Blocks)) 71 for _, gotBlock := range got.Blocks { 72 new := *gotBlock // shallow copy 73 new.Body = unknownBody{gotBlock.Body} // nested content must also be marked unknown 74 ret.Blocks = append(ret.Blocks, &new) 75 } 76 } 77 78 return ret 79 } 80 81 func (b unknownBody) fixupAttrs(got hcl.Attributes) hcl.Attributes { 82 if len(got) == 0 { 83 return nil 84 } 85 ret := make(hcl.Attributes, len(got)) 86 for name, gotAttr := range got { 87 new := *gotAttr // shallow copy 88 new.Expr = hcl.StaticExpr(cty.DynamicVal, gotAttr.Expr.Range()) 89 ret[name] = &new 90 } 91 return ret 92 }