mirror of
https://github.com/github/codeql.git
synced 2026-02-20 08:53:49 +01:00
AST: add Statement and ReturningStatement
This commit is contained in:
@@ -7,6 +7,7 @@ import ast.Module
|
||||
import ast.Parameter
|
||||
import ast.Operation
|
||||
import ast.Pattern
|
||||
import ast.Statement
|
||||
import ast.Variable
|
||||
private import ast.internal.TreeSitter
|
||||
|
||||
|
||||
97
ql/src/codeql_ruby/ast/Statement.qll
Normal file
97
ql/src/codeql_ruby/ast/Statement.qll
Normal file
@@ -0,0 +1,97 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.CFG
|
||||
private import internal.Statement
|
||||
private import codeql_ruby.controlflow.internal.ControlFlowGraphImpl
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
|
||||
/**
|
||||
* A statement.
|
||||
*
|
||||
* This is the root QL class for all statements.
|
||||
*/
|
||||
class Statement extends AstNode {
|
||||
Statement::Range range;
|
||||
|
||||
Statement() { this = range }
|
||||
|
||||
/** Gets a control-flow node for this statement, if any. */
|
||||
CfgNodes::AstCfgNode getAControlFlowNode() { result.getNode() = this }
|
||||
|
||||
/** Gets the control-flow scope of this statement, if any. */
|
||||
CfgScope getCfgScope() { result = getCfgScope(this) }
|
||||
|
||||
/** Gets the enclosing callable, if any. */
|
||||
Callable getEnclosingCallable() { result = this.getCfgScope() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A statement that may return a value: `return`, `break` and `next`.
|
||||
*
|
||||
* ```rb
|
||||
* return
|
||||
* return value
|
||||
* break
|
||||
* break value
|
||||
* next
|
||||
* next value
|
||||
* ```
|
||||
*/
|
||||
class ReturningStatement extends Statement {
|
||||
override ReturningStatement::Range range;
|
||||
|
||||
final override string toString() {
|
||||
not exists(getValue()) and result = range.getStatementName()
|
||||
or
|
||||
result = range.getStatementName() + " " + getValue().toString()
|
||||
}
|
||||
|
||||
/** Gets the returned value, if any. */
|
||||
final Expr getValue() {
|
||||
exists(Generated::ArgumentList a, int c |
|
||||
a = range.getArgumentList() and c = count(a.getChild(_))
|
||||
|
|
||||
result = a.getChild(0) and c = 1
|
||||
or
|
||||
result = a and c > 1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `return` statement.
|
||||
* ```rb
|
||||
* return
|
||||
* return value
|
||||
* ```
|
||||
*/
|
||||
class ReturnStmt extends ReturningStatement, @return {
|
||||
final override ReturnStmt::Range range;
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "ReturnStmt" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `break` statement.
|
||||
* ```rb
|
||||
* break
|
||||
* break value
|
||||
* ```
|
||||
*/
|
||||
class BreakStmt extends ReturningStatement, @break {
|
||||
final override BreakStmt::Range range;
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "BreakStmt" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `next` statement.
|
||||
* ```rb
|
||||
* next
|
||||
* next value
|
||||
* ```
|
||||
*/
|
||||
class NextStmt extends ReturningStatement, @next {
|
||||
final override NextStmt::Range range;
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "NextStmt" }
|
||||
}
|
||||
44
ql/src/codeql_ruby/ast/internal/Statement.qll
Normal file
44
ql/src/codeql_ruby/ast/internal/Statement.qll
Normal file
@@ -0,0 +1,44 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
|
||||
module Statement {
|
||||
abstract class Range extends AstNode { }
|
||||
}
|
||||
|
||||
module ReturningStatement {
|
||||
abstract class Range extends Statement::Range {
|
||||
abstract Generated::ArgumentList getArgumentList();
|
||||
|
||||
abstract string getStatementName();
|
||||
}
|
||||
}
|
||||
|
||||
module ReturnStmt {
|
||||
class Range extends ReturningStatement::Range, @return {
|
||||
final override Generated::Return generated;
|
||||
|
||||
final override string getStatementName() { result = "return" }
|
||||
|
||||
final override Generated::ArgumentList getArgumentList() { result = generated.getChild() }
|
||||
}
|
||||
}
|
||||
|
||||
module BreakStmt {
|
||||
class Range extends ReturningStatement::Range, @break {
|
||||
final override Generated::Break generated;
|
||||
|
||||
final override string getStatementName() { result = "break" }
|
||||
|
||||
final override Generated::ArgumentList getArgumentList() { result = generated.getChild() }
|
||||
}
|
||||
}
|
||||
|
||||
module NextStmt {
|
||||
class Range extends ReturningStatement::Range, @next {
|
||||
final override Generated::Next generated;
|
||||
|
||||
final override string getStatementName() { result = "next" }
|
||||
|
||||
final override Generated::ArgumentList getArgumentList() { result = generated.getChild() }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user