@@ -280,6 +280,37 @@ class Pair extends Expr instanceof PairImpl {
280280 final override string getAPrimaryQlClass ( ) { result = "Pair" }
281281}
282282
283+ /**
284+ * A list of exception types in a rescue clause. For example, the exception list
285+ * `FirstError, SecondError` in:
286+ * ```rb
287+ * begin
288+ * do_something
289+ * rescue FirstError, SecondError => e
290+ * handle_error(e)
291+ * end
292+ * ```
293+ * This node is only present when there are two or more exceptions in the list.
294+ */
295+ class ExceptionList extends Expr , TExceptionList {
296+ private Ruby:: Exceptions g ;
297+
298+ ExceptionList ( ) { this = TExceptionList ( g ) }
299+
300+ final override string getAPrimaryQlClass ( ) { result = "ExceptionList" }
301+
302+ /** Gets the `n`th exception in this list. */
303+ final Expr getException ( int n ) { toGenerated ( result ) = g .getChild ( n ) }
304+
305+ final override string toString ( ) { result = "..., ..." }
306+
307+ final override AstNode getAChild ( string pred ) {
308+ result = super .getAChild ( pred )
309+ or
310+ pred = "getException" and result = this .getException ( _)
311+ }
312+ }
313+
283314/**
284315 * A rescue clause. For example:
285316 * ```rb
@@ -305,8 +336,16 @@ class RescueClause extends Expr, TRescueClause {
305336 * handle_error(e)
306337 * end
307338 * ```
339+ * When there are two or more exceptions, use `getExceptions()` to get the `ExceptionList` node.
308340 */
309- final Expr getException ( int n ) { toGenerated ( result ) = g .getExceptions ( ) .getChild ( n ) }
341+ final Expr getException ( int n ) {
342+ // 0 or 1 exception: no ExceptionList node, access directly
343+ not exists ( this .getExceptions ( ) ) and
344+ toGenerated ( result ) = g .getExceptions ( ) .getChild ( n )
345+ or
346+ // 2+ exceptions: delegate through ExceptionList
347+ result = this .getExceptions ( ) .getException ( n )
348+ }
310349
311350 /**
312351 * Gets an exception to match, if any. For example `FirstError` or `SecondError` in:
@@ -320,6 +359,19 @@ class RescueClause extends Expr, TRescueClause {
320359 */
321360 final Expr getAnException ( ) { result = this .getException ( _) }
322361
362+ /**
363+ * Gets the exception list node when there are two or more exceptions to match. For example,
364+ * the exception list `FirstError, SecondError` in:
365+ * ```rb
366+ * begin
367+ * do_something
368+ * rescue FirstError, SecondError => e
369+ * handle_error(e)
370+ * end
371+ * ```
372+ */
373+ final ExceptionList getExceptions ( ) { result = TExceptionList ( g .getExceptions ( ) ) }
374+
323375 /**
324376 * Gets the variable to which to assign the matched exception, if any.
325377 * For example `err` in:
@@ -343,8 +395,13 @@ class RescueClause extends Expr, TRescueClause {
343395 final override AstNode getAChild ( string pred ) {
344396 result = super .getAChild ( pred )
345397 or
398+ // For 0 or 1 exceptions, exceptions are direct children
399+ not exists ( this .getExceptions ( ) ) and
346400 pred = "getException" and result = this .getException ( _)
347401 or
402+ // For 2+ exceptions, the ExceptionList node is the direct child
403+ pred = "getExceptions" and result = this .getExceptions ( )
404+ or
348405 pred = "getVariableExpr" and result = this .getVariableExpr ( )
349406 or
350407 pred = "getBody" and result = this .getBody ( )
0 commit comments