[前][次][番号順一覧][スレッド一覧]

ruby-changes:71242

From: Yusuke <ko1@a...>
Date: Tue, 22 Feb 2022 11:56:11 +0900 (JST)
Subject: [ruby-changes:71242] 35ff545bb6 (master): Exception#detailed_message is added

https://git.ruby-lang.org/ruby.git/commit/?id=35ff545bb6

From 35ff545bb689f5af93ac603ea1f512705e0dc249 Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Tue, 1 Feb 2022 17:59:31 +0900
Subject: Exception#detailed_message is added

Also, the default error printer and Exception#full_message use the
method instead of `Exception#message` to get the message string.

`Exception#detailed_message` calls `Exception#message`, decorates and
returns the result. It adds some escape sequences to highlight, and the
class name of the exception to the end of the first line of the message.

[Feature #18370]
---
 error.c      | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 eval_error.c | 27 ++++++++++++++-------------
 2 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/error.c b/error.c
index 8f9e21dbb5..be4c37cbac 100644
--- a/error.c
+++ b/error.c
@@ -1122,7 +1122,7 @@ static VALUE rb_eNOERROR; https://github.com/ruby/ruby/blob/trunk/error.c#L1122
 
 ID ruby_static_id_cause;
 #define id_cause ruby_static_id_cause
-static ID id_message, id_backtrace;
+static ID id_message, id_detailed_message, id_backtrace;
 static ID id_key, id_matchee, id_args, id_Errno, id_errno, id_i_path;
 static ID id_receiver, id_recv, id_iseq, id_local_variables;
 static ID id_private_call_p, id_top, id_bottom;
@@ -1224,7 +1224,7 @@ exc_to_s(VALUE exc) https://github.com/ruby/ruby/blob/trunk/error.c#L1224
 }
 
 /* FIXME: Include eval_error.c */
-void rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlight, VALUE reverse);
+void rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE opt, VALUE highlight, VALUE reverse);
 
 VALUE
 rb_get_message(VALUE exc)
@@ -1235,6 +1235,21 @@ rb_get_message(VALUE exc) https://github.com/ruby/ruby/blob/trunk/error.c#L1235
     return e;
 }
 
