Project

General

Profile

Feature #14111 » add_receiver_and_method_name_to_argument_error_for_application_code_2.diff

esjee (SJ Stoker), 12/01/2017 10:59 PM

View differences:

spec/ruby/core/exception/arguments_spec.rb
1 1
require File.expand_path('../../../spec_helper', __FILE__)
2 2

  
3 3
describe "ArgumentError" do
4
  class ArgumentErrorDummyClass
5
    def foo(a,b,c:)
6
    end
7

  
8
    def foo_kw(a:)
9
    end
10
  end
11

  
4 12
  it "is a subclass of StandardError" do
5 13
    StandardError.should be_ancestor_of(ArgumentError)
6 14
  end
......
8 16
  it "gives its own class name as message if it has no message" do
9 17
    ArgumentError.new.message.should == "ArgumentError"
10 18
  end
19

  
20
  describe "arity error" do
21
    it "includes receiver and method name when raised by application code" do
22
      exc = begin
23
        ArgumentErrorDummyClass.new.foo(3)
24
      rescue => exc
25
        exc
26
      end
27

  
28
      exc.instance_variable_get('@receiver').should_not be_nil
29
      exc.instance_variable_get('@receiver').should.class === ArgumentErrorDummyClass
30
      exc.instance_variable_get('@method_name').should == 'foo'
31
    end
32
  end
33

  
34
  describe "kw error" do
35
    it "includes receiver and method name when raised by application code" do
36
      exc = begin
37
        ArgumentErrorDummyClass.new.foo_kw()
38
      rescue => exc
39
        exc
40
      end
41

  
42
      exc.instance_variable_get('@receiver').should_not be_nil
43
      exc.instance_variable_get('@receiver').should.class === ArgumentErrorDummyClass
44
      exc.instance_variable_get('@method_name').should == 'foo'
45
    end
46
  end
11 47
end
vm_args.c
9 9
**********************************************************************/
10 10

  
11 11
NORETURN(static void raise_argument_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const VALUE exc));
12
NORETURN(static void argument_arity_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const int miss_argc, const int min_argc, const int max_argc));
13
NORETURN(static void argument_kw_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const char *error, const VALUE keys));
12
NORETURN(static void argument_arity_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_calling_info *calling, const int miss_argc, const int min_argc, const int max_argc));
13
NORETURN(static void argument_kw_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_calling_info *calling, const char *error, const VALUE keys));
14 14
VALUE rb_keyword_error_new(const char *error, VALUE keys); /* class.c */
15 15
static VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv,
16 16
			    enum method_missing_reason call_status);
......
394 394

  
395 395
static void
396 396
args_setup_kw_parameters(rb_execution_context_t *const ec, const rb_iseq_t *const iseq,
397
			 VALUE *const passed_values, const int passed_keyword_len, const VALUE *const passed_keywords,
397
			 struct rb_calling_info *calling, VALUE *const passed_values,
398
			 const int passed_keyword_len, const VALUE *const passed_keywords,
398 399
			 VALUE *const locals)
399 400
{
400 401
    const ID *acceptable_keywords = iseq->body->param.keyword->table;
......
417 418
	}
418 419
    }
419 420

  
420
    if (missing) argument_kw_error(ec, iseq, "missing", missing);
421
    if (missing) argument_kw_error(ec, iseq, calling, "missing", missing);
421 422

  
422 423
    for (di=0; i<key_num; i++, di++) {
423 424
	if (args_setup_kw_parameters_lookup(acceptable_keywords[i], &locals[i], passed_keywords, passed_values, passed_keyword_len)) {
......
458 459
    else {
459 460
	if (found != passed_keyword_len) {
460 461
	    VALUE keys = make_unknown_kw_hash(passed_keywords, passed_keyword_len, passed_values);
461
	    argument_kw_error(ec, iseq, "unknown", keys);
462
	    argument_kw_error(ec, iseq, calling, "unknown", keys);
462 463
	}
463 464
    }
464 465

  
......
593 594
		args_extend(args, min_argc);
594 595
	    }
595 596
	    else {
596
		argument_arity_error(ec, iseq, given_argc, min_argc, max_argc);
597
		argument_arity_error(ec, iseq, calling, given_argc, min_argc, max_argc);
597 598
	    }
598 599
	}
599 600
    }
......
615 616
	    given_argc = max_argc;
616 617
	}
617 618
	else {
618
	    argument_arity_error(ec, iseq, given_argc, min_argc, max_argc);
619
	    argument_arity_error(ec, iseq, calling, given_argc, min_argc, max_argc);
619 620
	}
620 621
    }
