@@ -280,6 +280,36 @@ class Pair extends Expr instanceof PairImpl {
280280 final override string getAPrimaryQlClass ( ) { result = "Pair" }
281281}
282282
283+ /**
284+ * A disjunctive exception pattern match 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+ */
294+ class ExceptionList extends Expr , TExceptionList {
295+ private Ruby:: Exceptions g ;
296+
297+ ExceptionList ( ) { this = TExceptionList ( g ) }
298+
299+ final override string getAPrimaryQlClass ( ) { result = "ExceptionList" }
300+
301+ /** Gets the `n`th exception in this list. */
302+ final Expr getException ( int n ) { toGenerated ( result ) = g .getChild ( n ) }
303+
304+ final override string toString ( ) { result = "..., ..." }
305+
306+ final override AstNode getAChild ( string pred ) {
307+ result = super .getAChild ( pred )
308+ or
309+ pred = "getException" and result = this .getException ( _)
310+ }
311+ }
312+
283313/**
284314 * A rescue clause. For example:
285315 * ```rb
@@ -296,36 +326,69 @@ class RescueClause extends Expr, TRescueClause {
296326
297327 final override string getAPrimaryQlClass ( ) { result = "RescueClause" }
298328
329+ /** Gets the exception list pattern when there are multiple exception expressions. */
330+ private ExceptionList getExceptions ( ) { result = TExceptionList ( g .getExceptions ( ) ) }
331+
299332 /**
300333 * Gets the `n`th exception to match, if any. For example `FirstError` or `SecondError` in:
301334 * ```rb
302335 * begin
303- * do_something
336+ * do_something
304337 * rescue FirstError, SecondError => e
305338 * handle_error(e)
306339 * end
307340 * ```
308341 */
309- final Expr getException ( int n ) { toGenerated ( result ) = g .getExceptions ( ) .getChild ( n ) }
342+ final Expr getException ( int n ) {
343+ // 0 or 1 exception: no ExceptionList node, access directly
344+ not exists ( this .getExceptions ( ) ) and
345+ toGenerated ( result ) = g .getExceptions ( ) .getChild ( n )
346+ or
347+ // 2+ exceptions: delegate through ExceptionList
348+ result = this .getExceptions ( ) .getException ( n )
349+ }
310350
311351 /**
312352 * Gets an exception to match, if any. For example `FirstError` or `SecondError` in:
313353 * ```rb
314354 * begin
315- * do_something
355+ * do_something
316356 * rescue FirstError, SecondError => e
317357 * handle_error(e)
318358 * end
319359 * ```
320360 */
321361 final Expr getAnException ( ) { result = this .getException ( _) }
322362
363+ /**
364+ * Gets the exception pattern to match, if any.
365+ *
366+ * This is either a single exception expression, or an `ExceptionList`
367+ * representing a disjunctive match of multiple exceptions when there are two
368+ * or more exceptions expressions.
369+ *
370+ * For example, in the following code, the exception pattern is the
371+ * exception list `FirstError, SecondError`:
372+ * ```rb
373+ * begin
374+ * do_something
375+ * rescue FirstError, SecondError => e
376+ * handle_error(e)
377+ * end
378+ * ```
379+ */
380+ final Expr getPattern ( ) {
381+ result = this .getExceptions ( )
382+ or
383+ not exists ( this .getExceptions ( ) ) and result = this .getAnException ( )
384+ }
385+
323386 /**
324387 * Gets the variable to which to assign the matched exception, if any.
325388 * For example `err` in:
326389 * ```rb
327390 * begin
328- * do_something
391+ * do_something
329392 * rescue StandardError => err
330393 * handle_error(err)
331394 * end
@@ -343,7 +406,7 @@ class RescueClause extends Expr, TRescueClause {
343406 final override AstNode getAChild ( string pred ) {
344407 result = super .getAChild ( pred )
345408 or
346- pred = "getException " and result = this .getException ( _ )
409+ pred = "getPattern " and result = this .getPattern ( )
347410 or
348411 pred = "getVariableExpr" and result = this .getVariableExpr ( )
349412 or
0 commit comments