Ignore <internal: entries from core library methods for Kernel#warn(message, uplevel: n)
* Fixes [Bug #17259]
This commit is contained in:
parent
fbb2d30ee6
commit
cffdacb15a
Notes:
git
2020-10-26 16:48:01 +09:00
5
error.c
5
error.c
@ -504,7 +504,8 @@ warning_write(int argc, VALUE *argv, VALUE buf)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE rb_ec_backtrace_location_ary(rb_execution_context_t *ec, long lev, long n);
|
VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal);
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALUE category)
|
rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALUE category)
|
||||||
{
|
{
|
||||||
@ -519,7 +520,7 @@ rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALU
|
|||||||
if (lev < 0) {
|
if (lev < 0) {
|
||||||
rb_raise(rb_eArgError, "negative level (%ld)", lev);
|
rb_raise(rb_eArgError, "negative level (%ld)", lev);
|
||||||
}
|
}
|
||||||
location = rb_ec_backtrace_location_ary(ec, lev + 1, 1);
|
location = rb_ec_backtrace_location_ary(ec, lev + 1, 1, TRUE);
|
||||||
if (!NIL_P(location)) {
|
if (!NIL_P(location)) {
|
||||||
location = rb_ary_entry(location, 0);
|
location = rb_ary_entry(location, 0);
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ VALUE rb_vm_cbase(void);
|
|||||||
/* vm_backtrace.c */
|
/* vm_backtrace.c */
|
||||||
VALUE rb_ec_backtrace_object(const rb_execution_context_t *ec);
|
VALUE rb_ec_backtrace_object(const rb_execution_context_t *ec);
|
||||||
VALUE rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n);
|
VALUE rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n);
|
||||||
VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n);
|
VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal);
|
||||||
|
|
||||||
#ifndef CharNext /* defined as CharNext[AW] on Windows. */
|
#ifndef CharNext /* defined as CharNext[AW] on Windows. */
|
||||||
# ifdef HAVE_MBLEN
|
# ifdef HAVE_MBLEN
|
||||||
|
14
spec/ruby/core/kernel/fixtures/warn_core_method.rb
Normal file
14
spec/ruby/core/kernel/fixtures/warn_core_method.rb
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
raise 'should be run without RubyGems' if defined?(Gem)
|
||||||
|
|
||||||
|
def deprecated(n=1)
|
||||||
|
# puts nil, caller(0), nil
|
||||||
|
warn "use X instead", uplevel: n
|
||||||
|
end
|
||||||
|
|
||||||
|
1.times do # to test with a non-empty stack above the reported locations
|
||||||
|
deprecated
|
||||||
|
tap(&:deprecated)
|
||||||
|
tap { deprecated(2) }
|
||||||
|
# eval sources with a <internal: file are also ignored
|
||||||
|
eval "tap(&:deprecated)", nil, "<internal:should-be-skipped-by-warn-uplevel>"
|
||||||
|
end
|
@ -114,6 +114,22 @@ describe "Kernel#warn" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
guard -> { Kernel.instance_method(:tap).source_location } do
|
||||||
|
it "skips <internal: core library methods defined in Ruby" do
|
||||||
|
file, line = Kernel.instance_method(:tap).source_location
|
||||||
|
file.should.start_with?('<internal:')
|
||||||
|
|
||||||
|
file = fixture(__FILE__ , "warn_core_method.rb")
|
||||||
|
n = 9
|
||||||
|
ruby_exe(file, options: "--disable-gems", args: "2>&1").lines.should == [
|
||||||
|
"#{file}:#{n+0}: warning: use X instead\n",
|
||||||
|
"#{file}:#{n+1}: warning: use X instead\n",
|
||||||
|
"#{file}:#{n+2}: warning: use X instead\n",
|
||||||
|
"#{file}:#{n+4}: warning: use X instead\n",
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
ruby_version_is "3.0" do
|
ruby_version_is "3.0" do
|
||||||
it "accepts :category keyword with a symbol" do
|
it "accepts :category keyword with a symbol" do
|
||||||
-> {
|
-> {
|
||||||
|
@ -601,6 +601,15 @@ struct bt_iter_arg {
|
|||||||
rb_backtrace_location_t *init_loc;
|
rb_backtrace_location_t *init_loc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_internal_location(const rb_control_frame_t *cfp)
|
||||||
|
{
|
||||||
|
static const char prefix[] = "<internal:";
|
||||||
|
const size_t prefix_len = sizeof(prefix) - 1;
|
||||||
|
VALUE file = rb_iseq_path(cfp->iseq);
|
||||||
|
return strncmp(prefix, RSTRING_PTR(file), prefix_len) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bt_init(void *ptr, size_t size)
|
bt_init(void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
@ -626,6 +635,27 @@ bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
|
|||||||
arg->prev_loc = loc;
|
arg->prev_loc = loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bt_iter_iseq_skip_internal(void *ptr, const rb_control_frame_t *cfp)
|
||||||
|
{
|
||||||
|
struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
|
||||||
|
rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++-1];
|
||||||
|
|
||||||
|
if (!is_internal_location(cfp)) {
|
||||||
|
loc->type = LOCATION_TYPE_ISEQ;
|
||||||
|
loc->body.iseq.iseq = cfp->iseq;
|
||||||
|
loc->body.iseq.lineno.pc = cfp->pc;
|
||||||
|
arg->prev_loc = loc;
|
||||||
|
} else if (arg->prev_cfp) {
|
||||||
|
loc->type = LOCATION_TYPE_ISEQ;
|
||||||
|
loc->body.iseq.iseq = arg->prev_cfp->iseq;
|
||||||
|
loc->body.iseq.lineno.pc = arg->prev_cfp->pc;
|
||||||
|
arg->prev_loc = loc;
|
||||||
|
} else {
|
||||||
|
rb_bug("No non-internal backtrace entry before an <internal: backtrace entry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
|
bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
|
||||||
{
|
{
|
||||||
@ -656,8 +686,18 @@ bt_iter_skip(void *ptr, const rb_control_frame_t *cfp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bt_iter_skip_skip_internal(void *ptr, const rb_control_frame_t *cfp)
|
||||||
|
{
|
||||||
|
if (cfp->iseq && cfp->pc) {
|
||||||
|
if (!is_internal_location(cfp)) {
|
||||||
|
((struct bt_iter_arg *) ptr)->prev_cfp = cfp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_ec_partial_backtrace_object(const rb_execution_context_t *ec, long lev, long n, int* level_too_large)
|
rb_ec_partial_backtrace_object(const rb_execution_context_t *ec, long lev, long n, int* level_too_large, bool skip_internal)
|
||||||
{
|
{
|
||||||
struct bt_iter_arg arg;
|
struct bt_iter_arg arg;
|
||||||
int too_large;
|
int too_large;
|
||||||
@ -667,9 +707,9 @@ rb_ec_partial_backtrace_object(const rb_execution_context_t *ec, long lev, long
|
|||||||
lev,
|
lev,
|
||||||
n,
|
n,
|
||||||
bt_init,
|
bt_init,
|
||||||
bt_iter_iseq,
|
skip_internal ? bt_iter_iseq_skip_internal : bt_iter_iseq,
|
||||||
bt_iter_cfunc,
|
bt_iter_cfunc,
|
||||||
bt_iter_skip,
|
skip_internal ? bt_iter_skip_skip_internal : bt_iter_skip,
|
||||||
&arg);
|
&arg);
|
||||||
|
|
||||||
if (level_too_large) *level_too_large = too_large;
|
if (level_too_large) *level_too_large = too_large;
|
||||||
@ -680,7 +720,7 @@ rb_ec_partial_backtrace_object(const rb_execution_context_t *ec, long lev, long
|
|||||||
MJIT_FUNC_EXPORTED VALUE
|
MJIT_FUNC_EXPORTED VALUE
|
||||||
rb_ec_backtrace_object(const rb_execution_context_t *ec)
|
rb_ec_backtrace_object(const rb_execution_context_t *ec)
|
||||||
{
|
{
|
||||||
return rb_ec_partial_backtrace_object(ec, BACKTRACE_START, ALL_BACKTRACE_LINES, NULL);
|
return rb_ec_partial_backtrace_object(ec, BACKTRACE_START, ALL_BACKTRACE_LINES, NULL, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
@ -802,13 +842,13 @@ backtrace_load_data(VALUE self, VALUE str)
|
|||||||
VALUE
|
VALUE
|
||||||
rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n)
|
rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n)
|
||||||
{
|
{
|
||||||
return backtrace_to_str_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL));
|
return backtrace_to_str_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE));
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n)
|
rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal)
|
||||||
{
|
{
|
||||||
return backtrace_to_location_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL));
|
return backtrace_to_location_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, skip_internal));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make old style backtrace directly */
|
/* make old style backtrace directly */
|
||||||
@ -1031,7 +1071,7 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg
|
|||||||
return rb_ary_new();
|
return rb_ary_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
btval = rb_ec_partial_backtrace_object(ec, lev, n, &too_large);
|
btval = rb_ec_partial_backtrace_object(ec, lev, n, &too_large, FALSE);
|
||||||
|
|
||||||
if (too_large) {
|
if (too_large) {
|
||||||
return Qnil;
|
return Qnil;
|
||||||
@ -1355,7 +1395,7 @@ rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
|
|||||||
|
|
||||||
dbg_context.ec = ec;
|
dbg_context.ec = ec;
|
||||||
dbg_context.cfp = dbg_context.ec->cfp;
|
dbg_context.cfp = dbg_context.ec->cfp;
|
||||||
dbg_context.backtrace = rb_ec_backtrace_location_ary(ec, BACKTRACE_START, ALL_BACKTRACE_LINES);
|
dbg_context.backtrace = rb_ec_backtrace_location_ary(ec, BACKTRACE_START, ALL_BACKTRACE_LINES, FALSE);
|
||||||
dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace);
|
dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace);
|
||||||
dbg_context.contexts = collect_caller_bindings(ec);
|
dbg_context.contexts = collect_caller_bindings(ec);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user