diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hclwrite/ast_body.go')
-rw-r--r-- | vendor/github.com/hashicorp/hcl2/hclwrite/ast_body.go | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hclwrite/ast_body.go b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_body.go new file mode 100644 index 0000000..cf69fee --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/hclwrite/ast_body.go | |||
@@ -0,0 +1,153 @@ | |||
1 | package hclwrite | ||
2 | |||
3 | import ( | ||
4 | "github.com/hashicorp/hcl2/hcl" | ||
5 | "github.com/hashicorp/hcl2/hcl/hclsyntax" | ||
6 | "github.com/zclconf/go-cty/cty" | ||
7 | ) | ||
8 | |||
9 | type Body struct { | ||
10 | inTree | ||
11 | |||
12 | items nodeSet | ||
13 | } | ||
14 | |||
15 | func newBody() *Body { | ||
16 | return &Body{ | ||
17 | inTree: newInTree(), | ||
18 | items: newNodeSet(), | ||
19 | } | ||
20 | } | ||
21 | |||
22 | func (b *Body) appendItem(c nodeContent) *node { | ||
23 | nn := b.children.Append(c) | ||
24 | b.items.Add(nn) | ||
25 | return nn | ||
26 | } | ||
27 | |||
28 | func (b *Body) appendItemNode(nn *node) *node { | ||
29 | nn.assertUnattached() | ||
30 | b.children.AppendNode(nn) | ||
31 | b.items.Add(nn) | ||
32 | return nn | ||
33 | } | ||
34 | |||
35 | // Clear removes all of the items from the body, making it empty. | ||
36 | func (b *Body) Clear() { | ||
37 | b.children.Clear() | ||
38 | } | ||
39 | |||
40 | func (b *Body) AppendUnstructuredTokens(ts Tokens) { | ||
41 | b.inTree.children.Append(ts) | ||
42 | } | ||
43 | |||
44 | // Attributes returns a new map of all of the attributes in the body, with | ||
45 | // the attribute names as the keys. | ||
46 | func (b *Body) Attributes() map[string]*Attribute { | ||
47 | ret := make(map[string]*Attribute) | ||
48 | for n := range b.items { | ||
49 | if attr, isAttr := n.content.(*Attribute); isAttr { | ||
50 | nameObj := attr.name.content.(*identifier) | ||
51 | name := string(nameObj.token.Bytes) | ||
52 | ret[name] = attr | ||
53 | } | ||
54 | } | ||
55 | return ret | ||
56 | } | ||
57 | |||
58 | // Blocks returns a new slice of all the blocks in the body. | ||
59 | func (b *Body) Blocks() []*Block { | ||
60 | ret := make([]*Block, 0, len(b.items)) | ||
61 | for n := range b.items { | ||
62 | if block, isBlock := n.content.(*Block); isBlock { | ||
63 | ret = append(ret, block) | ||
64 | } | ||
65 | } | ||
66 | return ret | ||
67 | } | ||
68 | |||
69 | // GetAttribute returns the attribute from the body that has the given name, | ||
70 | // or returns nil if there is currently no matching attribute. | ||
71 | func (b *Body) GetAttribute(name string) *Attribute { | ||
72 | for n := range b.items { | ||
73 | if attr, isAttr := n.content.(*Attribute); isAttr { | ||
74 | nameObj := attr.name.content.(*identifier) | ||
75 | if nameObj.hasName(name) { | ||
76 | // We've found it! | ||
77 | return attr | ||
78 | } | ||
79 | } | ||
80 | } | ||
81 | |||
82 | return nil | ||
83 | } | ||
84 | |||
85 | // SetAttributeValue either replaces the expression of an existing attribute | ||
86 | // of the given name or adds a new attribute definition to the end of the block. | ||
87 | // | ||
88 | // The value is given as a cty.Value, and must therefore be a literal. To set | ||
89 | // a variable reference or other traversal, use SetAttributeTraversal. | ||
90 | // | ||
91 | // The return value is the attribute that was either modified in-place or | ||
92 | // created. | ||
93 | func (b *Body) SetAttributeValue(name string, val cty.Value) *Attribute { | ||
94 | attr := b.GetAttribute(name) | ||
95 | expr := NewExpressionLiteral(val) | ||
96 | if attr != nil { | ||
97 | attr.expr = attr.expr.ReplaceWith(expr) | ||
98 | } else { | ||
99 | attr := newAttribute() | ||
100 | attr.init(name, expr) | ||
101 | b.appendItem(attr) | ||
102 | } | ||
103 | return attr | ||
104 | } | ||
105 | |||
106 | // SetAttributeTraversal either replaces the expression of an existing attribute | ||
107 | // of the given name or adds a new attribute definition to the end of the body. | ||
108 | // | ||
109 | // The new expression is given as a hcl.Traversal, which must be an absolute | ||
110 | // traversal. To set a literal value, use SetAttributeValue. | ||
111 | // | ||
112 | // The return value is the attribute that was either modified in-place or | ||
113 | // created. | ||
114 | func (b *Body) SetAttributeTraversal(name string, traversal hcl.Traversal) *Attribute { | ||
115 | attr := b.GetAttribute(name) | ||
116 | expr := NewExpressionAbsTraversal(traversal) | ||
117 | if attr != nil { | ||
118 | attr.expr = attr.expr.ReplaceWith(expr) | ||
119 | } else { | ||
120 | attr := newAttribute() | ||
121 | attr.init(name, expr) | ||
122 | b.appendItem(attr) | ||
123 | } | ||
124 | return attr | ||
125 | } | ||
126 | |||
127 | // AppendBlock appends an existing block (which must not be already attached | ||
128 | // to a body) to the end of the receiving body. | ||
129 | func (b *Body) AppendBlock(block *Block) *Block { | ||
130 | b.appendItem(block) | ||
131 | return block | ||
132 | } | ||
133 | |||
134 | // AppendNewBlock appends a new nested block to the end of the receiving body | ||
135 | // with the given type name and labels. | ||
136 | func (b *Body) AppendNewBlock(typeName string, labels []string) *Block { | ||
137 | block := newBlock() | ||
138 | block.init(typeName, labels) | ||
139 | b.appendItem(block) | ||
140 | return block | ||
141 | } | ||
142 | |||
143 | // AppendNewline appends a newline token to th end of the receiving body, | ||
144 | // which generally serves as a separator between different sets of body | ||
145 | // contents. | ||
146 | func (b *Body) AppendNewline() { | ||
147 | b.AppendUnstructuredTokens(Tokens{ | ||
148 | { | ||
149 | Type: hclsyntax.TokenNewline, | ||
150 | Bytes: []byte{'\n'}, | ||
151 | }, | ||
152 | }) | ||
153 | } | ||