mirror of
https://github.com/github/codeql.git
synced 2026-08-03 00:43:00 +02:00
271 lines
8.1 KiB
Plaintext
271 lines
8.1 KiB
Plaintext
/**
|
|
* Provides classes for working with AST nodes.
|
|
*/
|
|
overlay[local]
|
|
module;
|
|
|
|
import go
|
|
|
|
/**
|
|
* An AST node.
|
|
*/
|
|
class AstNode extends @node, Locatable {
|
|
/**
|
|
* Gets the `i`th child node of this node.
|
|
*
|
|
* Note that the precise indices of child nodes are considered an implementation detail
|
|
* and are subject to change without notice.
|
|
*/
|
|
AstNode getChild(int i) {
|
|
result = this.(ExprParent).getChildExpr(i) or
|
|
result = this.(GoModExprParent).getChildGoModExpr(i) or
|
|
result = this.(StmtParent).getChildStmt(i) or
|
|
result = this.(DeclParent).getDecl(i) or
|
|
result = this.(GenDecl).getSpec(i) or
|
|
result = this.(FieldParent).getField(i) or
|
|
result = this.(File).getCommentGroup(i) or
|
|
result = this.(CommentGroup).getComment(i)
|
|
}
|
|
|
|
/**
|
|
* Gets a child node of this node.
|
|
*/
|
|
AstNode getAChild() { result = this.getChild(_) }
|
|
|
|
/**
|
|
* Gets the number of child nodes of this node.
|
|
*/
|
|
int getNumChild() { result = count(this.getAChild()) }
|
|
|
|
/**
|
|
* Gets a child with the given index and of the given kind, if one exists.
|
|
* Note that a given parent can have multiple children with the same index but differing kind.
|
|
*/
|
|
private AstNode getChildOfKind(string kind, int i) {
|
|
kind = "expr" and result = this.(ExprParent).getChildExpr(i)
|
|
or
|
|
kind = "gomodexpr" and result = this.(GoModExprParent).getChildGoModExpr(i)
|
|
or
|
|
kind = "stmt" and result = this.(StmtParent).getChildStmt(i)
|
|
or
|
|
kind = "decl" and result = this.(DeclParent).getDecl(i)
|
|
or
|
|
kind = "spec" and result = this.(GenDecl).getSpec(i)
|
|
or
|
|
kind = "field" and result = this.(FieldParent).getField(i)
|
|
or
|
|
kind = "commentgroup" and result = this.(File).getCommentGroup(i)
|
|
or
|
|
kind = "comment" and result = this.(CommentGroup).getComment(i)
|
|
or
|
|
kind = "typeparamdecl" and result = this.(TypeParamDeclParent).getTypeParameterDecl(i)
|
|
}
|
|
|
|
/**
|
|
* Get an AstNode child, ordered by child kind and then by index.
|
|
*/
|
|
AstNode getUniquelyNumberedChild(int index) {
|
|
result =
|
|
rank[index + 1](AstNode child, string kind, int i |
|
|
child = this.getChildOfKind(kind, i)
|
|
|
|
|
child order by kind, i
|
|
)
|
|
}
|
|
|
|
/** Gets the parent node of this AST node, if any. */
|
|
AstNode getParent() { this = result.getAChild() }
|
|
|
|
/** Gets the parent node of this AST node, but without crossing function boundaries. */
|
|
private AstNode parentInSameFunction() {
|
|
result = this.getParent() and
|
|
not this instanceof FuncDef
|
|
}
|
|
|
|
/** Gets the innermost function definition to which this AST node belongs, if any. */
|
|
pragma[nomagic]
|
|
FuncDef getEnclosingFunction() { result = this.getParent().parentInSameFunction*() }
|
|
|
|
/** Gets the innermost block statement to which this AST node belongs, if any. */
|
|
BlockStmt getEnclosingBlock() {
|
|
exists(AstNode p | p = this.getParent() |
|
|
result = p
|
|
or
|
|
not p instanceof BlockStmt and
|
|
result = p.getEnclosingBlock()
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
|
|
*/
|
|
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
|
|
|
|
/**
|
|
* Gets the name of a primary CodeQL class to which this node belongs.
|
|
*
|
|
* For most nodes, this is simply the most precise syntactic category to which they belong;
|
|
* for example, `AddExpr` is a primary class, but `BinaryExpr` is not.
|
|
*
|
|
* For identifiers and selector expressions, the class describing what kind of entity they refer
|
|
* to (for example `FunctionName` or `TypeName`) is also considered primary. For such nodes,
|
|
* this predicate has multiple values.
|
|
*/
|
|
string getAPrimaryQlClass() { result = "???" }
|
|
|
|
override string toString() { result = "AST node" }
|
|
}
|
|
|
|
/**
|
|
* An AST node whose children include expressions.
|
|
*/
|
|
class ExprParent extends @exprparent, AstNode {
|
|
/**
|
|
* Gets the `i`th child expression of this node.
|
|
*
|
|
* Note that the precise indices of child expressions are considered an implementation detail
|
|
* and are subject to change without notice.
|
|
*/
|
|
Expr getChildExpr(int i) { exprs(result, _, this, i) }
|
|
|
|
/**
|
|
* Gets an expression that is a child node of this node in the AST.
|
|
*/
|
|
Expr getAChildExpr() { result = this.getChildExpr(_) }
|
|
|
|
/**
|
|
* Gets the number of child expressions of this node.
|
|
*/
|
|
int getNumChildExpr() { result = count(this.getAChildExpr()) }
|
|
}
|
|
|
|
/**
|
|
* An AST node whose children include go.mod expressions.
|
|
*/
|
|
class GoModExprParent extends @modexprparent, AstNode {
|
|
/**
|
|
* Gets the `i`th child expression of this node.
|
|
*
|
|
* Note that the precise indices of child expressions are considered an implementation detail
|
|
* and are subject to change without notice.
|
|
*/
|
|
GoModExpr getChildGoModExpr(int i) { modexprs(result, _, this, i) }
|
|
|
|
/**
|
|
* Gets an expression that is a child node of this node in the AST.
|
|
*/
|
|
GoModExpr getAChildGoModExpr() { result = this.getChildGoModExpr(_) }
|
|
|
|
/**
|
|
* Gets the number of child expressions of this node.
|
|
*/
|
|
int getNumChildGoModExpr() { result = count(this.getAChildGoModExpr()) }
|
|
}
|
|
|
|
/**
|
|
* An AST node whose children include statements.
|
|
*/
|
|
class StmtParent extends @stmtparent, AstNode {
|
|
/**
|
|
* Gets the `i`th child statement of this node.
|
|
*
|
|
* Note that the precise indices of child statements are considered an implementation detail
|
|
* and are subject to change without notice.
|
|
*/
|
|
Stmt getChildStmt(int i) { stmts(result, _, this, i) }
|
|
|
|
/**
|
|
* Gets a statement that is a child node of this node in the AST.
|
|
*/
|
|
Stmt getAChildStmt() { result = this.getChildStmt(_) }
|
|
|
|
/**
|
|
* Gets the number of child statements of this node.
|
|
*/
|
|
int getNumChildStmt() { result = count(this.getAChildStmt()) }
|
|
}
|
|
|
|
/**
|
|
* An AST node whose children include declarations.
|
|
*/
|
|
class DeclParent extends @declparent, AstNode {
|
|
/**
|
|
* Gets the `i`th child declaration of this node.
|
|
*
|
|
* Note that the precise indices of declarations are considered an implementation detail
|
|
* and are subject to change without notice.
|
|
*/
|
|
Decl getDecl(int i) { decls(result, _, this, i) }
|
|
|
|
/**
|
|
* Gets a child declaration of this node in the AST.
|
|
*/
|
|
Decl getADecl() { result = this.getDecl(_) }
|
|
|
|
/**
|
|
* Gets the number of child declarations of this node.
|
|
*/
|
|
int getNumDecl() { result = count(this.getADecl()) }
|
|
}
|
|
|
|
/**
|
|
* An AST node whose children include field declarations.
|
|
*
|
|
* A field declaration can be in a struct, a function (for parameter or result
|
|
* variables), or an interface (in which case it is a method or embedding spec).
|
|
*/
|
|
class FieldParent extends @fieldparent, AstNode {
|
|
/**
|
|
* Gets the `i`th field declaration of this node.
|
|
*
|
|
* Note that the precise indices of field declarations are considered an
|
|
* implementation detail and are subject to change without notice.
|
|
*/
|
|
FieldBase getField(int i) { fields(result, this, i) }
|
|
|
|
/**
|
|
* Gets a child field declaration of this node in the AST.
|
|
*/
|
|
FieldBase getAField() { result = this.getField(_) }
|
|
|
|
/**
|
|
* Gets the number of child field declarations of this node.
|
|
*/
|
|
int getNumFields() { result = count(this.getAField()) }
|
|
}
|
|
|
|
/**
|
|
* An AST node whose children include type parameter declarations.
|
|
*/
|
|
class TypeParamDeclParent extends @typeparamdeclparent, AstNode {
|
|
/**
|
|
* Gets the `i`th type parameter declaration of this node.
|
|
*
|
|
* Note that the precise indices of type parameters are considered an implementation detail
|
|
* and are subject to change without notice.
|
|
*/
|
|
TypeParamDecl getTypeParameterDecl(int i) { typeparamdecls(result, this, i) }
|
|
|
|
/**
|
|
* Gets a child field of this node in the AST.
|
|
*/
|
|
TypeParamDecl getATypeParameterDecl() { result = this.getTypeParameterDecl(_) }
|
|
}
|
|
|
|
/**
|
|
* An AST node which may induce a scope.
|
|
*
|
|
* The following nodes may induce scopes:
|
|
*
|
|
* - files
|
|
* - block statements, `if` statements, `switch` statements, `case` clauses, comm clauses, loops
|
|
* - function type expressions
|
|
*
|
|
* Note that functions themselves do not induce a scope, it is their type declaration that induces
|
|
* the scope.
|
|
*/
|
|
class ScopeNode extends @scopenode, AstNode {
|
|
/** Gets the scope induced by this node, if any. */
|
|
LocalScope getScope() { scopenodes(this, result) }
|
|
}
|