Module: Boson::ArgumentInspector
- Extended by:
- ArgumentInspector
- Included in:
- ArgumentInspector
- Defined in:
- lib/boson/argument_inspector.rb
Overview
Extracts arguments and their default values from methods either by by scraping a method’s text or with method_added and brute force eval (thanks to eigenclass).
Constant Summary collapse
- MAX_ARGS =
Max number of arguments extracted per method with scrape_with_eval
10
Instance Method Summary collapse
-
#format_arguments(params, values, arity, num_args) ⇒ Object
process params + values to return array of argument arrays.
-
#print_debug_message(klass, meth) ⇒ Object
:nodoc:.
-
#scrape_with_eval(meth, klass, object) ⇒ Object
Scrapes non-private methods for argument names and default values.
-
#trace_method_args(meth, klass, object) ⇒ Object
:nodoc:.
Instance Method Details
#format_arguments(params, values, arity, num_args) ⇒ Object
process params + values to return array of argument arrays
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/boson/argument_inspector.rb', line 32 def format_arguments(params, values, arity, num_args) #:nodoc: params ||= [] params = params[0,num_args] params.inject([[], 0]) do |(a, i), x| if Array === values[i] [a << ["*#{x}"], i+1] else if arity < 0 && i >= arity.abs - 1 [a << [x.to_s, values[i]], i + 1] else [a << [x.to_s], i+1] end end end.first end |
#print_debug_message(klass, meth) ⇒ Object
:nodoc:
27 28 29 |
# File 'lib/boson/argument_inspector.rb', line 27 def (klass, meth) #:nodoc: warn "DEBUG: Error while scraping arguments from #{klass.to_s[/\w+$/]}##{meth}: #{$!.}" end |
#scrape_with_eval(meth, klass, object) ⇒ Object
Scrapes non-private methods for argument names and default values. Returns arguments as array of argument arrays with optional default value as a second element.
Examples:
def meth1(arg1, arg2='val', options={}) -> [['arg1'], ['arg2', 'val'], ['options', {}]]
def meth2(*args) -> [['*args']]
14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/boson/argument_inspector.rb', line 14 def scrape_with_eval(meth, klass, object) unless %w[initialize].include?(meth.to_s) return if class << object; private_instance_methods(true).map {|e| e.to_s } end.include?(meth.to_s) end params, values, arity, num_args = trace_method_args(meth, klass, object) return if local_variables == params # nothing new found format_arguments(params, values, arity, num_args) rescue Exception (klass, meth) if Boson.debug ensure set_trace_func(nil) end |
#trace_method_args(meth, klass, object) ⇒ Object
:nodoc:
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/boson/argument_inspector.rb', line 48 def trace_method_args(meth, klass, object) #:nodoc: file = line = params = values = nil arity = klass.instance_method(meth).arity set_trace_func lambda{|event, file, line, id, binding, classname| begin if event[/call/] && classname == klass && id == meth params = eval("local_variables", binding) values = eval("local_variables.map{|x| eval(x.to_s)}", binding) throw :done end rescue Exception (klass, meth) if Boson.debug end } if arity >= 0 num_args = arity catch(:done){ object.send(meth, *(0...arity)) } else num_args = 0 # determine number of args (including splat & block) MAX_ARGS.downto(arity.abs - 1) do |i| catch(:done) do begin object.send(meth, *(0...i)) rescue Exception end end # all nils if there's no splat and we gave too many args next if !values || values.compact.empty? k = nil values.each_with_index{|x,j| break (k = j) if Array === x} num_args = k ? k+1 : i break end args = (0...arity.abs-1).to_a catch(:done) do args.empty? ? object.send(meth) : object.send(meth, *args) end end set_trace_func(nil) return [params, values, arity, num_args] end |