1
+ /**
2
+ * Base classes and core AST node implementations for HCL (HashiCorp Configuration Language).
3
+ * This module defines the fundamental AST node types including expressions, identifiers, objects,
4
+ * binary operations, and other core language constructs.
5
+ */
6
+
1
7
private import codeql.Locations
2
8
private import codeql.files.FileSystem
3
9
private import codeql.iac.ast.internal.Hcl
4
10
private import codeql.hcl.ast.Literals
5
11
private import codeql.hcl.ast.Variables
6
12
7
- /** An AST node of a IAC program */
13
+ /**
14
+ * An AST node of an HCL program.
15
+ *
16
+ * HCL AST nodes represent the structure of HashiCorp Configuration Language code,
17
+ * including all expressions, statements, blocks, and other language constructs.
18
+ *
19
+ * Example HCL code:
20
+ * ```hcl
21
+ * resource "aws_instance" "example" {
22
+ * ami = "ami-12345678"
23
+ * instance_type = "t2.micro"
24
+ * }
25
+ * ```
26
+ */
8
27
class HclAstNode extends THclAstNode {
9
28
string toString ( ) { result = this .getAPrimaryQlClass ( ) }
10
29
@@ -36,51 +55,111 @@ class HclAstNode extends THclAstNode {
36
55
37
56
/**
38
57
* Gets the parent in the AST for this node.
58
+ *
59
+ * Returns the parent AST node that contains this node as a child.
39
60
*/
40
61
cached
41
62
HclAstNode getParent ( ) { result .getAChild ( _) = this }
42
63
43
64
/**
44
65
* Gets a child of this node, which can also be retrieved using a predicate
45
66
* named `pred`.
67
+ *
68
+ * For example, for a binary operation, this might return the left and right operands
69
+ * with predicates "getLeftOperand" and "getRightOperand".
46
70
*/
47
71
cached
48
72
HclAstNode getAChild ( string pred ) { none ( ) }
49
73
50
- /** Gets any child of this node. */
74
+ /**
75
+ * Gets any child of this node.
76
+ *
77
+ * This is a convenience predicate that returns all children regardless of their predicate name.
78
+ */
51
79
HclAstNode getAChild ( ) { result = this .getAChild ( _) }
52
80
53
81
/**
54
- * Gets the primary QL class for the ast node.
82
+ * Gets the primary QL class for the AST node.
83
+ *
84
+ * This is used for identification and debugging purposes.
55
85
*/
56
86
string getAPrimaryQlClass ( ) { result = "???" }
57
87
}
58
88
89
+ /**
90
+ * A comment in HCL code.
91
+ *
92
+ * Comments are used for documentation and annotations in HCL files.
93
+ * They can be single-line or multi-line comments.
94
+ *
95
+ * Example HCL code:
96
+ * ```
97
+ * // This is a single-line comment
98
+ * resource "aws_instance" "example" {
99
+ * ami = "ami-12345678"
100
+ * }
101
+ * ```
102
+ */
59
103
class Comment extends HclAstNode , TComment {
60
104
private HCL:: Comment comment ;
61
105
62
106
override string getAPrimaryQlClass ( ) { result = "Comment" }
63
107
64
108
Comment ( ) { this = TComment ( comment ) }
65
109
110
+ /** Gets the textual contents of the comment. */
66
111
string getContents ( ) { result = comment .getValue ( ) }
67
112
}
68
113
114
+ /**
115
+ * An expression in HCL code.
116
+ *
117
+ * Expressions represent values and computations in HCL, including literals,
118
+ * variables, function calls, binary operations, and complex data structures.
119
+ *
120
+ * Example HCL expressions:
121
+ * ```
122
+ * resource "aws_instance" "example" {
123
+ * ami = "ami-12345678" // String literal expression
124
+ * instance_type = var.instance_type // Variable expression
125
+ * count = length(var.subnets) // Function call expression
126
+ * enabled = true && var.enabled // Binary operation expression
127
+ * }
128
+ * ```
129
+ */
69
130
class Expr extends HclAstNode , TExpr {
70
131
override string getAPrimaryQlClass ( ) { result = "Expr" }
71
132
}
72
133
134
+ /**
135
+ * A binary operation expression in HCL.
136
+ *
137
+ * Binary operations combine two expressions with an operator such as +, -, *, /,
138
+ * ==, !=, &&, ||, etc.
139
+ *
140
+ * Example HCL binary operations:
141
+ * ```
142
+ * locals {
143
+ * sum = var.a + var.b // Addition
144
+ * enabled = var.debug && true // Logical AND
145
+ * equal = var.env == "prod" // Equality comparison
146
+ * }
147
+ * ```
148
+ */
73
149
class BinaryOperation extends Expr {
74
150
HCL:: BinaryOperation binaryOp ;
75
151
76
152
override string getAPrimaryQlClass ( ) { result = "BinaryOperation" }
77
153
78
154
BinaryOperation ( ) { this = TBinaryOperation ( binaryOp ) }
79
155
156
+ /** Gets the left operand of the binary operation. */
80
157
Expr getLeftOperand ( ) { toHclTreeSitter ( result ) = binaryOp .getLeft ( ) }
81
158
159
+ /** Gets the right operand of the binary operation. */
82
160
Expr getRightOperand ( ) { toHclTreeSitter ( result ) = binaryOp .getRight ( ) }
83
161
162
+ /** Gets the operator string (e.g., "+", "&&", "=="). */
84
163
string getOperator ( ) { result = binaryOp .getOperator ( ) }
85
164
86
165
override string toString ( ) {
@@ -94,27 +173,70 @@ class BinaryOperation extends Expr {
94
173
}
95
174
}
96
175
176
+ /**
177
+ * An identifier in HCL code.
178
+ *
179
+ * Identifiers represent names of variables, attributes, functions, and other named entities.
180
+ * They must follow HCL naming conventions (alphanumeric characters and underscores).
181
+ *
182
+ * Example HCL identifiers:
183
+ * ```
184
+ * resource "aws_instance" "web_server" {
185
+ * ami = var.instance_ami // 'ami', 'var', 'instance_ami' are identifiers
186
+ * instance_type = "t2.micro"
187
+ * tags = {
188
+ * Name = "WebServer" // 'Name' is an identifier
189
+ * Environment = var.environment // 'Environment', 'environment' are identifiers
190
+ * }
191
+ * }
192
+ * ```
193
+ */
97
194
class Identifier extends Expr , TIdentifier {
98
195
private HCL:: Identifier identifier ;
99
196
100
197
override string getAPrimaryQlClass ( ) { result = "Identifier" }
101
198
102
199
Identifier ( ) { this = TIdentifier ( identifier ) }
103
200
201
+ /** Gets the name of the identifier. */
104
202
string getName ( ) { result = identifier .getValue ( ) }
105
203
}
106
204
205
+ /**
206
+ * An object expression in HCL.
207
+ *
208
+ * Objects are collections of key-value pairs enclosed in curly braces.
209
+ * They represent structured data similar to maps or dictionaries in other languages.
210
+ *
211
+ * Example HCL objects:
212
+ * ```
213
+ * resource "aws_instance" "example" {
214
+ * tags = { // This is an object
215
+ * Name = "WebServer"
216
+ * Environment = "production"
217
+ * Owner = var.team_name
218
+ * }
219
+ * }
220
+ * ```
221
+ */
107
222
class Object extends Expr , TObject {
108
223
private HCL:: Object object ;
109
224
110
225
override string getAPrimaryQlClass ( ) { result = "Object" }
111
226
112
227
Object ( ) { this = TObject ( object ) }
113
228
229
+ /** Gets the object element at the specified index. */
114
230
ObjectElement getElement ( int index ) { toHclTreeSitter ( result ) = object .getElement ( index ) }
115
231
232
+ /** Gets any object element in this object. */
116
233
ObjectElement getElements ( ) { toHclTreeSitter ( result ) = object .getElement ( _) }
117
234
235
+ /**
236
+ * Gets the value expression for an element with the specified key name.
237
+ *
238
+ * This predicate handles both identifier keys and string literal keys.
239
+ */
118
240
Expr getElementByName ( string name ) {
119
241
exists ( ObjectElement elem | this .getElements ( ) = elem |
120
242
(
@@ -129,28 +251,77 @@ class Object extends Expr, TObject {
129
251
}
130
252
}
131
253
254
+ /**
255
+ * An object element (key-value pair) in HCL.
256
+ *
257
+ * Object elements represent individual key-value pairs within an object.
258
+ * The key can be an identifier, string literal, or expression, and the value
259
+ * can be any valid HCL expression.
260
+ *
261
+ * Example HCL object elements:
262
+ * ```
263
+ * tags = {
264
+ * Name = "WebServer" // ObjectElement with identifier key
265
+ * "Team-Name" = var.team // ObjectElement with string literal key
266
+ * }
267
+ * ```
268
+ */
132
269
class ObjectElement extends Expr , TObjectElem {
133
270
private HCL:: ObjectElem objectElem ;
134
271
135
272
override string getAPrimaryQlClass ( ) { result = "ObjectElement" }
136
273
137
274
ObjectElement ( ) { this = TObjectElem ( objectElem ) }
138
275
276
+ /** Gets the key expression of this object element. */
139
277
Expr getKey ( ) { toHclTreeSitter ( result ) = objectElem .getKey ( ) }
140
278
279
+ /** Gets the value expression of this object element. */
141
280
Expr getExpr ( ) { toHclTreeSitter ( result ) = objectElem .getVal ( ) }
142
281
}
143
282
283
+ /**
284
+ * A tuple expression in HCL.
285
+ *
286
+ * Tuples are ordered collections of expressions enclosed in square brackets.
287
+ * They represent lists or arrays of values.
288
+ *
289
+ * Example HCL tuples:
290
+ * ```
291
+ * resource "aws_security_group" "example" {
292
+ * ingress {
293
+ * cidr_blocks = ["10.0.0.0/8", "172.16.0.0/12"] // This is a tuple
294
+ * }
295
+ * }
296
+ * ```
297
+ */
144
298
class Tuple extends Expr , TTuple {
145
299
private HCL:: Tuple tuple ;
146
300
147
301
override string getAPrimaryQlClass ( ) { result = "Tuple" }
148
302
149
303
Tuple ( ) { this = TTuple ( tuple ) }
150
304
305
+ /** Gets the element at the specified index in the tuple. */
151
306
Expr getElement ( int i ) { toHclTreeSitter ( result ) = tuple .getElement ( i ) }
152
307
}
153
308
309
+ /**
310
+ * A heredoc template expression in HCL.
311
+ *
312
+ * Heredocs allow multi-line string literals with embedded expressions.
313
+ * They are useful for defining large text blocks or templates.
314
+ *
315
+ * Example HCL heredoc:
316
+ * ```
317
+ * resource "aws_instance" "example" {
318
+ * user_data = <<-EOF
319
+ * #!/bin/bash
320
+ * echo "Hello, ${var.name}!"
321
+ * EOF
322
+ * }
323
+ * ```
324
+ */
154
325
class HereDoc extends Expr , THeredocTemplate {
155
326
private HCL:: HeredocTemplate hereDoc ;
156
327
0 commit comments