Skip to content

Commit a40c828

Browse files
authored
Merge pull request #42 from GitHubSecurityLab/docs-update
docs: Update and improve the AST docs
2 parents f6f8150 + 6b11459 commit a40c828

File tree

9 files changed

+943
-129
lines changed

9 files changed

+943
-129
lines changed

ql/lib/codeql/bicep/ast/AstNodes.qll

Lines changed: 93 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,58 @@ private import codeql.bicep.ast.internal.TreeSitter
66
private import codeql.bicep.controlflow.ControlFlowGraph
77

88
/**
9-
* An AST node of a Bicep program
9+
* An AST node of a Bicep program.
10+
*
11+
* This is the base class for all syntax nodes in the Bicep language. All
12+
* Bicep entities that have a representation in the abstract syntax tree
13+
* (such as expressions, statements, resources, parameters, etc.) extend this class.
1014
*/
1115
class AstNode extends TAstNode {
1216
private BICEP::AstNode node;
1317

1418
AstNode() { toTreeSitter(this) = node }
1519

20+
/**
21+
* Gets a string representation of this AST node.
22+
*
23+
* By default, returns the primary QL class name of this node.
24+
*/
1625
string toString() { result = this.getAPrimaryQlClass() }
1726

18-
/** Gets the location of the AST node. */
27+
/**
28+
* Gets the location of the AST node.
29+
*
30+
* The location includes information about the file, and the start and
31+
* end positions of the node in the file (line and column).
32+
*/
1933
cached
2034
Location getLocation() { result = this.getFullLocation() } // overridden in some subclasses
2135

22-
/** Gets the file containing this AST node. */
36+
/**
37+
* Gets the file containing this AST node.
38+
*
39+
* This is the source file where this AST node is defined.
40+
*/
2341
cached
2442
File getFile() { result = this.getFullLocation().getFile() }
2543

26-
/** Gets the location that spans the entire AST node. */
44+
/**
45+
* Gets the location that spans the entire AST node.
46+
*
47+
* This includes the full text range covered by this node and all its children.
48+
*/
2749
cached
2850
final Location getFullLocation() { result = toTreeSitter(this).getLocation() }
2951

52+
/**
53+
* Holds if this AST node has the specified location information.
54+
*
55+
* @param filepath The file path
56+
* @param startline The start line
57+
* @param startcolumn The start column
58+
* @param endline The end line
59+
* @param endcolumn The end column
60+
*/
3061
predicate hasLocationInfo(
3162
string filepath, int startline, int startcolumn, int endline, int endcolumn
3263
) {
@@ -43,18 +74,29 @@ class AstNode extends TAstNode {
4374

4475
/**
4576
* Gets the parent in the AST for this node.
77+
*
78+
* This is the immediately enclosing syntax node in the AST.
79+
* For example, the parent of an expression might be a statement that contains it.
4680
*/
4781
cached
4882
AstNode getParent() { result.getAChild() = this }
4983

5084
/**
51-
* Gets a child of this node, which can also be retrieved using a predicate
52-
* named `pred`.
85+
* Gets a child of this node.
86+
*
87+
* This returns any direct child node in the AST hierarchy.
88+
* The exact set of child nodes depends on the specific type of AST node.
5389
*/
5490
cached
5591
AstNode getAChild() { toTreeSitter(result) = node.getAFieldOrChild() }
5692

57-
/** Gets the CFG scope that encloses this node, if any. */
93+
/**
94+
* Gets the CFG scope that encloses this node, if any.
95+
*
96+
* A CFG scope is a region of code that has its own control flow graph.
97+
* This can include the entire file, functions, or other code blocks with
98+
* independent control flow.
99+
*/
58100
cached
59101
CfgScope getEnclosingCfgScope() {
60102
exists(AstNode p | p = this.getParent*() |
@@ -66,19 +108,36 @@ class AstNode extends TAstNode {
66108
}
67109

68110
/**
69-
* Gets the primary QL class for the ast node.
111+
* Gets the primary QL class for the AST node.
112+
*
113+
* This returns the name of the most specific QL class that describes this node.
114+
* Used primarily for debugging and toString() representations.
70115
*/
71116
string getAPrimaryQlClass() { result = "???" }
72117
}
73118

74-
/** A Bicep file */
119+
/**
120+
* A Bicep file.
121+
*
122+
* Represents a source file written in the Bicep language. This class provides
123+
* access to file metadata and metrics such as the total number of lines and
124+
* lines of code.
125+
*/
75126
class BicepFile extends File {
76127
BicepFile() { exists(Location loc | bicep_ast_node_location(_, loc) and this = loc.getFile()) }
77128

78-
/** Gets a token in this file. */
129+
/**
130+
* Gets a token in this file.
131+
*
132+
* A token is a basic syntactic unit recognized by the lexer.
133+
*/
79134
private BICEP::Token getAToken() { result.getLocation().getFile() = this }
80135

81-
/** Holds if `line` contains a token. */
136+
/**
137+
* Holds if `line` contains a token.
138+
*
139+
* This is used to calculate metrics like the number of lines of code.
140+
*/
82141
private predicate line(int line) {
83142
exists(BICEP::Token token, Location l |
84143
token = this.getAToken() and
@@ -87,15 +146,28 @@ class BicepFile extends File {
87146
)
88147
}
89148

90-
/** Gets the number of lines in this file. */
149+
/**
150+
* Gets the number of lines in this file.
151+
*
152+
* This counts the total number of lines in the file, including empty lines
153+
* and comment lines.
154+
*/
91155
int getNumberOfLines() { result = max([0, this.getAToken().getLocation().getEndLine()]) }
92156

93-
/** Gets the number of lines of code in this file. */
157+
/**
158+
* Gets the number of lines of code in this file.
159+
*
160+
* This counts only lines that contain at least one token, which excludes
161+
* completely empty lines.
162+
*/
94163
int getNumberOfLinesOfCode() { result = count(int line | this.line(line)) }
95164
}
96165

97166
/**
98-
* A comment in a Bicep program
167+
* A comment in a Bicep program.
168+
*
169+
* Represents a single- or multi-line comment in Bicep source code.
170+
* Comments may be either single-line (// comment) or multi-line (/* comment *\/).
99171
*/
100172
class Comment extends AstNode, TComment {
101173
private BICEP::Comment comment;
@@ -105,9 +177,14 @@ class Comment extends AstNode, TComment {
105177
Comment() { this = TComment(comment) }
106178

107179
/**
108-
* Gets the text of the comment.
180+
* Gets the text content of the comment.
181+
*
182+
* For a single-line comment, this is the text after the // delimiter.
183+
* For a multi-line comment, this is the text between the /* and *\/ delimiters.
109184
*
110-
* TODO: Implement this method
185+
* Note: This method is currently a placeholder and needs implementation.
186+
*
187+
* @return The text content of the comment (currently an empty string)
111188
*/
112189
string getContents() { result = "" }
113190
}

ql/lib/codeql/bicep/ast/Calls.qll

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,59 +7,112 @@ private import internal.CallExpression
77

88
/**
99
* Represents a callable expression in the AST, such as a function or method call.
10-
* Provides access to the identifier and name of the call expression.
10+
*
11+
* This abstract class serves as the base for any expression that represents
12+
* a call to a function or method. It provides common functionality for accessing
13+
* the name and identifier of the called entity.
1114
*/
1215
abstract class Callable extends Expr {
1316
/**
14-
* Gets the identifier of the call expression.
17+
* Gets the identifier of the callable expression.
18+
*
19+
* This is the name token that identifies what function or method is being called.
20+
*
21+
* @return The identifier node of the callable
1522
*/
1623
abstract Idents getIdentifier();
1724

1825
/**
19-
* Gets the name of the call expression.
26+
* Gets the name of the callable expression as a string.
27+
*
28+
* This is a convenience method that returns the name from the identifier.
2029
*
21-
* @return The name as a string.
30+
* @return The name of the callable
2231
*/
2332
string getName() { result = this.getIdentifier().getName() }
2433

2534
/**
26-
* Checks if the call expression has a specific name.
35+
* Checks if the callable expression has a specific name.
36+
*
37+
* This is useful for identifying calls to known functions by name.
2738
*
28-
* @param name The name to check against.
29-
* @return True if the call expression has the given name.
39+
* @param name The name to check against
40+
* @return True if the callable has the given name, false otherwise
3041
*/
3142
predicate hasName(string name) { this.getName() = name }
3243
}
3344

3445
/**
35-
* Represents a call expression node in the AST.
36-
* Provides access to the identifier, arguments, and declared arguments.
46+
* Represents a function or method call expression in the AST.
47+
*
48+
* This class models a function call in Bicep, consisting of an identifier
49+
* (the function name) followed by arguments in parentheses. Function calls
50+
* invoke functions defined in the language, user-defined functions, or
51+
* module functions to compute values or perform operations.
3752
*/
3853
class CallExpression extends Expr instanceof CallExpressionImpl {
39-
/** Gets the identifier of the call expression. */
54+
/**
55+
* Gets the identifier of the call expression.
56+
*
57+
* This is the name token that identifies what function is being called.
58+
*
59+
* @return The identifier node of the function being called
60+
*/
4061
Idents getIdentifier() { result = CallExpressionImpl.super.getIdentifier() }
4162

42-
/** Gets the name of the call expression. */
63+
/**
64+
* Gets the name of the call expression as a string.
65+
*
66+
* This is a convenience method that returns the name from the identifier.
67+
*
68+
* @return The name of the function being called
69+
*/
4370
string getName() { result = this.getIdentifier().getName() }
4471

45-
/** Gets the argument at the specified index. */
72+
/**
73+
* Gets the argument at the specified index.
74+
*
75+
* @param index The zero-based index of the argument to retrieve
76+
* @return The expression node of the argument at the specified index
77+
*/
4678
Expr getArgument(int index) { result = this.getDeclaredArguments().getArgument(index) }
4779

48-
/** Gets all arguments of the call expression. */
80+
/**
81+
* Gets all arguments of the call expression.
82+
*
83+
* @return All argument expressions passed to the function
84+
*/
4985
Expr getArguments() { result = this.getDeclaredArguments().getArguments() }
5086

51-
/** Gets the declared arguments node. */
87+
/**
88+
* Gets the arguments collection node of the call expression.
89+
*
90+
* This provides access to the AST node that contains all the arguments.
91+
*
92+
* @return The arguments node of the call expression
93+
*/
5294
Arguments getDeclaredArguments() { result = CallExpressionImpl.super.getArguments() }
5395
}
5496

5597
/**
56-
* Represents the arguments node in the AST.
57-
* Provides access to individual and all arguments.
98+
* Represents a collection of arguments in a function call.
99+
*
100+
* This class models the set of arguments passed to a function, allowing
101+
* access to individual arguments by index or to the complete set of arguments.
58102
*/
59103
class Arguments extends AstNode instanceof ArgumentsImpl {
60-
/** Gets the argument at the specified index. */
104+
/**
105+
* Gets the argument at the specified index.
106+
*
107+
* @param index The zero-based index of the argument to retrieve
108+
* @return The expression node of the argument at the specified index
109+
*/
61110
Expr getArgument(int index) { result = ArgumentsImpl.super.getArgument(index) }
62111

63-
/** Gets all arguments. */
112+
/**
113+
* Gets all arguments in the collection.
114+
*
115+
* @return All argument expressions in this arguments collection
116+
*/
64117
Expr getArguments() { result = ArgumentsImpl.super.getArguments() }
65118
}

0 commit comments

Comments
 (0)