package hclwrite import ( "github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/hcl2/hcl/hclsyntax" "github.com/zclconf/go-cty/cty" ) type Body struct { inTree items nodeSet } func (b *Body) appendItem(c nodeContent) *node { nn := b.children.Append(c) b.items.Add(nn) return nn } func (b *Body) appendItemNode(nn *node) *node { nn.assertUnattached() b.children.AppendNode(nn) b.items.Add(nn) return nn } func (b *Body) AppendUnstructuredTokens(ts Tokens) { b.inTree.children.Append(ts) } // 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 { for n := range b.items { if attr, isAttr := n.content.(*Attribute); isAttr { nameObj := attr.name.content.(*identifier) if nameObj.hasName(name) { // We've found it! return attr } } } return nil } // SetAttributeValue either replaces the expression of an existing attribute // of the given name or adds a new attribute definition to the end of the block. // // The value is given as a cty.Value, and must therefore be a literal. To set // a variable reference or other traversal, use SetAttributeTraversal. // // The return value is the attribute that was either modified in-place or // created. func (b *Body) SetAttributeValue(name string, val cty.Value) *Attribute { attr := b.GetAttribute(name) expr := NewExpressionLiteral(val) if attr != nil { attr.expr = attr.expr.ReplaceWith(expr) } else { attr := newAttribute() attr.init(name, expr) b.appendItem(attr) } return attr } // 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. // // The new expression is given as a hcl.Traversal, which must be an absolute // traversal. To set a literal value, use SetAttributeValue. // // 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(), } } 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) } type Block struct { inTree leadComments *node typeName *node labels nodeSet open *node body *node close *node }