AST: rescue clauses

This commit is contained in:
Arthur Baars
2021-02-11 18:40:29 +01:00
parent c4e2c87d82
commit 43b238f729
4 changed files with 165 additions and 88 deletions

View File

@@ -131,10 +131,16 @@ class StmtSequence extends Expr {
class BodyStatement extends StmtSequence {
override BodyStatement::Range range;
/** Gets the `else` block in this block, if any. */
/** Gets the `n`th rescue clause in this block. */
final Rescue getRescue(int n) { result = range.getRescue(n) }
/** Gets a rescue clause in this block. */
final Rescue getARescue() { result = this.getRescue(_) }
/** Gets the `else` clause in this block, if any. */
final StmtSequence getElse() { result = range.getElse() }
/** Gets the `ensure` block in this block, if any. */
/** Gets the `ensure` clause in this block, if any. */
final StmtSequence getEnsure() { result = range.getEnsure() }
final predicate hasEnsure() { exists(this.getEnsure()) }
@@ -198,3 +204,58 @@ class Pair extends Expr, @pair {
*/
final Expr getValue() { result = range.getValue() }
}
/**
* A rescue clause. For example:
* ```rb
* begin
* write_file
* rescue StandardError => msg
* puts msg
* end
*/
class Rescue extends Expr, @rescue {
final override Rescue::Range range;
/**
* Gets the `n`th exception to match, if any. For example `FirstError` or `SecondError` in:
* ```rb
* begin
* do_something
* rescue FirstError, SecondError => e
* handle_error(e)
* end
* ```
*/
final Expr getException(int n) { result = range.getException(n) }
/**
* Gets an exception to match, if any. For example `FirstError` or `SecondError` in:
* ```rb
* begin
* do_something
* rescue FirstError, SecondError => e
* handle_error(e)
* end
* ```
*/
final Expr getAnException() { result = getException(_) }
/**
* Gets the variable to which to assign the matched exception, if any.
* For example `err` in:
* ```rb
* begin
* do_something
* rescue StandardError => err
* handle_error(err)
* end
* ```
*/
final Expr getVariable() { result = range.getVariable() }
/**
* Gets the exception handler body.
*/
final StmtSequence getBody() { result = range.getBody() }
}

View File

@@ -33,8 +33,6 @@ module AstNode {
this = any(Generated::Call c).getMethod() and
not this instanceof Generated::ScopeResolution
or
this instanceof Generated::Rescue
or
this instanceof Generated::RestAssignment
or
this = any(Generated::RestAssignment ra).getChild()

View File

@@ -196,6 +196,10 @@ module BodyStatement {
)
}
final Rescue getRescue(int n) {
result = rank[n + 1](Generated::Rescue node, int i | node = getChild(i) | node order by i)
}
final StmtSequence getElse() { result = unique(Generated::Else s | s = getChild(_)) }
final StmtSequence getEnsure() { result = unique(Generated::Ensure s | s = getChild(_)) }
@@ -250,7 +254,21 @@ module Ensure {
final override Stmt getStmt(int n) { result = generated.getChild(n) }
final override string toString() { result = "ensure ... end" }
final override string toString() { result = "ensure ..." }
}
}
module Rescue {
class Range extends Expr::Range, @rescue {
final override Generated::Rescue generated;
final Expr getException(int n) { result = generated.getExceptions().getChild(n) }
final Expr getVariable() { result = generated.getVariable() }
final StmtSequence getBody() { result = generated.getBody() }
final override string toString() { result = "rescue ..." }
}
}