summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mair <jrmair@gmail.com>2011-06-01 23:52:49 +1200
committerJohn Mair <jrmair@gmail.com>2011-06-01 23:52:49 +1200
commit51e58be34c4f893efcc74b54412917dec2b657b6 (patch)
treeb722d91b890d1db35b75c3d924f0635e8503a967
parentc111c0e64b646bcd75ce2ed1bd58be3eb9bd63cf (diff)
downloadmethod_source-51e58be34c4f893efcc74b54412917dec2b657b6.tar.gz
added source_location to procs for rbx, all tests passing on rbx
-rw-r--r--lib/method_source.rb37
-rw-r--r--lib/method_source/source_location.rb24
-rw-r--r--test/test.rb29
-rw-r--r--test/test_helper.rb6
4 files changed, 60 insertions, 36 deletions
diff --git a/lib/method_source.rb b/lib/method_source.rb
index 878ddbe..33eeb1f 100644
--- a/lib/method_source.rb
+++ b/lib/method_source.rb
@@ -47,7 +47,7 @@ module MethodSource
# @return [File] The opened source file
def self.source_helper(source_location)
return nil if !source_location.is_a?(Array)
-
+
file_name, line = source_location
File.open(file_name) do |file|
(line - 1).times { file.readline }
@@ -56,26 +56,26 @@ module MethodSource
loop do
val = file.readline
code << val
-
+
return code if valid_expression?(code)
end
- end
+ end
end
-
+
# Helper method responsible for opening source file and buffering up
- # the comments for a specified method. Defined here to avoid polluting
+ # the comments for a specified method. Defined here to avoid polluting
# `Method` class.
# @param [Array] source_location The array returned by Method#source_location
# @return [String] The comments up to the point of the method.
def self.comment_helper(source_location)
return nil if !source_location.is_a?(Array)
-
+
file_name, line = source_location
File.open(file_name) do |file|
buffer = ""
(line - 1).times do
line = file.readline
- # Add any line that is a valid ruby comment,
+ # Add any line that is a valid ruby comment,
# but clear as soon as we hit a non comment line.
if (line =~ /^\s*#/) || (line =~ /^\s*$/)
buffer << line.lstrip
@@ -83,11 +83,11 @@ module MethodSource
buffer.replace("")
end
end
-
+
buffer
end
end
-
+
# This module is to be included by `Method` and `UnboundMethod` and
# provides the `#source` functionality
module MethodExtensions
@@ -103,7 +103,7 @@ module MethodSource
klass.class_eval do
orig_source = instance_method(:source)
-
+
define_method(:source) do
begin
super
@@ -111,11 +111,11 @@ module MethodSource
orig_source.bind(self).call
end
end
-
+
end
end
end
-
+
# Return the sourcecode for the method as a string
# (This functionality is only supported in Ruby 1.9 and above)
# @return [String] The method sourcecode as a string
@@ -129,15 +129,15 @@ module MethodSource
def source
if respond_to?(:source_location)
source = MethodSource.source_helper(source_location)
-
+
raise "Cannot locate source for this method: #{name}" if !source
else
raise "#{self.class}#source not supported by this Ruby version (#{RUBY_VERSION})"
end
-
+
source
end
-
+
# Return the comments associated with the method as a string.
# (This functionality is only supported in Ruby 1.9 and above)
# @return [String] The method's comments as a string
@@ -148,7 +148,7 @@ module MethodSource
def comment
if respond_to?(:source_location)
comment = MethodSource.comment_helper(source_location)
-
+
raise "Cannot locate source for this method: #{name}" if !comment
else
raise "#{self.class}#comment not supported by this Ruby version (#{RUBY_VERSION})"
@@ -171,4 +171,9 @@ end
class Proc
include MethodSource::MethodExtensions
+
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
+ include MethodSource::SourceLocation::ProcExtensions
+ end
end
+
diff --git a/lib/method_source/source_location.rb b/lib/method_source/source_location.rb
index cc7026b..4e078f7 100644
--- a/lib/method_source/source_location.rb
+++ b/lib/method_source/source_location.rb
@@ -4,14 +4,14 @@ module MethodSource
def trace_func(event, file, line, id, binding, classname)
return unless event == 'call'
- set_trace_func nil
-
+ set_trace_func nil
+
@file, @line = file, line
raise :found
end
private :trace_func
-
+
# Return the source location of a method for Ruby 1.8.
# @return [Array] A two element array. First element is the
# file, second element is the line in the file where the
@@ -19,16 +19,28 @@ module MethodSource
def source_location
if @file.nil?
args =[*(1..(arity<-1 ? -arity-1 : arity ))]
-
+
set_trace_func method(:trace_func).to_proc
call(*args) rescue nil
- set_trace_func nil
+ set_trace_func nil
@file = File.expand_path(@file) if @file && File.exist?(File.expand_path(@file))
end
return [@file, @line] if File.exist?(@file.to_s)
end
end
+ # Rubinius only
+ module ProcExtensions
+
+ # Return the source location for a Proc (Rubinius only)
+ # @return [Array] A two element array. First element is the
+ # file, second element is the line in the file where the
+ # proc definition is found.
+ def source_location
+ [block.file.to_s, block.line]
+ end
+ end
+
module UnboundMethodExtensions
# Return the source location of an instance method for Ruby 1.8.
@@ -57,7 +69,7 @@ module MethodSource
when klass == NilClass
return nil.method(name).source_location
end
-
+
begin
klass.allocate.method(name).source_location
rescue TypeError
diff --git a/test/test.rb b/test/test.rb
index 5390de8..334ea82 100644
--- a/test/test.rb
+++ b/test/test.rb
@@ -11,7 +11,7 @@ describe MethodSource do
it 'should return correct source_location for a method' do
method(:hello).source_location.first.should =~ /test_helper/
end
-
+
it 'should not raise for immediate instance methods' do
[Symbol, Fixnum, TrueClass, FalseClass, NilClass].each do |immediate_class|
lambda { immediate_class.instance_method(:to_s).source_location }.should.not.raise
@@ -34,7 +34,7 @@ describe MethodSource do
@lambda_source = "MyLambda = lambda { :lambda }\n"
@proc_source = "MyProc = Proc.new { :proc }\n"
end
-
+
it 'should define methods on Method and UnboundMethod and Proc' do
Method.method_defined?(:source).should == true
UnboundMethod.method_defined?(:source).should == true
@@ -57,35 +57,38 @@ describe MethodSource do
it 'should return source for a singleton method' do
$o.method(:hello).source.should == @hello_singleton_source
end
-
-
+
+
it 'should return a comment for method' do
method(:hello).comment.should == @hello_comment
end
- it 'should raise for C methods' do
- lambda { method(:puts).source }.should.raise RuntimeError
+
+ if !is_rbx?
+ it 'should raise for C methods' do
+ lambda { method(:puts).source }.should.raise RuntimeError
+ end
end
end
- if RUBY_VERSION =~ /1.9/
+ if RUBY_VERSION =~ /1.9/ || is_rbx?
describe "Lambdas and Procs" do
it 'should return source for proc' do
MyProc.source.should == @proc_source
end
-
+
it 'should return an empty string if there is no comment' do
MyProc.comment.should == ''
end
-
+
it 'should return source for lambda' do
MyLambda.source.should == @lambda_source
end
-
+
it 'should return comment for lambda' do
MyLambda.comment.should == @lambda_comment
end
- end
+ end
end
describe "Comment tests" do
before do
@@ -107,13 +110,13 @@ describe MethodSource do
it "should keep empty comment lines" do
method(:comment_test3).comment.should == @comment3
end
-
+
it "should ignore blank lines between comments" do
method(:comment_test4).comment.should == @comment4
end
it "should align all comments to same indent level" do
method(:comment_test5).comment.should == @comment5
- end
+ end
end
end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index ed5fa26..fafc1fb 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -1,3 +1,7 @@
+def is_rbx?
+ defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
+end
+
module M
def hello; :hello_module; end
end
@@ -6,7 +10,7 @@ $o = Object.new
def $o.hello; :hello_singleton; end
# A comment for hello
-
+
# It spans two lines and is indented by 2 spaces
def hello; :hello; end