1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Use more accurate source location in keyword argument separation warnings

This shows locations in places it didn't before, such as for
proc calls, and fixes the location for super calls.

This requires making iseq_location non-static and MJIT exported,
which I hope will not cause problems.
This commit is contained in:
Jeremy Evans 2019-08-30 21:56:50 -07:00
parent 3463e83192
commit ec6206a81a
3 changed files with 17 additions and 21 deletions

2
proc.c
View file

@ -1183,7 +1183,7 @@ rb_proc_get_iseq(VALUE self, int *is_proc)
return NULL;
}
static VALUE
MJIT_FUNC_EXPORTED VALUE
iseq_location(const rb_iseq_t *iseq)
{
VALUE loc[2];

View file

@ -308,18 +308,18 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(expect, rest_keyrest(*expect), bug7665)
end
pr = proc {|*args, **opt| next *args, opt}
assert_warn(/The last argument for `call' is used as the keyword parameter/) do
assert_warn(/The last argument for `call' .* is used as the keyword parameter/) do
assert_equal(expect, pr.call(*expect), bug7665)
end
assert_warn(/The last argument for `call' is used as the keyword parameter/) do
assert_warn(/The last argument for `call' .* is used as the keyword parameter/) do
assert_equal(expect, pr.call(expect), bug8463)
end
pr = proc {|a, *b, **opt| next a, *b, opt}
assert_warn(/The last argument for `call' is used as the keyword parameter/) do
assert_warn(/The last argument for `call' .* is used as the keyword parameter/) do
assert_equal(expect, pr.call(expect), bug8463)
end
pr = proc {|a, **opt| next a, opt}
assert_warn(/The last argument for `call' is used as the keyword parameter/) do
assert_warn(/The last argument for `call' .* is used as the keyword parameter/) do
assert_equal(expect.values_at(0, -1), pr.call(expect), bug8463)
end
end

View file

@ -579,17 +579,13 @@ ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq) {
return 0;
}
static inline VALUE
get_loc(struct rb_calling_info *calling, const struct rb_call_info *ci)
{
return rb_obj_method_location(calling->recv, ci->mid);
}
VALUE iseq_location(const rb_iseq_t *iseq);
static inline void
rb_warn_keyword_to_last_hash(struct rb_calling_info *calling, const struct rb_call_info *ci)
rb_warn_keyword_to_last_hash(struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
{
if (calling->recv == Qundef) return;
VALUE loc = get_loc(calling, ci);
VALUE loc = iseq_location(iseq);
if (NIL_P(loc)) {
rb_warn("The keyword argument for `%s' is passed as the last hash parameter", rb_id2name(ci->mid));
}
@ -600,10 +596,10 @@ rb_warn_keyword_to_last_hash(struct rb_calling_info *calling, const struct rb_ca
}
static inline void
rb_warn_split_last_hash_to_keyword(struct rb_calling_info *calling, const struct rb_call_info *ci)
rb_warn_split_last_hash_to_keyword(struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
{
if (calling->recv == Qundef) return;
VALUE loc = get_loc(calling, ci);
VALUE loc = iseq_location(iseq);
if (NIL_P(loc)) {
rb_warn("The last argument for `%s' is split into positional and keyword parameters", rb_id2name(ci->mid));
}
@ -614,10 +610,10 @@ rb_warn_split_last_hash_to_keyword(struct rb_calling_info *calling, const struct
}
static inline void
rb_warn_last_hash_to_keyword(struct rb_calling_info *calling, const struct rb_call_info *ci)
rb_warn_last_hash_to_keyword(struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
{
if (calling->recv == Qundef) return;
VALUE loc = get_loc(calling, ci);
VALUE loc = iseq_location(iseq);
if (NIL_P(loc)) {
rb_warn("The last argument for `%s' is used as the keyword parameter", rb_id2name(ci->mid));
}
@ -770,10 +766,10 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
}
else if (check_only_symbol) {
if (keyword_hash != Qnil) {
rb_warn_split_last_hash_to_keyword(calling, ci);
rb_warn_split_last_hash_to_keyword(calling, ci, iseq);
}
else {
rb_warn_keyword_to_last_hash(calling, ci);
rb_warn_keyword_to_last_hash(calling, ci, iseq);
}
}
}
@ -784,16 +780,16 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
*/
if (ec->cfp->iseq) {
/* called from Ruby level */
rb_warn_last_hash_to_keyword(calling, ci);
rb_warn_last_hash_to_keyword(calling, ci, iseq);
}
given_argc--;
}
else if (keyword_hash != Qnil && ec->cfp->iseq) {
rb_warn_split_last_hash_to_keyword(calling, ci);
rb_warn_split_last_hash_to_keyword(calling, ci, iseq);
}
}
else if (given_argc == min_argc && kw_flag) {
rb_warn_keyword_to_last_hash(calling, ci);
rb_warn_keyword_to_last_hash(calling, ci, iseq);
}
}