Skip to content

Commit

Permalink
Allow locations like x.foo where x is not a method and foo is.
Browse files Browse the repository at this point in the history
  • Loading branch information
rocky committed Feb 13, 2011
1 parent 6b6cea0 commit 44998ac
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 8 deletions.
42 changes: 34 additions & 8 deletions app/method_name.rb
Expand Up @@ -11,7 +11,7 @@ module CmdParser
# Name error if we can't find a method. parent_class is the parent class of
# the object we've found so far and "binding" is used if we need
# to use eval to find the method.
def resolve_method(match_data, binding, parent_class = nil)
def resolve_method(match_data, bind, parent_class = nil)
m = match_data
name = m.value.name
errmsg = nil
Expand All @@ -22,16 +22,16 @@ def resolve_method(match_data, binding, parent_class = nil)
else
errmsg = "Constant #{m} is not a class or module"
raise NameError, errmsg unless m.value.chain[0]
klass = eval(m.value.chain[0], binding)
klass = eval(m.value.chain[0], bind)
end
errmsg = "Constant #{klass} is not a class or module" unless
raise NameError, errmsg unless
klass.kind_of?(Class) or klass.kind_of?(Module)
m = m.value.chain[1]
if klass.instance_methods.member?(:binding)
bind = klass.binding
elsif klass.private_instance_methods.member?(:binding)
bind = klass.send(:binding)
if klass.instance_methods.member?(:bind)
bind = klass.bind
elsif klass.private_instance_methods.member?(:bind)
bind = klass.send(:bind)
else
bind = nil
end
Expand All @@ -54,7 +54,28 @@ def resolve_method(match_data, binding, parent_class = nil)
parent_class.method(name)
end
else
eval("self.method(#{name.inspect})", binding)
if child = m.value.chain[1]
parent = m.value.chain[0]
parent_class=eval("#{parent}.class", bind)
raise NameError, "No method eval of #{parent} in allowed" if
parent_class.kind_of?(Method)
is_method =
eval("#{parent}.methods.member?(#{child.to_sym.inspect})",
bind)
if is_method
if child.value.chain[1]
raise NameError, "No method eval past method #{child}"
else
eval("#{parent}.method(#{child.inspect})", bind)
end
elsif parent_class.kind_of?(Constant)
resolve_method(parent, bind, parent_class)
else
raise NameError, "field #{child} of #{parent} is neither a method or a Constant"
end
else
eval("self.method(#{name.inspect})", bind)
end
end
return meth
rescue
Expand Down Expand Up @@ -106,8 +127,8 @@ def meth_for_string(str, start_binding)

def five; 5 end
include Trepan::CmdParser
p meth_for_string('Array.map', binding)
%w(five
Array.map
RubyVM::InstructionSequence.new
Kernel.eval
Kernel::eval).each do |str|
Expand All @@ -120,5 +141,10 @@ def testing; 5 end
end
p meth_for_string('Testing.testing', binding)
p meth_for_string('File.basename', binding)
x = File
p meth_for_string('x.basename', binding)
def x.five; 5; end
p meth_for_string('x.five', binding)
p x.five
end

1 change: 1 addition & 0 deletions data/.gitignore
@@ -0,0 +1 @@
/*~
6 changes: 6 additions & 0 deletions test/unit/test-app-method_name.rb
Expand Up @@ -63,6 +63,12 @@ def five; 5 end
meth = meth_for_string(str, binding)
assert meth.kind_of?(Method), "#{str} method's class should be Method, not #{meth.class}"
end
x = File
def x.five; 5; end
%w(x.basename x.five).each do |str|
meth = meth_for_string(str, binding)
assert meth.kind_of?(Method), "#{str} method's class should be Method, not #{meth.class}"
end
%w(Array.map).each do |str|
meth = meth_for_string(str, binding)
assert meth.kind_of?(UnboundMethod), "#{meth.class}"
Expand Down

0 comments on commit 44998ac

Please sign in to comment.