+VALUE
+rb_get_detailed_message(VALUE exc, VALUE opt)
+{
+    VALUE e;
+    if (NIL_P(opt)) {
+        e = rb_check_funcall(exc, id_detailed_message, 0, 0);
+    }
+    else {
+        e = rb_check_funcall_kw(exc, id_detailed_message, 1, &opt, 1);
+    }
+    if (e == Qundef) return Qnil;
+    if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e);
+    return e;
+}
+
 /*
  * call-seq:
  *    Exception.to_tty?   ->  true or false
@@ -1332,9 +1347,9 @@ exc_full_message(int argc, VALUE *argv, VALUE exc) https://github.com/ruby/ruby/blob/trunk/error.c#L1347
 
     str = rb_str_new2("");
     errat = rb_get_backtrace(exc);
-    emesg = rb_get_message(exc);
+    emesg = rb_get_detailed_message(exc, opt);
 
-    rb_error_write(exc, emesg, errat, str, highlight, order);
+    rb_error_write(exc, emesg, errat, str, opt, highlight, order);
     return str;
 }
 
@@ -1352,6 +1367,38 @@ exc_message(VALUE exc) https://github.com/ruby/ruby/blob/trunk/error.c#L1367
     return rb_funcallv(exc, idTo_s, 0, 0);
 }
 
+/*
+ * call-seq:
+ *   exception.detailed_message(highlight: bool, **opt)   ->  string
+ *
+ * Processes a string returned by #message.
+ *
+ * It may add the class name of the exception to the end of the first line.
+ * Also, when +highlight+ keyword is true, it adds ANSI escape sequences to
+ * make the message bold.
+ *
+ * If you override this method, it must be tolerant for unknown keyword
+ * arguments. All keyword arguments passed to #full_message are delegated
+ * to this method.
+ *
+ * This method is overridden by did_you_mean and error_highlight to add
+ * their information.
+ */
+
+static VALUE
+exc_detailed_message(int argc, VALUE *argv, VALUE exc)
+{
+    VALUE opt;
+
+    rb_scan_args(argc, argv, "0:", &opt);
+
+    VALUE highlight = check_highlight_keyword(opt);
+
+    extern VALUE rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight);
+
+    return rb_decorate_message(CLASS_OF(exc), rb_get_message(exc), highlight);
+}
+
 /*
  * call-seq:
  *   exception.inspect   -> string
@@ -2908,6 +2955,7 @@ Init_Exception(void) https://github.com/ruby/ruby/blob/trunk/error.c#L2955
     rb_define_method(rb_eException, "==", exc_equal, 1);
     rb_define_method(rb_eException, "to_s", exc_to_s, 0);
     rb_define_method(rb_eException, "message", exc_message, 0);
+    rb_define_method(rb_eException, "detailed_message", exc_detailed_message, -1);
     rb_define_method(rb_eException, "full_message", exc_full_message, -1);
     rb_define_method(rb_eException, "inspect", exc_inspect, 0);
     rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
@@ -2995,6 +3043,7 @@ Init_Exception(void) https://github.com/ruby/ruby/blob/trunk/error.c#L3043
 
     id_cause = rb_intern_const("cause");
     id_message = rb_intern_const("message");
+    id_detailed_message = rb_intern_const("detailed_message");
     id_backtrace = rb_intern_const("backtrace");
     id_key = rb_intern_const("key");
     id_matchee = rb_intern_const("matchee");
diff --git a/eval_error.c b/eval_error.c
index 7486f2777f..f69243e21d 100644
--- a/eval_error.c
+++ b/eval_error.c
@@ -261,7 +261,7 @@ print_backtrace(const VALUE eclass, const VALUE errat, const VALUE str, int reve https://github.com/ruby/ruby/blob/trunk/eval_error.c#L261
     }
 }
 
-VALUE rb_get_message(VALUE exc);
+VALUE rb_get_detailed_message(VALUE exc, VALUE opt);
 
 static int
 shown_cause_p(VALUE cause, VALUE *shown_causes)
@@ -276,30 +276,29 @@ shown_cause_p(VALUE cause, VALUE *shown_causes) https://github.com/ruby/ruby/blob/trunk/eval_error.c#L276
 }
 
 static void
-show_cause(VALUE errinfo, VALUE str, VALUE highlight, VALUE reverse, long backtrace_limit, VALUE *shown_causes)
+show_cause(VALUE errinfo, VALUE str, VALUE opt, VALUE highlight, VALUE reverse, long backtrace_limit, VALUE *shown_causes)
 {
     VALUE cause = rb_attr_get(errinfo, id_cause);
     if (!NIL_P(cause) && rb_obj_is_kind_of(cause, rb_eException) &&
         !shown_cause_p(cause, shown_causes)) {
         volatile VALUE eclass = CLASS_OF(cause);
         VALUE errat = rb_get_backtrace(cause);
-        VALUE emesg = rb_get_message(cause);
-        emesg = rb_decorate_message(eclass, emesg, RTEST(highlight));
+        VALUE emesg = rb_get_detailed_message(cause, opt);
         if (reverse) {
-            show_cause(cause, str, highlight, reverse, backtrace_limit, shown_causes);
+            show_cause(cause, str, opt, highlight, reverse, backtrace_limit, shown_causes);
             print_backtrace(eclass, errat, str, TRUE, backtrace_limit);
             print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
         }
         else {
             print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
             print_backtrace(eclass, errat, str, FALSE, backtrace_limit);
-            show_cause(cause, str, highlight, reverse, backtrace_limit, shown_causes);
+            show_cause(cause, str, opt, highlight, reverse, backtrace_limit, shown_causes);
         }
     }
 }
 
 void
-rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlight, VALUE reverse)
+rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE opt, VALUE highlight, VALUE reverse)
 {
     volatile VALUE eclass;
     VALUE shown_causes = 0;
@@ -312,7 +311,6 @@ rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlig https://github.com/ruby/ruby/blob/trunk/eval_error.c#L311
 	errat = Qnil;
     }
     eclass = CLASS_OF(errinfo);
-    emesg = rb_decorate_message(eclass, emesg, RTEST(highlight));
     if (reverse) {
 	static const char traceback[] = "Traceback "
 	    "(most recent call last):\n";
@@ -330,14 +328,14 @@ rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlig https://github.com/ruby/ruby/blob/trunk/eval_error.c#L328
 	    len = p - (msg = buff);
 	}
 	write_warn2(str, msg, len);
-        show_cause(errinfo, str, highlight, reverse, backtrace_limit, &shown_causes);
+        show_cause(errinfo, str, opt, highlight, reverse, backtrace_limit, &shown_causes);
 	print_backtrace(eclass, errat, str, TRUE, backtrace_limit);
 	print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
     }
     else {
 	print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
 	print_backtrace(eclass, errat, str, FALSE, backtrace_limit);
-        show_cause(errinfo, str, highlight, reverse, backtrace_limit, &shown_causes);
+        show_cause(errinfo, str, opt, highlight, reverse, backtrace_limit, &shown_causes);
     }
 }
 
@@ -349,6 +347,10 @@ rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo) https://github.com/ruby/ruby/blob/trunk/eval_error.c#L347
     volatile VALUE emesg = Qundef;
     volatile bool written = false;
 
+    VALUE opt = rb_hash_new();
+    VALUE highlight = rb_stderr_tty_p() ? Qtrue : Qfalse;
+    rb_hash_aset(opt, ID2SYM(rb_intern_const("highlight")), highlight);
+
     if (NIL_P(errinfo))
 	return;
     rb_ec_raised_clear(ec);
@@ -359,13 +361,12 @@ rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo) https://github.com/ruby/ruby/blob/trunk/eval_error.c#L361
     }
     if (emesg == Qundef) {
 	emesg = Qnil;
-	emesg = rb_get_message(errinfo);
+	emesg = rb_get_detailed_message(errinfo, opt);
     }
 
     if (!written) {
         written = true;
-        VALUE highlight = rb_stderr_tty_p() ? Qtrue : Qfalse;
-        rb_error_write(errinfo, emesg, errat, Qnil, highlight, Qfalse);
+        rb_error_write(errinfo, emesg, errat, Qnil, opt, highlight, Qfalse);
     }
 
     EC_POP_TAG();
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]