[Bug #19570] Propagate message encoding to decorated message

This commit is contained in:
Nobuyoshi Nakada 2023-04-10 15:13:26 +09:00
parent e1d2dc4cfc
commit c30cab8ce4
No known key found for this signature in database
GPG Key ID: 7CD2805BFA3770C6
2 changed files with 25 additions and 6 deletions

View File

@ -7,6 +7,8 @@
(NIL_P(str) ? warn_print(x) : (void)rb_str_cat_cstr(str, x)) (NIL_P(str) ? warn_print(x) : (void)rb_str_cat_cstr(str, x))
#define write_warn2(str, x, l) \ #define write_warn2(str, x, l) \
(NIL_P(str) ? warn_print2(x, l) : (void)rb_str_cat(str, x, l)) (NIL_P(str) ? warn_print2(x, l) : (void)rb_str_cat(str, x, l))
#define write_warn_enc(str, x, l, enc) \
(NIL_P(str) ? warn_print2(x, l) : (void)rb_enc_str_buf_cat(str, x, l, enc))
#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P #ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P
#define warn_print(x) RB_GNUC_EXTENSION_BLOCK( \ #define warn_print(x) RB_GNUC_EXTENSION_BLOCK( \
(__builtin_constant_p(x)) ? \ (__builtin_constant_p(x)) ? \
@ -127,13 +129,17 @@ rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight)
{ {
const char *einfo = ""; const char *einfo = "";
long elen = 0; long elen = 0;
rb_encoding *eenc;
VALUE str = rb_str_new2(""); VALUE str = rb_usascii_str_new_cstr("");
if (!NIL_P(emesg)) { if (!NIL_P(emesg) && rb_enc_asciicompat(eenc = rb_enc_get(emesg))) {
einfo = RSTRING_PTR(emesg); einfo = RSTRING_PTR(emesg);
elen = RSTRING_LEN(emesg); elen = RSTRING_LEN(emesg);
} }
else {
eenc = NULL;
}
if (eclass == rb_eRuntimeError && elen == 0) { if (eclass == rb_eRuntimeError && elen == 0) {
if (highlight) write_warn(str, underline); if (highlight) write_warn(str, underline);
write_warn(str, "unhandled exception"); write_warn(str, "unhandled exception");
@ -156,7 +162,7 @@ rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight)
if (RSTRING_PTR(epath)[0] == '#') if (RSTRING_PTR(epath)[0] == '#')
epath = 0; epath = 0;
if ((tail = memchr(einfo, '\n', elen)) != 0) { if ((tail = memchr(einfo, '\n', elen)) != 0) {
write_warn2(str, einfo, tail - einfo); write_warn_enc(str, einfo, tail - einfo, eenc);
tail++; /* skip newline */ tail++; /* skip newline */
} }
else { else {
@ -176,7 +182,7 @@ rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight)
if (tail && einfo+elen > tail) { if (tail && einfo+elen > tail) {
if (!highlight) { if (!highlight) {
write_warn2(str, "\n", 1); write_warn2(str, "\n", 1);
write_warn2(str, tail, einfo+elen-tail); write_warn_enc(str, tail, einfo+elen-tail, eenc);
} }
else { else {
elen -= tail - einfo; elen -= tail - einfo;
@ -186,7 +192,7 @@ rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight)
tail = memchr(einfo, '\n', elen); tail = memchr(einfo, '\n', elen);
if (!tail || tail > einfo) { if (!tail || tail > einfo) {
write_warn(str, bold); write_warn(str, bold);
write_warn2(str, einfo, tail ? tail-einfo : elen); write_warn_enc(str, einfo, tail ? tail-einfo : elen, eenc);
write_warn(str, reset); write_warn(str, reset);
if (!tail) { if (!tail) {
break; break;
@ -195,7 +201,7 @@ rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight)
elen -= tail - einfo; elen -= tail - einfo;
einfo = tail; einfo = tail;
do ++tail; while (tail < einfo+elen && *tail == '\n'); do ++tail; while (tail < einfo+elen && *tail == '\n');
write_warn2(str, einfo, tail-einfo); write_warn_enc(str, einfo, tail-einfo, eenc);
elen -= tail - einfo; elen -= tail - einfo;
einfo = tail; einfo = tail;
} }

View File

@ -1470,6 +1470,19 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
assert_equal({ highlight: Exception.to_tty? }, opt_) assert_equal({ highlight: Exception.to_tty? }, opt_)
end end
def test_full_message_with_encoding
message = "\u{dc}bersicht"
begin
begin
raise message
rescue => e
raise "\n#{e.message}"
end
rescue => e
end
assert_include(e.full_message, message)
end
def test_syntax_error_detailed_message def test_syntax_error_detailed_message
Dir.mktmpdir do |dir| Dir.mktmpdir do |dir|
File.write(File.join(dir, "detail.rb"), "#{<<~"begin;"}\n#{<<~'end;'}") File.write(File.join(dir, "detail.rb"), "#{<<~"begin;"}\n#{<<~'end;'}")