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+
17private import codeql.Locations
28private import codeql.files.FileSystem
39private import codeql.iac.ast.internal.Hcl
410private import codeql.hcl.ast.Literals
511private import codeql.hcl.ast.Variables
612
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+ */
827class HclAstNode extends THclAstNode {
928 string toString ( ) { result = this .getAPrimaryQlClass ( ) }
1029
@@ -36,51 +55,111 @@ class HclAstNode extends THclAstNode {
3655
3756 /**
3857 * Gets the parent in the AST for this node.
58+ *
59+ * Returns the parent AST node that contains this node as a child.
3960 */
4061 cached
4162 HclAstNode getParent ( ) { result .getAChild ( _) = this }
4263
4364 /**
4465 * Gets a child of this node, which can also be retrieved using a predicate
4566 * named `pred`.
67+ *
68+ * For example, for a binary operation, this might return the left and right operands
69+ * with predicates "getLeftOperand" and "getRightOperand".
4670 */
4771 cached
4872 HclAstNode getAChild ( string pred ) { none ( ) }
4973
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+ */
5179 HclAstNode getAChild ( ) { result = this .getAChild ( _) }
5280
5381 /**
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.
5585 */
5686 string getAPrimaryQlClass ( ) { result = "???" }
5787}
5888
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+ */
59103class Comment extends HclAstNode , TComment {
60104 private HCL:: Comment comment ;
61105
62106 override string getAPrimaryQlClass ( ) { result = "Comment" }
63107
64108 Comment ( ) { this = TComment ( comment ) }
65109
110+ /** Gets the textual contents of the comment. */
66111 string getContents ( ) { result = comment .getValue ( ) }
67112}
68113
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+ */
69130class Expr extends HclAstNode , TExpr {
70131 override string getAPrimaryQlClass ( ) { result = "Expr" }
71132}
72133
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+ */
73149class BinaryOperation extends Expr {
74150 HCL:: BinaryOperation binaryOp ;
75151
76152 override string getAPrimaryQlClass ( ) { result = "BinaryOperation" }
77153
78154 BinaryOperation ( ) { this = TBinaryOperation ( binaryOp ) }
79155
156+ /** Gets the left operand of the binary operation. */
80157 Expr getLeftOperand ( ) { toHclTreeSitter ( result ) = binaryOp .getLeft ( ) }
81158
159+ /** Gets the right operand of the binary operation. */
82160 Expr getRightOperand ( ) { toHclTreeSitter ( result ) = binaryOp .getRight ( ) }
83161
162+ /** Gets the operator string (e.g., "+", "&&", "=="). */
84163 string getOperator ( ) { result = binaryOp .getOperator ( ) }
85164
86165 override string toString ( ) {
@@ -94,27 +173,70 @@ class BinaryOperation extends Expr {
94173 }
95174}
96175
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+ */
97194class Identifier extends Expr , TIdentifier {
98195 private HCL:: Identifier identifier ;
99196
100197 override string getAPrimaryQlClass ( ) { result = "Identifier" }
101198
102199 Identifier ( ) { this = TIdentifier ( identifier ) }
103200
201+ /** Gets the name of the identifier. */
104202 string getName ( ) { result = identifier .getValue ( ) }
105203}
106204
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+ */
107222class Object extends Expr , TObject {
108223 private HCL:: Object object ;
109224
110225 override string getAPrimaryQlClass ( ) { result = "Object" }
111226
112227 Object ( ) { this = TObject ( object ) }
113228
229+ /** Gets the object element at the specified index. */
114230 ObjectElement getElement ( int index ) { toHclTreeSitter ( result ) = object .getElement ( index ) }
115231
232+ /** Gets any object element in this object. */
116233 ObjectElement getElements ( ) { toHclTreeSitter ( result ) = object .getElement ( _) }
117234
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+ */
118240 Expr getElementByName ( string name ) {
119241 exists ( ObjectElement elem | this .getElements ( ) = elem |
120242 (
@@ -129,28 +251,77 @@ class Object extends Expr, TObject {
129251 }
130252}
131253
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+ */
132269class ObjectElement extends Expr , TObjectElem {
133270 private HCL:: ObjectElem objectElem ;
134271
135272 override string getAPrimaryQlClass ( ) { result = "ObjectElement" }
136273
137274 ObjectElement ( ) { this = TObjectElem ( objectElem ) }
138275
276+ /** Gets the key expression of this object element. */
139277 Expr getKey ( ) { toHclTreeSitter ( result ) = objectElem .getKey ( ) }
140278
279+ /** Gets the value expression of this object element. */
141280 Expr getExpr ( ) { toHclTreeSitter ( result ) = objectElem .getVal ( ) }
142281}
143282
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+ */
144298class Tuple extends Expr , TTuple {
145299 private HCL:: Tuple tuple ;
146300
147301 override string getAPrimaryQlClass ( ) { result = "Tuple" }
148302
149303 Tuple ( ) { this = TTuple ( tuple ) }
150304
305+ /** Gets the element at the specified index in the tuple. */
151306 Expr getElement ( int i ) { toHclTreeSitter ( result ) = tuple .getElement ( i ) }
152307}
153308
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+ */
154325class HereDoc extends Expr , THeredocTemplate {
155326 private HCL:: HeredocTemplate hereDoc ;
156327
0 commit comments