public
Description: master merb branch
Homepage: http://www.merbivore.com
Clone URL: git://github.com/wycats/merb.git
merb / merb-action-args / lib / merb-action-args / jruby_args.rb
100644 67 lines (53 sloc) 1.689 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
require 'java'
require 'jruby'
 
module GetArgs
  Methods = org.jruby.internal.runtime.methods
 
  def get_args
    real_method = JRuby.reference(self)
 
    # hack to expose a protected field; could be improved in 1.1.5
    method_field = org.jruby.RubyMethod.java_class.declared_field(:method)
 
    method_field.accessible = true
  
    dyn_method = method_field.value(real_method)
 
    case dyn_method
    when Methods.MethodArgs
      return build_args(dyn_method.args_node)
    else
      raise "Can't get args from method: #{self}"
    end
  end
 
  def build_args(args_node)
    args = []
    required = []
    optional = []
 
    # required args
    if (args_node.args && args_node.args.size > 0)
      required << args_node.args.child_nodes.map { |arg| [arg.name.to_s.intern] }
    end
  
    # optional args
    if (args_node.opt_args && args_node.opt_args.size > 0)
      optional << args_node.opt_args.child_nodes.map do |arg|
        name = arg.name.to_s.intern
        value_node = arg.value_node
        case value_node
        when org.jruby.ast::FixnumNode
          value = value_node.value
        when org.jruby.ast::SymbolNode
          value = value_node.get_symbol(JRuby.runtime)
        when org.jruby.ast::StrNode
          value = value_node.value
        else
          value = nil
        end
        [name, value]
      end
    end
 
    first_args = required.first
    optional.first.each {|arg| first_args << arg} if optional.first
        
    args = [first_args]
    
    rest = args_node.rest_arg_node
    args << (rest ? rest.name.to_s.intern : nil)
  
    block = args_node.block_arg_node
    args << (block ? block.name.to_s.intern : nil)
 
    args
  end
end