621 622

  
......
641 642

  
642 643
	if (args->kw_argv != NULL) {
643 644
	    const struct rb_call_info_kw_arg *kw_arg = args->kw_arg;
644
	    args_setup_kw_parameters(ec, iseq, args->kw_argv, kw_arg->keyword_len, kw_arg->keywords, klocals);
645
	    args_setup_kw_parameters(ec, iseq, calling, args->kw_argv, kw_arg->keyword_len, kw_arg->keywords, klocals);
645 646
	}
646 647
	else if (!NIL_P(keyword_hash)) {
647 648
	    int kw_len = rb_long2int(RHASH_SIZE(keyword_hash));
......
652 653
	    arg.argc = 0;
653 654
	    rb_hash_foreach(keyword_hash, fill_keys_values, (VALUE)&arg);
654 655
	    VM_ASSERT(arg.argc == kw_len);
655
	    args_setup_kw_parameters(ec, iseq, arg.vals, kw_len, arg.keys, klocals);
656
	    args_setup_kw_parameters(ec, iseq, calling, arg.vals, kw_len, arg.keys, klocals);
656 657
	}
657 658
	else {
658 659
	    VM_ASSERT(args_argc(args) == 0);
659
	    args_setup_kw_parameters(ec, iseq, NULL, 0, NULL, klocals);
660
	    args_setup_kw_parameters(ec, iseq, calling, NULL, 0, NULL, klocals);
660 661
	}
661 662
    }
662 663
    else if (iseq->body->param.flags.has_kwrest) {
663 664
	args_setup_kw_rest_parameter(keyword_hash, locals + iseq->body->param.keyword->rest_start);
664 665
    }
665 666
    else if (!NIL_P(keyword_hash) && RHASH_SIZE(keyword_hash) > 0) {
666
	argument_kw_error(ec, iseq, "unknown", rb_hash_keys(keyword_hash));
667
	argument_kw_error(ec, iseq, calling, "unknown", rb_hash_keys(keyword_hash));
667 668
    }
668 669

  
669 670
    if (iseq->body->param.flags.has_block) {
......
714 715
}
715 716

  
716 717
static void
717
argument_arity_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const int miss_argc, const int min_argc, const int max_argc)
718
argument_arity_error(rb_execution_context_t *ec, const rb_iseq_t *iseq,
719
		     struct rb_calling_info *calling,
720
		     const int miss_argc, const int min_argc, const int max_argc)
718 721
{
719 722
    VALUE exc = rb_arity_error_new(miss_argc, min_argc, max_argc);
720 723
    if (iseq->body->param.flags.has_kw) {
......
735 738
	    RSTRING_PTR(mesg)[RSTRING_LEN(mesg)-1] = ')';
736 739
	}
737 740
    }
741

  
742
    rb_iv_set(exc, "@receiver", calling->recv);
743
    rb_iv_set(exc, "@method_name", rb_iseq_method_name(iseq));
738 744
    raise_argument_error(ec, iseq, exc);
739 745
}
740 746

  
741 747
static void
742
argument_kw_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const char *error, const VALUE keys)
748
argument_kw_error(rb_execution_context_t *ec, const rb_iseq_t *iseq,
749
		  struct rb_calling_info *calling, const char *error,
750
		  const VALUE keys)
743 751
{
744
    raise_argument_error(ec, iseq, rb_keyword_error_new(error, keys));
752
    VALUE exc = rb_keyword_error_new(error, keys);
753
    rb_iv_set(exc, "@receiver", calling->recv);
754
    rb_iv_set(exc, "@method_name", rb_iseq_method_name(iseq));
755
    raise_argument_error(ec, iseq, exc);
745 756
}
746 757

  
747 758
static inline void
vm_insnhelper.c
1608 1608
	CALLER_SETUP_ARG(cfp, calling, ci); /* splat arg */
1609 1609

  
1610 1610
	if (calling->argc != iseq->body->param.lead_num) {
1611
	    argument_arity_error(ec, iseq, calling->argc, iseq->body->param.lead_num, iseq->body->param.lead_num);
1611
	    argument_arity_error(ec, iseq, calling, calling->argc, iseq->body->param.lead_num, iseq->body->param.lead_num);
1612 1612
	}
1613 1613

  
1614 1614
	CI_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size),
......
2593 2593
		}
2594 2594
	    }
2595 2595
	    else {
2596
		argument_arity_error(ec, iseq, calling->argc, iseq->body->param.lead_num, iseq->body->param.lead_num);
2596
		argument_arity_error(ec, iseq, calling, calling->argc, iseq->body->param.lead_num, iseq->body->param.lead_num);
2597 2597
	    }
2598 2598
	}
2599 2599