diff --git a/ChangeLog b/ChangeLog index 2b3035dd51..cdd9319864 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Tue Sep 27 18:10:18 2016 Jeremy Evans + + * error.c: This makes all warnings raised call Warning.warn, which + by default does the same thing it does currently + (rb_write_error_str). You can override Warning.warn to change + the behavior. [ruby-core:75016] [Feature #12299] + Tue Sep 27 17:35:28 2016 Nobuyoshi Nakada * iseq.c (iseqw_s_compile_file): deal with syntax error as well as diff --git a/error.c b/error.c index 4224c5f771..2fcacfaa5b 100644 --- a/error.c +++ b/error.c @@ -42,6 +42,9 @@ VALUE rb_iseqw_new(const rb_iseq_t *); VALUE rb_eEAGAIN; VALUE rb_eEWOULDBLOCK; VALUE rb_eEINPROGRESS; +VALUE rb_mWarning; + +static ID id_warn; extern const char ruby_description[]; @@ -146,6 +149,19 @@ ruby_only_for_internal_use(const char *func) rb_fatal("%s is only for internal use and deprecated; do not use", func); } +static VALUE +rb_warning_s_warn(VALUE mod, VALUE str) +{ + rb_write_error_str(str); + return Qnil; +} + +static void +rb_write_warning_str(VALUE str) +{ + rb_funcall(rb_mWarning, id_warn, 1, str); +} + static VALUE warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_list args) { @@ -166,7 +182,7 @@ rb_compile_warn(const char *file, int line, const char *fmt, ...) va_start(args, fmt); str = warn_vsprintf(NULL, file, line, fmt, args); va_end(args); - rb_write_error_str(str); + rb_write_warning_str(str); } /* rb_compile_warning() reports only in verbose mode */ @@ -181,7 +197,7 @@ rb_compile_warning(const char *file, int line, const char *fmt, ...) va_start(args, fmt); str = warn_vsprintf(NULL, file, line, fmt, args); va_end(args); - rb_write_error_str(str); + rb_write_warning_str(str); } static VALUE @@ -206,7 +222,7 @@ rb_warn(const char *fmt, ...) va_start(args, fmt); mesg = warning_string(0, fmt, args); va_end(args); - rb_write_error_str(mesg); + rb_write_warning_str(mesg); } void @@ -220,7 +236,7 @@ rb_enc_warn(rb_encoding *enc, const char *fmt, ...) va_start(args, fmt); mesg = warning_string(enc, fmt, args); va_end(args); - rb_write_error_str(mesg); + rb_write_warning_str(mesg); } /* rb_warning() reports only in verbose mode */ @@ -235,7 +251,7 @@ rb_warning(const char *fmt, ...) va_start(args, fmt); mesg = warning_string(0, fmt, args); va_end(args); - rb_write_error_str(mesg); + rb_write_warning_str(mesg); } #if 0 @@ -250,7 +266,7 @@ rb_enc_warning(rb_encoding *enc, const char *fmt, ...) va_start(args, fmt); mesg = warning_string(enc, fmt, args); va_end(args); - rb_write_error_str(mesg); + rb_write_warning_str(mesg); } #endif @@ -2052,6 +2068,10 @@ Init_Exception(void) rb_mErrno = rb_define_module("Errno"); + rb_mWarning = rb_define_module("Warning"); + rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, 1); + rb_extend_object(rb_mWarning, rb_mWarning); + rb_define_global_function("warn", rb_warn_m, -1); id_new = rb_intern_const("new"); @@ -2066,6 +2086,7 @@ Init_Exception(void) id_Errno = rb_intern_const("Errno"); id_errno = rb_intern_const("errno"); id_i_path = rb_intern_const("@path"); + id_warn = rb_intern_const("warn"); id_iseq = rb_make_internal_id(); } @@ -2289,7 +2310,7 @@ rb_sys_warning(const char *fmt, ...) va_end(args); rb_str_set_len(mesg, RSTRING_LEN(mesg)-1); rb_str_catf(mesg, ": %s\n", strerror(errno_save)); - rb_write_error_str(mesg); + rb_write_warning_str(mesg); errno = errno_save; } @@ -2309,7 +2330,7 @@ rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...) va_end(args); rb_str_set_len(mesg, RSTRING_LEN(mesg)-1); rb_str_catf(mesg, ": %s\n", strerror(errno_save)); - rb_write_error_str(mesg); + rb_write_warning_str(mesg); errno = errno_save; } diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index 208c5ecfc0..3735e492d8 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -913,4 +913,31 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end end end + + def test_warning_warn + verbose = $VERBOSE + warning = nil + + ::Warning.class_eval do + alias_method :warn2, :warn + remove_method :warn + + define_method(:warn) do |str| + warning = str + end + end + + $VERBOSE = true + a = @a + + assert_match(/instance variable @a not initialized/, warning) + ensure + $VERBOSE = verbose + + ::Warning.class_eval do + remove_method :warn + alias_method :warn, :warn2 + remove_method :warn2 + end + end end