Add AST library for control expressions (conditionals and loops)

This commit is contained in:
Nick Rolfe
2021-01-05 16:08:33 +00:00
parent c35283cefb
commit 7c503120ae
23 changed files with 1070 additions and 39 deletions

View File

@@ -0,0 +1,176 @@
private import codeql_ruby.AST
private import codeql_ruby.ast.internal.Expr
private import codeql_ruby.ast.internal.Pattern
private import codeql_ruby.ast.internal.TreeSitter
module ControlExpr {
abstract class Range extends Expr::Range { }
}
module ConditionalExpr {
abstract class Range extends ControlExpr::Range {
abstract Expr getCondition();
abstract Expr getThen();
abstract Expr getElse();
}
}
module IfOrElsifExpr {
abstract class Range extends ConditionalExpr::Range { }
}
module IfExpr {
class Range extends IfOrElsifExpr::Range, @if {
final override Generated::If generated;
final override Expr getCondition() { result = generated.getCondition() }
final override ThenExpr getThen() { result = generated.getConsequence() }
final override Expr getElse() { result = generated.getAlternative() }
}
}
module ElsifExpr {
class Range extends IfOrElsifExpr::Range, @elsif {
final override Generated::Elsif generated;
final override Expr getCondition() { result = generated.getCondition() }
final override ThenExpr getThen() { result = generated.getConsequence() }
final override Expr getElse() { result = generated.getAlternative() }
}
}
module UnlessExpr {
class Range extends ConditionalExpr::Range, @unless {
final override Generated::Unless generated;
final override Expr getCondition() { result = generated.getCondition() }
final override ThenExpr getThen() { result = generated.getConsequence() }
final override ElseExpr getElse() { result = generated.getAlternative() }
}
}
module IfModifierExpr {
class Range extends ConditionalExpr::Range, @if_modifier {
final override Generated::IfModifier generated;
final override Expr getCondition() { result = generated.getCondition() }
final override Expr getThen() { result = generated.getBody() }
final override Expr getElse() { none() }
}
}
module UnlessModifierExpr {
class Range extends ConditionalExpr::Range, @unless_modifier {
final override Generated::UnlessModifier generated;
final override Expr getCondition() { result = generated.getCondition() }
final override Expr getThen() { result = generated.getBody() }
final override Expr getElse() { none() }
}
}
module TernaryIfExpr {
class Range extends ConditionalExpr::Range, @conditional {
final override Generated::Conditional generated;
final override Expr getCondition() { result = generated.getCondition() }
final override Expr getThen() { result = generated.getConsequence() }
final override Expr getElse() { result = generated.getAlternative() }
}
}
module CaseExpr {
class Range extends ControlExpr::Range {
final override Generated::Case generated;
final Expr getValue() { result = generated.getValue() }
final Expr getBranch(int n) { result = generated.getChild(n) }
final WhenExpr getAWhenBranch() { result = this.getBranch(_) }
final ElseExpr getElseBranch() { result = this.getBranch(_) }
}
}
module WhenExpr {
class Range extends Expr::Range, @when {
final override Generated::When generated;
final ThenExpr getBody() { result = generated.getBody() }
final Expr getPattern(int n) { result = generated.getPattern(n).getChild() }
}
}
module Loop {
abstract class Range extends ControlExpr::Range {
abstract Expr getBody();
}
}
module WhileExpr {
class Range extends Loop::Range, @while {
final override Generated::While generated;
final override DoExpr getBody() { result = generated.getBody() }
final Expr getCondition() { result = generated.getCondition() }
}
}
module UntilExpr {
class Range extends Loop::Range, @until {
final override Generated::Until generated;
final override DoExpr getBody() { result = generated.getBody() }
final Expr getCondition() { result = generated.getCondition() }
}
}
module WhileModifierExpr {
class Range extends Loop::Range, @while_modifier {
final override Generated::WhileModifier generated;
final override Expr getBody() { result = generated.getBody() }
final Expr getCondition() { result = generated.getCondition() }
}
}
module UntilModifierExpr {
class Range extends Loop::Range, @until_modifier {
final override Generated::UntilModifier generated;
final override Expr getBody() { result = generated.getBody() }
final Expr getCondition() { result = generated.getCondition() }
}
}
module ForExpr {
class Range extends Loop::Range, @for {
final override Generated::For generated;
final override DoExpr getBody() { result = generated.getBody() }
final Pattern getPattern() { result = generated.getPattern() }
final Expr getValue() { result = generated.getValue().getChild() }
}
}

