From f7774e8209ba8ddec8837814f61dd9244fa52f0e Mon Sep 17 00:00:00 2001 From: Simon Coffey Date: Mon, 16 Oct 2017 16:52:32 +0100 Subject: [PATCH] Clarify output when printing nested exception traces Since v10.2.0, if an exception has a nested cause exception, the cause is also displayed in the trace output.[1] For heavily-nested exceptions, this output can be quite lengthy - for example, Rails migrations nest DB errors twice over, resulting in an error message and backtrace repeated three times. To break up this output and make it clearer what each individual backtrace relates to, this adds whitespace and a "Caused by:" label to each nested exception being displayed. To prevent "Caused by:" labels occurring on their own, I've moved the exception loop shortcut return into the `#display_cause_details` method. This doesn't alter the behaviour of the shortcut, as only the first exception will be unconditionally printed (which was already the case, as the first exception can't be already seen). [1] https://github.com/ruby/rake/commit/fbb22e7f570fc573ad1bff9d5905df1ab1cbd475 [2] https://github.com/ruby/rake/commit/57c932cea12ef3201fcaeaf80ba6f4f545390269 --- lib/rake/application.rb | 17 +++++++++++++---- test/test_rake_application.rb | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/rake/application.rb b/lib/rake/application.rb index 89565a670..88a38fd8c 100644 --- a/lib/rake/application.rb +++ b/lib/rake/application.rb @@ -207,13 +207,22 @@ def display_error_message(ex) # :nodoc: end def display_exception_details(ex) # :nodoc: - seen = Thread.current[:rake_display_exception_details_seen] ||= [] - return if seen.include? ex - seen << ex + display_exception_details_seen << ex display_exception_message_details(ex) display_exception_backtrace(ex) - display_exception_details(ex.cause) if has_cause?(ex) + display_cause_details(ex.cause) if has_cause?(ex) + end + + def display_cause_details(ex) # :nodoc: + return if display_exception_details_seen.include? ex + + trace "\nCaused by:" + display_exception_details(ex) + end + + def display_exception_details_seen # :nodoc: + Thread.current[:rake_display_exception_details_seen] ||= [] end def has_cause?(ex) # :nodoc: diff --git a/test/test_rake_application.rb b/test/test_rake_application.rb index cc063c0d2..d17445c7e 100644 --- a/test/test_rake_application.rb +++ b/test/test_rake_application.rb @@ -97,6 +97,7 @@ def test_display_exception_details_cause assert_empty out + assert_match "Caused by:", err assert_match "cause a", err assert_match "cause b", err end