2018-08-01 15:45:22 +00:00
|
|
|
package hclwrite
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/hashicorp/hcl2/hcl"
|
2018-08-09 15:44:48 +00:00
|
|
|
"github.com/hashicorp/hcl2/hcl/hclsyntax"
|
2018-08-01 15:45:22 +00:00
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Body struct {
|
|
|
|
inTree
|
|
|
|
|
|
|
|
items nodeSet
|
|
|
|
}
|
|
|
|
|
2018-08-09 15:44:48 +00:00
|
|
|
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
|
2018-08-01 15:45:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2018-08-09 15:44:48 +00:00
|
|
|
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
|
2018-08-01 15:45:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2018-08-09 15:44:48 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2018-08-01 15:45:22 +00:00
|
|
|
type Block struct {
|
|
|
|
inTree
|
|
|
|
|
|
|
|
leadComments *node
|
|
|
|
typeName *node
|
|
|
|
labels nodeSet
|
|
|
|
open *node
|
|
|
|
body *node
|
|
|
|
close *node
|
|
|
|
}
|