View File

@@ -1,4 +1,4 @@
import codeql_ruby.AST
private import codeql_ruby.AST
private import codeql_ruby.ast.internal.TreeSitter
module Expr {
@@ -59,3 +59,33 @@ module RegexLiteral {
}
}
}
module ExprSequence {
abstract class Range extends Expr::Range {
abstract Expr getExpr(int n);
}
}
module ThenExpr {
class Range extends ExprSequence::Range, @then {
final override Generated::Then generated;
final override Expr getExpr(int n) { result = generated.getChild(n) }
}
}
module ElseExpr {
class Range extends ExprSequence::Range, @else {
final override Generated::Else generated;
final override Expr getExpr(int n) { result = generated.getChild(n) }
}
}
module DoExpr {
class Range extends ExprSequence::Range, @do {
final override Generated::Do generated;
final override Expr getExpr(int n) { result = generated.getChild(n) }
}
}

View File

@@ -27,7 +27,7 @@ private predicate patternNode(Generated::AstNode n, boolean parameter) {
any(Generated::Assignment assign).getLeft(),
any(Generated::OperatorAssignment assign).getLeft(),
any(Generated::ExceptionVariable exceptionVariable).getChild(),
any(Generated::For for).getPattern(_)
any(Generated::For for).getPattern()
]
}

View File

@@ -621,22 +621,22 @@ module Generated {
class For extends @for, AstNode {
override string getAPrimaryQlClass() { result = "For" }
override Location getLocation() { for_def(this, _, _, _, _, result) }
override Location getLocation() { for_def(this, _, _, _, _, _, result) }
Do getBody() { for_def(this, _, _, result, _, _) }
Do getBody() { for_def(this, _, _, result, _, _, _) }
AstNode getPattern(int i) { for_pattern(this, i, result) }
AstNode getPattern() { for_def(this, _, _, _, result, _, _) }
In getValue() { for_def(this, _, _, _, result, _) }
In getValue() { for_def(this, _, _, _, _, result, _) }
override AstNode getParent() { for_def(this, result, _, _, _, _) }
override AstNode getParent() { for_def(this, result, _, _, _, _, _) }
override int getParentIndex() { for_def(this, _, result, _, _, _) }
override int getParentIndex() { for_def(this, _, result, _, _, _, _) }
override AstNode getAFieldOrChild() {
for_def(this, _, _, result, _, _) or
for_pattern(this, _, result) or
for_def(this, _, _, _, result, _)
for_def(this, _, _, result, _, _, _) or
for_def(this, _, _, _, result, _, _) or
for_def(this, _, _, _, _, result, _)
}
}
@@ -779,15 +779,15 @@ module Generated {
class Interpolation extends @interpolation, AstNode {
override string getAPrimaryQlClass() { result = "Interpolation" }
override Location getLocation() { interpolation_def(this, _, _, _, result) }
override Location getLocation() { interpolation_def(this, _, _, result) }
UnderscoreStatement getChild() { interpolation_def(this, _, _, result, _) }
UnderscoreStatement getChild() { interpolation_child(this, result) }
override AstNode getParent() { interpolation_def(this, result, _, _, _) }
override AstNode getParent() { interpolation_def(this, result, _, _) }
override int getParentIndex() { interpolation_def(this, _, result, _, _) }
override int getParentIndex() { interpolation_def(this, _, result, _) }
override AstNode getAFieldOrChild() { interpolation_def(this, _, _, result, _) }
override AstNode getAFieldOrChild() { interpolation_child(this, result) }
}
class KeywordParameter extends @keyword_parameter, AstNode {