aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS.md8
-rw-r--r--error.c30
-rw-r--r--test/ruby/test_exception.rb24
3 files changed, 54 insertions, 8 deletions
diff --git a/NEWS.md b/NEWS.md
index 075c5ec8b9..1bc19e83e1 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -165,6 +165,13 @@ Outstanding ones only.
* Symbol#to_proc now returns a lambda Proc.
[[Feature #16260]]
+* Warning
+
+ * Modified method
+
+ * Warning#warn now supports a category kwarg.
+ [[Feature #17122]]
+
## Stdlib updates
Outstanding ones only.
@@ -342,3 +349,4 @@ Excluding feature bug fixes.
[Feature #16686]: https://bugs.ruby-lang.org/issues/16686
[Misc #16961]: https://bugs.ruby-lang.org/issues/16961
[Bug #8446]: https://bugs.ruby-lang.org/issues/8446
+[Feature #17122]: https://bugs.ruby-lang.org/issues/17122
diff --git a/error.c b/error.c
index ce936ac568..841ab6c97f 100644
--- a/error.c
+++ b/error.c
@@ -229,15 +229,20 @@ rb_warning_s_aset(VALUE mod, VALUE category, VALUE flag)
/*
* call-seq:
- * warn(msg) -> nil
+ * warn(msg, **kw) -> nil
*
* Writes warning message +msg+ to $stderr. This method is called by
- * Ruby for all emitted warnings.
+ * Ruby for all emitted warnings. A +category+ may be included with
+ * the warning.
*/
static VALUE
-rb_warning_s_warn(VALUE mod, VALUE str)
+rb_warning_s_warn(int argc, VALUE *argv, VALUE mod)
{
+ VALUE str;
+ VALUE opt;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
Check_Type(str, T_STRING);
rb_must_asciicompat(str);
rb_write_error_str(str);
@@ -401,7 +406,22 @@ rb_warn_deprecated_to_remove(const char *fmt, const char *removal, ...)
va_end(args);
rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1);
rb_str_catf(mesg, " is deprecated and will be removed in Ruby %s\n", removal);
- rb_write_warning_str(mesg);
+
+ VALUE warn_args[2];
+ warn_args[0] = mesg;
+
+ const rb_method_entry_t * me;
+ me = rb_method_entry(rb_mWarning, id_warn);
+
+ if (rb_method_entry_arity(me) != 1) {
+ VALUE kwargs = rb_hash_new();
+ rb_hash_aset(kwargs, ID2SYM(rb_intern("category")), ID2SYM(rb_intern("deprecated")));
+ warn_args[1] = kwargs;
+
+ rb_funcallv_kw(rb_mWarning, id_warn, 2, warn_args, RB_PASS_KEYWORDS);
+ } else {
+ rb_funcall(rb_mWarning, id_warn, 1, mesg);
+ }
}
static inline int
@@ -2658,7 +2678,7 @@ Init_Exception(void)
rb_mWarning = rb_define_module("Warning");
rb_define_singleton_method(rb_mWarning, "[]", rb_warning_s_aref, 1);
rb_define_singleton_method(rb_mWarning, "[]=", rb_warning_s_aset, 2);
- rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, 1);
+ rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, -1);
rb_extend_object(rb_mWarning, rb_mWarning);
/* :nodoc: */
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 4decddc273..a89aed8806 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -915,7 +915,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
end
- def capture_warning_warn
+ def capture_warning_warn(category: false)
verbose = $VERBOSE
deprecated = Warning[:deprecated]
warning = []
@@ -924,8 +924,14 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
alias_method :warn2, :warn
remove_method :warn
- define_method(:warn) do |str|
- warning << str
+ if category
+ define_method(:warn) do |str, **kw|
+ warning << [str, kw[:category]]
+ end
+ else
+ define_method(:warn) do |str|
+ warning << str
+ end
end
end
@@ -954,6 +960,18 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
assert_equal(["\n"], capture_warning_warn {warn ""})
end
+ def test_warn_backwards_compatibility
+ warning = capture_warning_warn { Object.new.tainted? }
+
+ assert_match(/deprecated/, warning[0])
+ end
+
+ def test_warn_category
+ warning = capture_warning_warn(category: true) { Object.new.tainted? }
+
+ assert_equal :deprecated, warning[0][1]
+ end
+
def test_kernel_warn_uplevel
warning = capture_warning_warn {warn("test warning", uplevel: 0)}
assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0])