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]
This commit is contained in:
parent
3af316fa8c
commit
35ff545bb6
Notes:
git
2022-02-22 11:56:16 +09:00
57
error.c
57
error.c
@ -1122,7 +1122,7 @@ static VALUE rb_eNOERROR;
|
|||||||
|
|
||||||
ID ruby_static_id_cause;
|
ID ruby_static_id_cause;
|
||||||
#define id_cause 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_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_receiver, id_recv, id_iseq, id_local_variables;
|
||||||
static ID id_private_call_p, id_top, id_bottom;
|
static ID id_private_call_p, id_top, id_bottom;
|
||||||
@ -1224,7 +1224,7 @@ exc_to_s(VALUE exc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Include eval_error.c */
|
/* 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
|
VALUE
|
||||||
rb_get_message(VALUE exc)
|
rb_get_message(VALUE exc)
|
||||||
@ -1235,6 +1235,21 @@ rb_get_message(VALUE exc)
|
|||||||
return e;
|
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:
|
* call-seq:
|
||||||
* Exception.to_tty? -> true or false
|
* Exception.to_tty? -> true or false
|
||||||
@ -1332,9 +1347,9 @@ exc_full_message(int argc, VALUE *argv, VALUE exc)
|
|||||||
|
|
||||||
str = rb_str_new2("");
|
str = rb_str_new2("");
|
||||||
errat = rb_get_backtrace(exc);
|
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;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1352,6 +1367,38 @@ exc_message(VALUE exc)
|
|||||||
return rb_funcallv(exc, idTo_s, 0, 0);
|
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:
|
* call-seq:
|
||||||
* exception.inspect -> string
|
* exception.inspect -> string
|
||||||
@ -2908,6 +2955,7 @@ Init_Exception(void)
|
|||||||
rb_define_method(rb_eException, "==", exc_equal, 1);
|
rb_define_method(rb_eException, "==", exc_equal, 1);
|
||||||
rb_define_method(rb_eException, "to_s", exc_to_s, 0);
|
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, "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, "full_message", exc_full_message, -1);
|
||||||
rb_define_method(rb_eException, "inspect", exc_inspect, 0);
|
rb_define_method(rb_eException, "inspect", exc_inspect, 0);
|
||||||
rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
|
rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
|
||||||
@ -2995,6 +3043,7 @@ Init_Exception(void)
|
|||||||
|
|
||||||
id_cause = rb_intern_const("cause");
|
id_cause = rb_intern_const("cause");
|
||||||
id_message = rb_intern_const("message");
|
id_message = rb_intern_const("message");
|
||||||
|
id_detailed_message = rb_intern_const("detailed_message");
|
||||||
id_backtrace = rb_intern_const("backtrace");
|
id_backtrace = rb_intern_const("backtrace");
|
||||||
id_key = rb_intern_const("key");
|
id_key = rb_intern_const("key");
|
||||||
id_matchee = rb_intern_const("matchee");
|
id_matchee = rb_intern_const("matchee");
|
||||||
|
27
eval_error.c
27
eval_error.c
@ -261,7 +261,7 @@ print_backtrace(const VALUE eclass, const VALUE errat, const VALUE str, int reve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE rb_get_message(VALUE exc);
|
VALUE rb_get_detailed_message(VALUE exc, VALUE opt);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
shown_cause_p(VALUE cause, VALUE *shown_causes)
|
shown_cause_p(VALUE cause, VALUE *shown_causes)
|
||||||
@ -276,30 +276,29 @@ shown_cause_p(VALUE cause, VALUE *shown_causes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
VALUE cause = rb_attr_get(errinfo, id_cause);
|
||||||
if (!NIL_P(cause) && rb_obj_is_kind_of(cause, rb_eException) &&
|
if (!NIL_P(cause) && rb_obj_is_kind_of(cause, rb_eException) &&
|
||||||
!shown_cause_p(cause, shown_causes)) {
|
!shown_cause_p(cause, shown_causes)) {
|
||||||
volatile VALUE eclass = CLASS_OF(cause);
|
volatile VALUE eclass = CLASS_OF(cause);
|
||||||
VALUE errat = rb_get_backtrace(cause);
|
VALUE errat = rb_get_backtrace(cause);
|
||||||
VALUE emesg = rb_get_message(cause);
|
VALUE emesg = rb_get_detailed_message(cause, opt);
|
||||||
emesg = rb_decorate_message(eclass, emesg, RTEST(highlight));
|
|
||||||
if (reverse) {
|
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_backtrace(eclass, errat, str, TRUE, backtrace_limit);
|
||||||
print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
|
print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
|
print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
|
||||||
print_backtrace(eclass, errat, str, FALSE, backtrace_limit);
|
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
|
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;
|
volatile VALUE eclass;
|
||||||
VALUE shown_causes = 0;
|
VALUE shown_causes = 0;
|
||||||
@ -312,7 +311,6 @@ rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlig
|
|||||||
errat = Qnil;
|
errat = Qnil;
|
||||||
}
|
}
|
||||||
eclass = CLASS_OF(errinfo);
|
eclass = CLASS_OF(errinfo);
|
||||||
emesg = rb_decorate_message(eclass, emesg, RTEST(highlight));
|
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
static const char traceback[] = "Traceback "
|
static const char traceback[] = "Traceback "
|
||||||
"(most recent call last):\n";
|
"(most recent call last):\n";
|
||||||
@ -330,14 +328,14 @@ rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlig
|
|||||||
len = p - (msg = buff);
|
len = p - (msg = buff);
|
||||||
}
|
}
|
||||||
write_warn2(str, msg, len);
|
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_backtrace(eclass, errat, str, TRUE, backtrace_limit);
|
||||||
print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
|
print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
|
print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
|
||||||
print_backtrace(eclass, errat, str, FALSE, backtrace_limit);
|
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)
|
|||||||
volatile VALUE emesg = Qundef;
|
volatile VALUE emesg = Qundef;
|
||||||
volatile bool written = false;
|
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))
|
if (NIL_P(errinfo))
|
||||||
return;
|
return;
|
||||||
rb_ec_raised_clear(ec);
|
rb_ec_raised_clear(ec);
|
||||||
@ -359,13 +361,12 @@ rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo)
|
|||||||
}
|
}
|
||||||
if (emesg == Qundef) {
|
if (emesg == Qundef) {
|
||||||
emesg = Qnil;
|
emesg = Qnil;
|
||||||
emesg = rb_get_message(errinfo);
|
emesg = rb_get_detailed_message(errinfo, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!written) {
|
if (!written) {
|
||||||
written = true;
|
written = true;
|
||||||
VALUE highlight = rb_stderr_tty_p() ? Qtrue : Qfalse;
|
rb_error_write(errinfo, emesg, errat, Qnil, opt, highlight, Qfalse);
|
||||||
rb_error_write(errinfo, emesg, errat, Qnil, highlight, Qfalse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EC_POP_TAG();
|
EC_POP_TAG();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user