diff --git a/go.mod b/go.mod index d35689306e..bc8f7e6f0d 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/hashicorp/go-version v0.0.0-20180322230233-23480c066577 github.com/hashicorp/golang-lru v0.5.0 // indirect github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f - github.com/hashicorp/hcl2 v0.0.0-20180925175540-3f1c5474d4f7 + github.com/hashicorp/hcl2 v0.0.0-20181126233546-67424e43b184 github.com/hashicorp/hil v0.0.0-20170627220502-fa9f258a9250 github.com/hashicorp/logutils v0.0.0-20150609070431-0dc08b1671f3 github.com/hashicorp/memberlist v0.1.0 // indirect diff --git a/go.sum b/go.sum index 6adc6d5c53..4a41abe2ee 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,8 @@ github.com/blang/semver v0.0.0-20170202183821-4a1e882c79dc h1:J/iAaGTCZYfT/allw6 github.com/blang/semver v0.0.0-20170202183821-4a1e882c79dc/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e h1:D64GF/Xr5zSUnM3q1Jylzo4sK7szhP/ON+nb2DB5XJA= +github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e/go.mod h1:N+BjUcTjSxc2mtRGSCPsat1kze3CUtvJN3/jTXlp29k= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20161106042343-c914be64f07d h1:aG5FcWiZTOhPQzYIxwxSR1zEOxzL32fwr1CsaCfhO6w= @@ -166,6 +168,10 @@ github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f h1:UdxlrJz4JOnY8W+Db github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hashicorp/hcl2 v0.0.0-20180925175540-3f1c5474d4f7 h1:lNBI8nmNlIpLl8Lqf+9JLBmNGrU91Nlt71q7cGpZi+k= github.com/hashicorp/hcl2 v0.0.0-20180925175540-3f1c5474d4f7/go.mod h1:hrRmgPTdXWuNLpHcv7cRXL+ofoFsY76vDylTzH8eu3E= +github.com/hashicorp/hcl2 v0.0.0-20181123160133-f901b36da204 h1:/rUVBMdrcpWOwNw5KFhqrbMVnbgsN1zJOp5sAEx2XXQ= +github.com/hashicorp/hcl2 v0.0.0-20181123160133-f901b36da204/go.mod h1:4nBvwJRETsbpa0LQ7FbXXVFmo0Crvhya1Dmpbm7cVow= +github.com/hashicorp/hcl2 v0.0.0-20181126233546-67424e43b184 h1:cBDzEsx+Tm9vHp9WiUeBlhPazwbbKJxOiRAT+pVLuag= +github.com/hashicorp/hcl2 v0.0.0-20181126233546-67424e43b184/go.mod h1:4nBvwJRETsbpa0LQ7FbXXVFmo0Crvhya1Dmpbm7cVow= github.com/hashicorp/hil v0.0.0-20170627220502-fa9f258a9250 h1:fooK5IvDL/KIsi4LxF/JH68nVdrBSiGNPhS2JAQjtjo= github.com/hashicorp/hil v0.0.0-20170627220502-fa9f258a9250/go.mod h1:KHvg/R2/dPtaePb16oW4qIyzkMxXOL38xjRN64adsts= github.com/hashicorp/logutils v0.0.0-20150609070431-0dc08b1671f3 h1:oD64EFjELI9RY9yoWlfua58r+etdnoIC871z+rr6lkA= diff --git a/vendor/github.com/hashicorp/hcl2/gohcl/doc.go b/vendor/github.com/hashicorp/hcl2/gohcl/doc.go index 8500214bf0..aa3c6ea9ef 100644 --- a/vendor/github.com/hashicorp/hcl2/gohcl/doc.go +++ b/vendor/github.com/hashicorp/hcl2/gohcl/doc.go @@ -40,6 +40,10 @@ // present then any attributes or blocks not matched by another valid tag // will cause an error diagnostic. // +// Only a subset of this tagging/typing vocabulary is supported for the +// "Encode" family of functions. See the EncodeIntoBody docs for full details +// on the constraints there. +// // Broadly-speaking this package deals with two types of error. The first is // errors in the configuration itself, which are returned as diagnostics // written with the configuration author as the target audience. The second diff --git a/vendor/github.com/hashicorp/hcl2/gohcl/encode.go b/vendor/github.com/hashicorp/hcl2/gohcl/encode.go new file mode 100644 index 0000000000..3cbf7e48af --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/gohcl/encode.go @@ -0,0 +1,191 @@ +package gohcl + +import ( + "fmt" + "reflect" + "sort" + + "github.com/hashicorp/hcl2/hclwrite" + "github.com/zclconf/go-cty/cty/gocty" +) + +// EncodeIntoBody replaces the contents of the given hclwrite Body with +// attributes and blocks derived from the given value, which must be a +// struct value or a pointer to a struct value with the struct tags defined +// in this package. +// +// This function can work only with fully-decoded data. It will ignore any +// fields tagged as "remain", any fields that decode attributes into either +// hcl.Attribute or hcl.Expression values, and any fields that decode blocks +// into hcl.Attributes values. This function does not have enough information +// to complete the decoding of these types. +// +// Any fields tagged as "label" are ignored by this function. Use EncodeAsBlock +// to produce a whole hclwrite.Block including block labels. +// +// As long as a suitable value is given to encode and the destination body +// is non-nil, this function will always complete. It will panic in case of +// any errors in the calling program, such as passing an inappropriate type +// or a nil body. +// +// The layout of the resulting HCL source is derived from the ordering of +// the struct fields, with blank lines around nested blocks of different types. +// Fields representing attributes should usually precede those representing +// blocks so that the attributes can group togather in the result. For more +// control, use the hclwrite API directly. +func EncodeIntoBody(val interface{}, dst *hclwrite.Body) { + rv := reflect.ValueOf(val) + ty := rv.Type() + if ty.Kind() == reflect.Ptr { + rv = rv.Elem() + ty = rv.Type() + } + if ty.Kind() != reflect.Struct { + panic(fmt.Sprintf("value is %s, not struct", ty.Kind())) + } + + tags := getFieldTags(ty) + populateBody(rv, ty, tags, dst) +} + +// EncodeAsBlock creates a new hclwrite.Block populated with the data from +// the given value, which must be a struct or pointer to struct with the +// struct tags defined in this package. +// +// If the given struct type has fields tagged with "label" tags then they +// will be used in order to annotate the created block with labels. +// +// This function has the same constraints as EncodeIntoBody and will panic +// if they are violated. +func EncodeAsBlock(val interface{}, blockType string) *hclwrite.Block { + rv := reflect.ValueOf(val) + ty := rv.Type() + if ty.Kind() == reflect.Ptr { + rv = rv.Elem() + ty = rv.Type() + } + if ty.Kind() != reflect.Struct { + panic(fmt.Sprintf("value is %s, not struct", ty.Kind())) + } + + tags := getFieldTags(ty) + labels := make([]string, len(tags.Labels)) + for i, lf := range tags.Labels { + lv := rv.Field(lf.FieldIndex) + // We just stringify whatever we find. It should always be a string + // but if not then we'll still do something reasonable. + labels[i] = fmt.Sprintf("%s", lv.Interface()) + } + + block := hclwrite.NewBlock(blockType, labels) + populateBody(rv, ty, tags, block.Body()) + return block +} + +func populateBody(rv reflect.Value, ty reflect.Type, tags *fieldTags, dst *hclwrite.Body) { + nameIdxs := make(map[string]int, len(tags.Attributes)+len(tags.Blocks)) + namesOrder := make([]string, 0, len(tags.Attributes)+len(tags.Blocks)) + for n, i := range tags.Attributes { + nameIdxs[n] = i + namesOrder = append(namesOrder, n) + } + for n, i := range tags.Blocks { + nameIdxs[n] = i + namesOrder = append(namesOrder, n) + } + sort.SliceStable(namesOrder, func(i, j int) bool { + ni, nj := namesOrder[i], namesOrder[j] + return nameIdxs[ni] < nameIdxs[nj] + }) + + dst.Clear() + + prevWasBlock := false + for _, name := range namesOrder { + fieldIdx := nameIdxs[name] + field := ty.Field(fieldIdx) + fieldTy := field.Type + fieldVal := rv.Field(fieldIdx) + + if fieldTy.Kind() == reflect.Ptr { + fieldTy = fieldTy.Elem() + fieldVal = fieldVal.Elem() + } + + if _, isAttr := tags.Attributes[name]; isAttr { + + if exprType.AssignableTo(fieldTy) || attrType.AssignableTo(fieldTy) { + continue // ignore undecoded fields + } + if !fieldVal.IsValid() { + continue // ignore (field value is nil pointer) + } + if fieldTy.Kind() == reflect.Ptr && fieldVal.IsNil() { + continue // ignore + } + if prevWasBlock { + dst.AppendNewline() + prevWasBlock = false + } + + valTy, err := gocty.ImpliedType(fieldVal.Interface()) + if err != nil { + panic(fmt.Sprintf("cannot encode %T as HCL expression: %s", fieldVal.Interface(), err)) + } + + val, err := gocty.ToCtyValue(fieldVal.Interface(), valTy) + if err != nil { + // This should never happen, since we should always be able + // to decode into the implied type. + panic(fmt.Sprintf("failed to encode %T as %#v: %s", fieldVal.Interface(), valTy, err)) + } + + dst.SetAttributeValue(name, val) + + } else { // must be a block, then + elemTy := fieldTy + isSeq := false + if elemTy.Kind() == reflect.Slice || elemTy.Kind() == reflect.Array { + isSeq = true + elemTy = elemTy.Elem() + } + + if bodyType.AssignableTo(elemTy) || attrsType.AssignableTo(elemTy) { + continue // ignore undecoded fields + } + prevWasBlock = false + + if isSeq { + l := fieldVal.Len() + for i := 0; i < l; i++ { + elemVal := fieldVal.Index(i) + if !elemVal.IsValid() { + continue // ignore (elem value is nil pointer) + } + if elemTy.Kind() == reflect.Ptr && elemVal.IsNil() { + continue // ignore + } + block := EncodeAsBlock(elemVal.Interface(), name) + if !prevWasBlock { + dst.AppendNewline() + prevWasBlock = true + } + dst.AppendBlock(block) + } + } else { + if !fieldVal.IsValid() { + continue // ignore (field value is nil pointer) + } + if elemTy.Kind() == reflect.Ptr && fieldVal.IsNil() { + continue // ignore + } + block := EncodeAsBlock(fieldVal.Interface(), name) + if !prevWasBlock { + dst.AppendNewline() + prevWasBlock = true + } + dst.AppendBlock(block) + } + } + } +} diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go index 13cb46f20f..f375e1b92b 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go @@ -132,7 +132,7 @@ type RelativeTraversalExpr struct { } func (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) { - e.Source = w(e.Source).(Expression) + w(e.Source) } func (e *RelativeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { @@ -181,8 +181,8 @@ type FunctionCallExpr struct { } func (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) { - for i, arg := range e.Args { - e.Args[i] = w(arg).(Expression) + for _, arg := range e.Args { + w(arg) } } @@ -463,9 +463,9 @@ type ConditionalExpr struct { } func (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) { - e.Condition = w(e.Condition).(Expression) - e.TrueResult = w(e.TrueResult).(Expression) - e.FalseResult = w(e.FalseResult).(Expression) + w(e.Condition) + w(e.TrueResult) + w(e.FalseResult) } func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { @@ -593,8 +593,8 @@ type IndexExpr struct { } func (e *IndexExpr) walkChildNodes(w internalWalkFunc) { - e.Collection = w(e.Collection).(Expression) - e.Key = w(e.Key).(Expression) + w(e.Collection) + w(e.Key) } func (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { @@ -625,8 +625,8 @@ type TupleConsExpr struct { } func (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) { - for i, expr := range e.Exprs { - e.Exprs[i] = w(expr).(Expression) + for _, expr := range e.Exprs { + w(expr) } } @@ -674,9 +674,9 @@ type ObjectConsItem struct { } func (e *ObjectConsExpr) walkChildNodes(w internalWalkFunc) { - for i, item := range e.Items { - e.Items[i].KeyExpr = w(item.KeyExpr).(Expression) - e.Items[i].ValueExpr = w(item.ValueExpr).(Expression) + for _, item := range e.Items { + w(item.KeyExpr) + w(item.ValueExpr) } } @@ -792,7 +792,7 @@ func (e *ObjectConsKeyExpr) walkChildNodes(w internalWalkFunc) { // We only treat our wrapped expression as a real expression if we're // not going to interpret it as a literal. if e.literalName() == "" { - e.Wrapped = w(e.Wrapped).(Expression) + w(e.Wrapped) } } @@ -1157,7 +1157,7 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { } func (e *ForExpr) walkChildNodes(w internalWalkFunc) { - e.CollExpr = w(e.CollExpr).(Expression) + w(e.CollExpr) scopeNames := map[string]struct{}{} if e.KeyVar != "" { @@ -1170,17 +1170,17 @@ func (e *ForExpr) walkChildNodes(w internalWalkFunc) { if e.KeyExpr != nil { w(ChildScope{ LocalNames: scopeNames, - Expr: &e.KeyExpr, + Expr: e.KeyExpr, }) } w(ChildScope{ LocalNames: scopeNames, - Expr: &e.ValExpr, + Expr: e.ValExpr, }) if e.CondExpr != nil { w(ChildScope{ LocalNames: scopeNames, - Expr: &e.CondExpr, + Expr: e.CondExpr, }) } } @@ -1266,8 +1266,8 @@ func (e *SplatExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { } func (e *SplatExpr) walkChildNodes(w internalWalkFunc) { - e.Source = w(e.Source).(Expression) - e.Each = w(e.Each).(Expression) + w(e.Source) + w(e.Each) } func (e *SplatExpr) Range() hcl.Range { diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go index ee96a0d712..7f59f1a275 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go @@ -129,8 +129,8 @@ type BinaryOpExpr struct { } func (e *BinaryOpExpr) walkChildNodes(w internalWalkFunc) { - e.LHS = w(e.LHS).(Expression) - e.RHS = w(e.RHS).(Expression) + w(e.LHS) + w(e.RHS) } func (e *BinaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { @@ -212,7 +212,7 @@ type UnaryOpExpr struct { } func (e *UnaryOpExpr) walkChildNodes(w internalWalkFunc) { - e.Val = w(e.Val).(Expression) + w(e.Val) } func (e *UnaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_template.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_template.go index 6aa6b60ff0..fa79e3d08f 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_template.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_template.go @@ -16,8 +16,8 @@ type TemplateExpr struct { } func (e *TemplateExpr) walkChildNodes(w internalWalkFunc) { - for i, part := range e.Parts { - e.Parts[i] = w(part).(Expression) + for _, part := range e.Parts { + w(part) } } @@ -98,7 +98,7 @@ type TemplateJoinExpr struct { } func (e *TemplateJoinExpr) walkChildNodes(w internalWalkFunc) { - e.Tuple = w(e.Tuple).(Expression) + w(e.Tuple) } func (e *TemplateJoinExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { @@ -184,7 +184,7 @@ type TemplateWrapExpr struct { } func (e *TemplateWrapExpr) walkChildNodes(w internalWalkFunc) { - e.Wrapped = w(e.Wrapped).(Expression) + w(e.Wrapped) } func (e *TemplateWrapExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/navigation.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/navigation.go index 4d41b6b662..c8c97f37cd 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/navigation.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/navigation.go @@ -3,6 +3,8 @@ package hclsyntax import ( "bytes" "fmt" + + "github.com/hashicorp/hcl2/hcl" ) type navigation struct { @@ -39,3 +41,19 @@ func (n navigation) ContextString(offset int) string { } return buf.String() } + +func (n navigation) ContextDefRange(offset int) hcl.Range { + var block *Block + for _, candidate := range n.root.Blocks { + if candidate.Range().ContainsOffset(offset) { + block = candidate + break + } + } + + if block == nil { + return hcl.Range{} + } + + return block.DefRange() +} diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/node.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/node.go index fd426d4a6c..75812e63dd 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/node.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/node.go @@ -19,4 +19,4 @@ type Node interface { Range() hcl.Range } -type internalWalkFunc func(Node) Node +type internalWalkFunc func(Node) diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser.go index 009b93043d..5784f0c9ce 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/parser.go @@ -273,7 +273,10 @@ Token: return &Block{ Type: blockType, Labels: labels, - Body: nil, + Body: &Body{ + SrcRange: ident.Range, + EndRange: ident.Range, + }, TypeRange: ident.Range, LabelRanges: labelRanges, diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure.go index 089311df89..ebafcb4963 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure.go @@ -47,8 +47,8 @@ type Body struct { var assertBodyImplBody hcl.Body = &Body{} func (b *Body) walkChildNodes(w internalWalkFunc) { - b.Attributes = w(b.Attributes).(Attributes) - b.Blocks = w(b.Blocks).(Blocks) + w(b.Attributes) + w(b.Blocks) } func (b *Body) Range() hcl.Range { @@ -86,8 +86,8 @@ func (b *Body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostic diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, - Summary: "Unsupported attribute", - Detail: fmt.Sprintf("An attribute named %q is not expected here.%s", name, suggestion), + Summary: "Unsupported argument", + Detail: fmt.Sprintf("An argument named %q is not expected here.%s", name, suggestion), Subject: &attr.NameRange, }) } @@ -107,7 +107,7 @@ func (b *Body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostic // Is there an attribute of the same name? for _, attrS := range schema.Attributes { if attrS.Name == blockTy { - suggestion = fmt.Sprintf(" Did you mean to define attribute %q?", blockTy) + suggestion = fmt.Sprintf(" Did you mean to define argument %q? If so, use the equals sign to assign it a value.", blockTy) break } } @@ -151,8 +151,8 @@ func (b *Body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Bod if attrS.Required { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, - Summary: "Missing required attribute", - Detail: fmt.Sprintf("The attribute %q is required, but no definition was found.", attrS.Name), + Summary: "Missing required argument", + Detail: fmt.Sprintf("The argument %q is required, but no definition was found.", attrS.Name), Subject: b.MissingItemRange().Ptr(), }) } @@ -286,8 +286,8 @@ func (b *Body) MissingItemRange() hcl.Range { type Attributes map[string]*Attribute func (a Attributes) walkChildNodes(w internalWalkFunc) { - for k, attr := range a { - a[k] = w(attr).(*Attribute) + for _, attr := range a { + w(attr) } } @@ -321,7 +321,7 @@ type Attribute struct { } func (a *Attribute) walkChildNodes(w internalWalkFunc) { - a.Expr = w(a.Expr).(Expression) + w(a.Expr) } func (a *Attribute) Range() hcl.Range { @@ -346,8 +346,8 @@ func (a *Attribute) AsHCLAttribute() *hcl.Attribute { type Blocks []*Block func (bs Blocks) walkChildNodes(w internalWalkFunc) { - for i, block := range bs { - bs[i] = w(block).(*Block) + for _, block := range bs { + w(block) } } @@ -378,9 +378,13 @@ type Block struct { } func (b *Block) walkChildNodes(w internalWalkFunc) { - b.Body = w(b.Body).(*Body) + w(b.Body) } func (b *Block) Range() hcl.Range { return hcl.RangeBetween(b.TypeRange, b.CloseBraceRange) } + +func (b *Block) DefRange() hcl.Range { + return hcl.RangeBetween(b.TypeRange, b.OpenBraceRange) +} diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go index eeee1a529a..91f417f873 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go @@ -72,15 +72,15 @@ func (w *variablesWalker) Exit(n Node) hcl.Diagnostics { // that the child scope struct wraps. type ChildScope struct { LocalNames map[string]struct{} - Expr *Expression // pointer because it can be replaced on walk + Expr Expression } func (e ChildScope) walkChildNodes(w internalWalkFunc) { - *(e.Expr) = w(*(e.Expr)).(Expression) + w(e.Expr) } // Range returns the range of the expression that the ChildScope is // encapsulating. It isn't really very useful to call Range on a ChildScope. func (e ChildScope) Range() hcl.Range { - return (*e.Expr).Range() + return e.Expr.Range() } diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/walk.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/walk.go index e069cf6c71..90f81c9c1c 100644 --- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/walk.go +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/walk.go @@ -15,9 +15,8 @@ type VisitFunc func(node Node) hcl.Diagnostics // and returned as a single set. func VisitAll(node Node, f VisitFunc) hcl.Diagnostics { diags := f(node) - node.walkChildNodes(func(node Node) Node { + node.walkChildNodes(func(node Node) { diags = append(diags, VisitAll(node, f)...) - return node }) return diags } @@ -33,47 +32,10 @@ type Walker interface { // Enter and Exit functions. func Walk(node Node, w Walker) hcl.Diagnostics { diags := w.Enter(node) - node.walkChildNodes(func(node Node) Node { + node.walkChildNodes(func(node Node) { diags = append(diags, Walk(node, w)...) - return node }) moreDiags := w.Exit(node) diags = append(diags, moreDiags...) return diags } - -// Transformer is an interface used with Transform -type Transformer interface { - // Transform accepts a node and returns a replacement node along with - // a flag for whether to also visit child nodes. If the flag is false, - // none of the child nodes will be visited and the TransformExit method - // will not be called for the node. - // - // It is acceptable and appropriate for Transform to return the same node - // it was given, for situations where no transform is needed. - Transform(node Node) (Node, bool, hcl.Diagnostics) - - // TransformExit signals the end of transformations of child nodes of the - // given node. If Transform returned a new node, the given node is the - // node that was returned, rather than the node that was originally - // encountered. - TransformExit(node Node) hcl.Diagnostics -} - -// Transform allows for in-place transformations of an AST starting with a -// particular node. The provider Transformer implementation drives the -// transformation process. The return value is the node that replaced the -// given top-level node. -func Transform(node Node, t Transformer) (Node, hcl.Diagnostics) { - newNode, descend, diags := t.Transform(node) - if !descend { - return newNode, diags - } - node.walkChildNodes(func(node Node) Node { - newNode, newDiags := Transform(node, t) - diags = append(diags, newDiags...) - return newNode - }) - diags = append(diags, t.TransformExit(newNode)...) - return newNode, diags -} diff --git a/vendor/github.com/hashicorp/hcl2/hcled/navigation.go b/vendor/github.com/hashicorp/hcl2/hcled/navigation.go index b63a3f46c3..5d10cd86ce 100644 --- a/vendor/github.com/hashicorp/hcl2/hcled/navigation.go +++ b/vendor/github.com/hashicorp/hcl2/hcled/navigation.go @@ -18,3 +18,17 @@ func ContextString(file *hcl.File, offset int) string { } return "" } + +type contextDefRanger interface { + ContextDefRange(offset int) hcl.Range +} + +func ContextDefRange(file *hcl.File, offset int) hcl.Range { + if cser, ok := file.Nav.(contextDefRanger); ok { + defRange := cser.ContextDefRange(offset) + if !defRange.Empty() { + return defRange + } + } + return file.Body.MissingItemRange() +} diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/ast.go b/vendor/github.com/hashicorp/hcl2/hclwrite/ast.go index 7620b839f3..090416528d 100644 --- a/vendor/github.com/hashicorp/hcl2/hclwrite/ast.go +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/ast.go @@ -12,6 +12,17 @@ type File struct { body *node } +// NewEmptyFile constructs a new file with no content, ready to be mutated +// by other calls that append to its body. +func NewEmptyFile() *File { + f := &File{ + inTree: newInTree(), + } + body := newBody() + f.body = f.children.Append(body) + return f +} + // Body returns the root body of the file, which contains the top-level // attributes and blocks. func (f *File) Body() *Body { @@ -22,7 +33,7 @@ func (f *File) Body() *Body { // // The tokens first have a simple formatting pass applied that adjusts only // the spaces between them. -func (f *File) WriteTo(wr io.Writer) (int, error) { +func (f *File) WriteTo(wr io.Writer) (int64, error) { tokens := f.inTree.children.BuildTokens(nil) format(tokens) return tokens.WriteTo(wr) diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/ast_attribute.go b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_attribute.go new file mode 100644 index 0000000000..975fa74280 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_attribute.go @@ -0,0 +1,48 @@ +package hclwrite + +import ( + "github.com/hashicorp/hcl2/hcl/hclsyntax" +) + +type Attribute struct { + inTree + + leadComments *node + name *node + expr *node + lineComments *node +} + +func newAttribute() *Attribute { + return &Attribute{ + inTree: newInTree(), + } +} + +func (a *Attribute) init(name string, expr *Expression) { + expr.assertUnattached() + + nameTok := newIdentToken(name) + nameObj := newIdentifier(nameTok) + a.leadComments = a.children.Append(newComments(nil)) + a.name = a.children.Append(nameObj) + a.children.AppendUnstructuredTokens(Tokens{ + { + Type: hclsyntax.TokenEqual, + Bytes: []byte{'='}, + }, + }) + a.expr = a.children.Append(expr) + a.expr.list = a.children + a.lineComments = a.children.Append(newComments(nil)) + a.children.AppendUnstructuredTokens(Tokens{ + { + Type: hclsyntax.TokenNewline, + Bytes: []byte{'\n'}, + }, + }) +} + +func (a *Attribute) Expr() *Expression { + return a.expr.content.(*Expression) +} diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/ast_block.go b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_block.go new file mode 100644 index 0000000000..d5fd32bd51 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_block.go @@ -0,0 +1,74 @@ +package hclwrite + +import ( + "github.com/hashicorp/hcl2/hcl/hclsyntax" + "github.com/zclconf/go-cty/cty" +) + +type Block struct { + inTree + + leadComments *node + typeName *node + labels nodeSet + open *node + body *node + close *node +} + +func newBlock() *Block { + return &Block{ + inTree: newInTree(), + labels: newNodeSet(), + } +} + +// NewBlock constructs a new, empty block with the given type name and labels. +func NewBlock(typeName string, labels []string) *Block { + block := newBlock() + block.init(typeName, labels) + return block +} + +func (b *Block) init(typeName string, labels []string) { + nameTok := newIdentToken(typeName) + nameObj := newIdentifier(nameTok) + b.leadComments = b.children.Append(newComments(nil)) + b.typeName = b.children.Append(nameObj) + for _, label := range labels { + labelToks := TokensForValue(cty.StringVal(label)) + labelObj := newQuoted(labelToks) + labelNode := b.children.Append(labelObj) + b.labels.Add(labelNode) + } + b.open = b.children.AppendUnstructuredTokens(Tokens{ + { + Type: hclsyntax.TokenOBrace, + Bytes: []byte{'{'}, + }, + { + Type: hclsyntax.TokenNewline, + Bytes: []byte{'\n'}, + }, + }) + body := newBody() // initially totally empty; caller can append to it subsequently + b.body = b.children.Append(body) + b.close = b.children.AppendUnstructuredTokens(Tokens{ + { + Type: hclsyntax.TokenCBrace, + Bytes: []byte{'}'}, + }, + { + Type: hclsyntax.TokenNewline, + Bytes: []byte{'\n'}, + }, + }) +} + +// Body returns the body that represents the content of the receiving block. +// +// Appending to or otherwise modifying this body will make changes to the +// tokens that are generated between the blocks open and close braces. +func (b *Block) Body() *Body { + return b.body.content.(*Body) +} diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/ast_body.go b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_body.go index d0d79fd7a1..cf69fee215 100644 --- a/vendor/github.com/hashicorp/hcl2/hclwrite/ast_body.go +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_body.go @@ -12,6 +12,13 @@ type Body struct { items nodeSet } +func newBody() *Body { + return &Body{ + inTree: newInTree(), + items: newNodeSet(), + } +} + func (b *Body) appendItem(c nodeContent) *node { nn := b.children.Append(c) b.items.Add(nn) @@ -25,10 +32,40 @@ func (b *Body) appendItemNode(nn *node) *node { return nn } +// Clear removes all of the items from the body, making it empty. +func (b *Body) Clear() { + b.children.Clear() +} + func (b *Body) AppendUnstructuredTokens(ts Tokens) { b.inTree.children.Append(ts) } +// Attributes returns a new map of all of the attributes in the body, with +// the attribute names as the keys. +func (b *Body) Attributes() map[string]*Attribute { + ret := make(map[string]*Attribute) + for n := range b.items { + if attr, isAttr := n.content.(*Attribute); isAttr { + nameObj := attr.name.content.(*identifier) + name := string(nameObj.token.Bytes) + ret[name] = attr + } + } + return ret +} + +// Blocks returns a new slice of all the blocks in the body. +func (b *Body) Blocks() []*Block { + ret := make([]*Block, 0, len(b.items)) + for n := range b.items { + if block, isBlock := n.content.(*Block); isBlock { + ret = append(ret, block) + } + } + return ret +} + // GetAttribute returns the attribute from the body that has the given name, // or returns nil if there is currently no matching attribute. func (b *Body) GetAttribute(name string) *Attribute { @@ -67,7 +104,7 @@ func (b *Body) SetAttributeValue(name string, val cty.Value) *Attribute { } // SetAttributeTraversal either replaces the expression of an existing attribute -// of the given name or adds a new attribute definition to the end of the block. +// of the given name or adds a new attribute definition to the end of the body. // // The new expression is given as a hcl.Traversal, which must be an absolute // traversal. To set a literal value, use SetAttributeValue. @@ -75,59 +112,42 @@ func (b *Body) SetAttributeValue(name string, val cty.Value) *Attribute { // The return value is the attribute that was either modified in-place or // created. func (b *Body) SetAttributeTraversal(name string, traversal hcl.Traversal) *Attribute { - panic("Body.SetAttributeTraversal not yet implemented") -} - -type Attribute struct { - inTree - - leadComments *node - name *node - expr *node - lineComments *node -} - -func newAttribute() *Attribute { - return &Attribute{ - inTree: newInTree(), + attr := b.GetAttribute(name) + expr := NewExpressionAbsTraversal(traversal) + if attr != nil { + attr.expr = attr.expr.ReplaceWith(expr) + } else { + attr := newAttribute() + attr.init(name, expr) + b.appendItem(attr) } + return attr } -func (a *Attribute) init(name string, expr *Expression) { - expr.assertUnattached() +// AppendBlock appends an existing block (which must not be already attached +// to a body) to the end of the receiving body. +func (b *Body) AppendBlock(block *Block) *Block { + b.appendItem(block) + return block +} - nameTok := newIdentToken(name) - nameObj := newIdentifier(nameTok) - a.leadComments = a.children.Append(newComments(nil)) - a.name = a.children.Append(nameObj) - a.children.AppendUnstructuredTokens(Tokens{ - { - Type: hclsyntax.TokenEqual, - Bytes: []byte{'='}, - }, - }) - a.expr = a.children.Append(expr) - a.expr.list = a.children - a.lineComments = a.children.Append(newComments(nil)) - a.children.AppendUnstructuredTokens(Tokens{ +// AppendNewBlock appends a new nested block to the end of the receiving body +// with the given type name and labels. +func (b *Body) AppendNewBlock(typeName string, labels []string) *Block { + block := newBlock() + block.init(typeName, labels) + b.appendItem(block) + return block +} + +// AppendNewline appends a newline token to th end of the receiving body, +// which generally serves as a separator between different sets of body +// contents. +func (b *Body) AppendNewline() { + b.AppendUnstructuredTokens(Tokens{ { Type: hclsyntax.TokenNewline, Bytes: []byte{'\n'}, }, }) } - -func (a *Attribute) Expr() *Expression { - return a.expr.content.(*Expression) -} - -type Block struct { - inTree - - leadComments *node - typeName *node - labels nodeSet - open *node - body *node - close *node -} diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/ast_expression.go b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_expression.go index cdd6e48f24..62d89fbefc 100644 --- a/vendor/github.com/hashicorp/hcl2/hclwrite/ast_expression.go +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_expression.go @@ -1,7 +1,10 @@ package hclwrite import ( + "fmt" + "github.com/hashicorp/hcl2/hcl" + "github.com/hashicorp/hcl2/hcl/hclsyntax" "github.com/zclconf/go-cty/cty" ) @@ -41,9 +44,125 @@ func NewExpressionLiteral(val cty.Value) *Expression { // NewExpressionAbsTraversal constructs an expression that represents the // given traversal, which must be absolute or this function will panic. func NewExpressionAbsTraversal(traversal hcl.Traversal) *Expression { - panic("NewExpressionAbsTraversal not yet implemented") + if traversal.IsRelative() { + panic("can't construct expression from relative traversal") + } + + physT := newTraversal() + rootName := traversal.RootName() + steps := traversal[1:] + + { + tn := newTraverseName() + tn.name = tn.children.Append(newIdentifier(&Token{ + Type: hclsyntax.TokenIdent, + Bytes: []byte(rootName), + })) + physT.steps.Add(physT.children.Append(tn)) + } + + for _, step := range steps { + switch ts := step.(type) { + case hcl.TraverseAttr: + tn := newTraverseName() + tn.children.AppendUnstructuredTokens(Tokens{ + { + Type: hclsyntax.TokenDot, + Bytes: []byte{'.'}, + }, + }) + tn.name = tn.children.Append(newIdentifier(&Token{ + Type: hclsyntax.TokenIdent, + Bytes: []byte(ts.Name), + })) + physT.steps.Add(physT.children.Append(tn)) + case hcl.TraverseIndex: + ti := newTraverseIndex() + ti.children.AppendUnstructuredTokens(Tokens{ + { + Type: hclsyntax.TokenOBrack, + Bytes: []byte{'['}, + }, + }) + indexExpr := NewExpressionLiteral(ts.Key) + ti.key = ti.children.Append(indexExpr) + ti.children.AppendUnstructuredTokens(Tokens{ + { + Type: hclsyntax.TokenCBrack, + Bytes: []byte{']'}, + }, + }) + physT.steps.Add(physT.children.Append(ti)) + } + } + + expr := newExpression() + expr.absTraversals.Add(expr.children.Append(physT)) + return expr } +// Variables returns the absolute traversals that exist within the receiving +// expression. +func (e *Expression) Variables() []*Traversal { + nodes := e.absTraversals.List() + ret := make([]*Traversal, len(nodes)) + for i, node := range nodes { + ret[i] = node.content.(*Traversal) + } + return ret +} + +// RenameVariablePrefix examines each of the absolute traversals in the +// receiving expression to see if they have the given sequence of names as +// a prefix prefix. If so, they are updated in place to have the given +// replacement names instead of that prefix. +// +// This can be used to implement symbol renaming. The calling application can +// visit all relevant expressions in its input and apply the same renaming +// to implement a global symbol rename. +// +// The search and replacement traversals must be the same length, or this +// method will panic. Only attribute access operations can be matched and +// replaced. Index steps never match the prefix. +func (e *Expression) RenameVariablePrefix(search, replacement []string) { + if len(search) != len(replacement) { + panic(fmt.Sprintf("search and replacement length mismatch (%d and %d)", len(search), len(replacement))) + } +Traversals: + for node := range e.absTraversals { + traversal := node.content.(*Traversal) + if len(traversal.steps) < len(search) { + // If it's shorter then it can't have our prefix + continue + } + + stepNodes := traversal.steps.List() + for i, name := range search { + step, isName := stepNodes[i].content.(*TraverseName) + if !isName { + continue Traversals // only name nodes can match + } + foundNameBytes := step.name.content.(*identifier).token.Bytes + if len(foundNameBytes) != len(name) { + continue Traversals + } + if string(foundNameBytes) != name { + continue Traversals + } + } + + // If we get here then the prefix matched, so now we'll swap in + // the replacement strings. + for i, name := range replacement { + step := stepNodes[i].content.(*TraverseName) + token := step.name.content.(*identifier).token + token.Bytes = []byte(name) + } + } +} + +// Traversal represents a sequence of variable, attribute, and/or index +// operations. type Traversal struct { inTree diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/doc.go b/vendor/github.com/hashicorp/hcl2/hclwrite/doc.go index 6f4109dec9..56d5b77526 100644 --- a/vendor/github.com/hashicorp/hcl2/hclwrite/doc.go +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/doc.go @@ -4,4 +4,8 @@ // It operates at a different level of abstraction than the main HCL parser // and AST, since details such as the placement of comments and newlines // are preserved when unchanged. +// +// The hclwrite API follows a similar principle to XML/HTML DOM, allowing nodes +// to be read out, created and inserted, etc. Nodes represent syntax constructs +// rather than semantic concepts. package hclwrite diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/generate.go b/vendor/github.com/hashicorp/hcl2/hclwrite/generate.go index 320ee6c0cb..d249cfdf9a 100644 --- a/vendor/github.com/hashicorp/hcl2/hclwrite/generate.go +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/generate.go @@ -5,6 +5,7 @@ import ( "unicode" "unicode/utf8" + "github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/hcl2/hcl/hclsyntax" "github.com/zclconf/go-cty/cty" ) @@ -25,6 +26,19 @@ func TokensForValue(val cty.Value) Tokens { return toks } +// TokensForTraversal returns a sequence of tokens that represents the given +// traversal. +// +// If the traversal is absolute then the result is a self-contained, valid +// reference expression. If the traversal is relative then the returned tokens +// could be appended to some other expression tokens to traverse into the +// represented expression. +func TokensForTraversal(traversal hcl.Traversal) Tokens { + toks := appendTokensForTraversal(traversal, nil) + format(toks) // fiddle with the SpacesBefore field to get canonical spacing + return toks +} + func appendTokensForValue(val cty.Value, toks Tokens) Tokens { switch { @@ -143,6 +157,47 @@ func appendTokensForValue(val cty.Value, toks Tokens) Tokens { return toks } +func appendTokensForTraversal(traversal hcl.Traversal, toks Tokens) Tokens { + for _, step := range traversal { + appendTokensForTraversalStep(step, toks) + } + return toks +} + +func appendTokensForTraversalStep(step hcl.Traverser, toks Tokens) { + switch ts := step.(type) { + case hcl.TraverseRoot: + toks = append(toks, &Token{ + Type: hclsyntax.TokenIdent, + Bytes: []byte(ts.Name), + }) + case hcl.TraverseAttr: + toks = append( + toks, + &Token{ + Type: hclsyntax.TokenDot, + Bytes: []byte{'.'}, + }, + &Token{ + Type: hclsyntax.TokenIdent, + Bytes: []byte(ts.Name), + }, + ) + case hcl.TraverseIndex: + toks = append(toks, &Token{ + Type: hclsyntax.TokenOBrack, + Bytes: []byte{'['}, + }) + appendTokensForValue(ts.Key, toks) + toks = append(toks, &Token{ + Type: hclsyntax.TokenCBrack, + Bytes: []byte{']'}, + }) + default: + panic(fmt.Sprintf("unsupported traversal step type %T", step)) + } +} + func escapeQuotedStringLit(s string) []byte { if len(s) == 0 { return nil diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/node.go b/vendor/github.com/hashicorp/hcl2/hclwrite/node.go index 674b830d23..71fd00faf6 100644 --- a/vendor/github.com/hashicorp/hcl2/hclwrite/node.go +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/node.go @@ -104,6 +104,11 @@ func (ns *nodes) BuildTokens(to Tokens) Tokens { return to } +func (ns *nodes) Clear() { + ns.first = nil + ns.last = nil +} + func (ns *nodes) Append(c nodeContent) *node { n := &node{ content: c, diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/parser.go b/vendor/github.com/hashicorp/hcl2/hclwrite/parser.go index d83d3e55d2..1876818fd8 100644 --- a/vendor/github.com/hashicorp/hcl2/hclwrite/parser.go +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/parser.go @@ -372,6 +372,7 @@ func parseTraversal(nativeTraversal hcl.Traversal, from inputTokens) (before inp before, step, after := parseTraversalStep(nativeStep, stepAfter) children.AppendUnstructuredTokens(before.Tokens()) children.AppendNode(step) + traversal.steps.Add(step) stepAfter = after } diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/tokens.go b/vendor/github.com/hashicorp/hcl2/hclwrite/tokens.go index 0b2034a1ba..d37b1c6f5f 100644 --- a/vendor/github.com/hashicorp/hcl2/hclwrite/tokens.go +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/tokens.go @@ -51,7 +51,7 @@ func (ts Tokens) Columns() int { // WriteTo takes an io.Writer and writes the bytes for each token to it, // along with the spacing that separates each token. In other words, this // allows serializing the tokens to a file or other such byte stream. -func (ts Tokens) WriteTo(wr io.Writer) (int, error) { +func (ts Tokens) WriteTo(wr io.Writer) (int64, error) { // We know we're going to be writing a lot of small chunks of repeated // space characters, so we'll prepare a buffer of these that we can // easily pass to wr.Write without any further allocation. @@ -60,7 +60,7 @@ func (ts Tokens) WriteTo(wr io.Writer) (int, error) { spaces[i] = ' ' } - var n int + var n int64 var err error for _, token := range ts { if err != nil { @@ -74,7 +74,7 @@ func (ts Tokens) WriteTo(wr io.Writer) (int, error) { } var thisN int thisN, err = wr.Write(spaces[:thisChunk]) - n += thisN + n += int64(thisN) if err != nil { return n, err } @@ -82,7 +82,7 @@ func (ts Tokens) WriteTo(wr io.Writer) (int, error) { var thisN int thisN, err = wr.Write(token.Bytes) - n += thisN + n += int64(thisN) } return n, err diff --git a/vendor/modules.txt b/vendor/modules.txt index c735e80d2e..befd14d357 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -343,7 +343,7 @@ github.com/hashicorp/hcl/hcl/scanner github.com/hashicorp/hcl/hcl/strconv github.com/hashicorp/hcl/json/scanner github.com/hashicorp/hcl/json/token -# github.com/hashicorp/hcl2 v0.0.0-20180925175540-3f1c5474d4f7 +# github.com/hashicorp/hcl2 v0.0.0-20181126233546-67424e43b184 github.com/hashicorp/hcl2/hcl github.com/hashicorp/hcl2/hcl/hclsyntax github.com/hashicorp/hcl2/hcldec