method_source 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +21 -6
- data/lib/method_source.rb +61 -17
- data/lib/method_source/version.rb +1 -1
- data/test/test.rb +60 -15
- data/test/test_helper.rb +34 -0
- metadata +5 -4
data/README.markdown
CHANGED
@@ -5,23 +5,25 @@ method_source
|
|
5
5
|
|
6
6
|
_retrieve the sourcecode for a method_
|
7
7
|
|
8
|
-
*NOTE:* This
|
9
|
-
|
8
|
+
*NOTE:* This simply utilizes `Method#source_location` in Ruby 1.9; it
|
9
|
+
does not access the live AST.
|
10
10
|
|
11
11
|
`method_source` is a utility to return a method's sourcecode as a
|
12
12
|
Ruby string. Also returns `Proc` and `Lambda` sourcecode.
|
13
13
|
|
14
|
+
Method comments can also be extracted using the `comment` method.
|
15
|
+
|
14
16
|
It is written in pure Ruby (no C).
|
15
17
|
|
16
|
-
`method_source` provides the `source`
|
18
|
+
`method_source` provides the `source` and `comment` methods to the `Method` and
|
17
19
|
`UnboundMethod` and `Proc` classes.
|
18
20
|
|
19
21
|
* Install the [gem](https://rubygems.org/gems/method_source): `gem install method_source`
|
20
22
|
* Read the [documentation](http://rdoc.info/github/banister/method_source/master/file/README.markdown)
|
21
23
|
* See the [source code](http://github.com/banister/method_source)
|
22
24
|
|
23
|
-
Example:
|
24
|
-
|
25
|
+
Example: display method source
|
26
|
+
------------------------------
|
25
27
|
|
26
28
|
Set.instance_method(:merge).source.display
|
27
29
|
# =>
|
@@ -35,10 +37,18 @@ Example: methods
|
|
35
37
|
self
|
36
38
|
end
|
37
39
|
|
40
|
+
Example: display method comments
|
41
|
+
--------------------------------
|
42
|
+
|
43
|
+
Set.instance_method(:merge).comment.display
|
44
|
+
# =>
|
45
|
+
# Merges the elements of the given enumerable object to the set and
|
46
|
+
# returns self.
|
47
|
+
|
38
48
|
Limitations:
|
39
49
|
------------
|
40
50
|
|
41
|
-
* Only works with Ruby 1.9+
|
51
|
+
* Only works with Ruby 1.9+
|
42
52
|
* Cannot return source for C methods.
|
43
53
|
* Cannot return source for dynamically defined methods.
|
44
54
|
|
@@ -49,3 +59,8 @@ Possible Applications:
|
|
49
59
|
for extra fun.
|
50
60
|
|
51
61
|
|
62
|
+
Special Thanks
|
63
|
+
--------------
|
64
|
+
|
65
|
+
[Adam Sanderson](https://github.com/adamsanderson) for `comment` functionality.
|
66
|
+
|
data/lib/method_source.rb
CHANGED
@@ -20,9 +20,8 @@ module MethodSource
|
|
20
20
|
!!Ripper::SexpBuilder.new(code).parse
|
21
21
|
end
|
22
22
|
|
23
|
-
# Helper method responsible for
|
24
|
-
#
|
25
|
-
# class.
|
23
|
+
# Helper method responsible for extracting method body.
|
24
|
+
# Defined here to avoid polluting `Method` class.
|
26
25
|
# @param [Array] source_location The array returned by Method#source_location
|
27
26
|
# @return [File] The opened source file
|
28
27
|
def self.source_helper(source_location)
|
@@ -31,7 +30,44 @@ module MethodSource
|
|
31
30
|
file_name, line = source_location
|
32
31
|
file = File.open(file_name)
|
33
32
|
(line - 1).times { file.readline }
|
34
|
-
|
33
|
+
|
34
|
+
code = ""
|
35
|
+
loop do
|
36
|
+
val = file.readline
|
37
|
+
code << val
|
38
|
+
|
39
|
+
return code if MethodSource.valid_expression?(code)
|
40
|
+
end
|
41
|
+
|
42
|
+
ensure
|
43
|
+
file.close if file
|
44
|
+
end
|
45
|
+
|
46
|
+
# Helper method responsible for opening source file and buffering up
|
47
|
+
# the comments for a specified method. Defined here to avoid polluting
|
48
|
+
# `Method` class.
|
49
|
+
# @param [Array] source_location The array returned by Method#source_location
|
50
|
+
# @return [String] The comments up to the point of the method.
|
51
|
+
def self.comment_helper(source_location)
|
52
|
+
return nil if !source_location.is_a?(Array)
|
53
|
+
|
54
|
+
file_name, line = source_location
|
55
|
+
file = File.open(file_name)
|
56
|
+
buffer = ""
|
57
|
+
(line - 1).times do
|
58
|
+
line = file.readline
|
59
|
+
# Add any line that is a valid ruby comment,
|
60
|
+
# but clear as soon as we hit a non comment line.
|
61
|
+
if (line =~ /^\s*#/) || (line =~ /^\s*$/)
|
62
|
+
buffer << line.lstrip
|
63
|
+
else
|
64
|
+
buffer.clear
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
buffer
|
69
|
+
ensure
|
70
|
+
file.close if file
|
35
71
|
end
|
36
72
|
|
37
73
|
# This module is to be included by `Method` and `UnboundMethod` and
|
@@ -49,26 +85,34 @@ module MethodSource
|
|
49
85
|
# self
|
50
86
|
# end
|
51
87
|
def source
|
52
|
-
file = nil
|
53
|
-
|
54
88
|
if respond_to?(:source_location)
|
55
|
-
|
89
|
+
source = MethodSource.source_helper(source_location)
|
56
90
|
|
57
|
-
raise "Cannot locate source for this method: #{name}" if !
|
91
|
+
raise "Cannot locate source for this method: #{name}" if !source
|
58
92
|
else
|
59
93
|
raise "Method#source not supported by this Ruby version (#{RUBY_VERSION})"
|
60
94
|
end
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
95
|
+
|
96
|
+
source
|
97
|
+
end
|
98
|
+
|
99
|
+
# Return the comments associated with the method as a string.
|
100
|
+
# (This functionality is only supported in Ruby 1.9 and above)
|
101
|
+
# @return [String] The method's comments as a string
|
102
|
+
# @example
|
103
|
+
# Set.instance_method(:clear).comment.display
|
104
|
+
# =>
|
105
|
+
# # Removes all elements and returns self.
|
106
|
+
def comment
|
107
|
+
if respond_to?(:source_location)
|
108
|
+
comment = MethodSource.comment_helper(source_location)
|
66
109
|
|
67
|
-
|
110
|
+
raise "Cannot locate source for this method: #{name}" if !comment
|
111
|
+
else
|
112
|
+
raise "Method#comment not supported by this Ruby version (#{RUBY_VERSION})"
|
68
113
|
end
|
69
|
-
|
70
|
-
|
71
|
-
file.close if file
|
114
|
+
|
115
|
+
comment
|
72
116
|
end
|
73
117
|
end
|
74
118
|
end
|
data/test/test.rb
CHANGED
@@ -2,17 +2,18 @@ direc = File.dirname(__FILE__)
|
|
2
2
|
|
3
3
|
require 'bacon'
|
4
4
|
require "#{direc}/../lib/method_source"
|
5
|
-
|
6
|
-
hello_source = "def hello; :hello; end\n"
|
7
|
-
lambda_source = "MyLambda = lambda { :lambda }\n"
|
8
|
-
proc_source = "MyProc = Proc.new { :proc }\n"
|
9
|
-
|
10
|
-
def hello; :hello; end
|
11
|
-
|
12
|
-
MyLambda = lambda { :lambda }
|
13
|
-
MyProc = Proc.new { :proc }
|
5
|
+
require "#{direc}/test_helper"
|
14
6
|
|
15
7
|
describe MethodSource do
|
8
|
+
|
9
|
+
before do
|
10
|
+
@hello_source = "def hello; :hello; end\n"
|
11
|
+
@hello_comment = "# A comment for hello\n# It spans two lines and is indented by 2 spaces\n"
|
12
|
+
@lambda_comment = "# This is a comment for MyLambda\n"
|
13
|
+
@lambda_source = "MyLambda = lambda { :lambda }\n"
|
14
|
+
@proc_source = "MyProc = Proc.new { :proc }\n"
|
15
|
+
end
|
16
|
+
|
16
17
|
it 'should define methods on Method and UnboundMethod and Proc' do
|
17
18
|
Method.method_defined?(:source).should == true
|
18
19
|
UnboundMethod.method_defined?(:source).should == true
|
@@ -22,7 +23,11 @@ describe MethodSource do
|
|
22
23
|
describe "Methods" do
|
23
24
|
if RUBY_VERSION =~ /1.9/
|
24
25
|
it 'should return source for method' do
|
25
|
-
method(:hello).source.should == hello_source
|
26
|
+
method(:hello).source.should == @hello_source
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should return a comment for method' do
|
30
|
+
method(:hello).comment.should == @hello_comment
|
26
31
|
end
|
27
32
|
|
28
33
|
it 'should raise for C methods' do
|
@@ -30,7 +35,7 @@ describe MethodSource do
|
|
30
35
|
end
|
31
36
|
|
32
37
|
else
|
33
|
-
it 'should raise on #source' do
|
38
|
+
it 'should raise on #source for 1.8' do
|
34
39
|
lambda { method(:hello).source }.should.raise RuntimeError
|
35
40
|
end
|
36
41
|
end
|
@@ -39,16 +44,56 @@ describe MethodSource do
|
|
39
44
|
describe "Lambdas and Procs" do
|
40
45
|
if RUBY_VERSION =~ /1.9/
|
41
46
|
it 'should return source for proc' do
|
42
|
-
MyProc.source.should == proc_source
|
47
|
+
MyProc.source.should == @proc_source
|
43
48
|
end
|
44
|
-
|
49
|
+
|
50
|
+
it 'should return an empty string if there is no comment' do
|
51
|
+
MyProc.comment.should == ''
|
52
|
+
end
|
53
|
+
|
45
54
|
it 'should return source for lambda' do
|
46
|
-
MyLambda.source.should == lambda_source
|
55
|
+
MyLambda.source.should == @lambda_source
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should return comment for lambda' do
|
59
|
+
MyLambda.comment.should == @lambda_comment
|
47
60
|
end
|
48
61
|
else
|
49
|
-
it 'should raise on #source' do
|
62
|
+
it 'should raise on #source for 1.8' do
|
50
63
|
lambda { method(:hello).source }.should.raise RuntimeError
|
51
64
|
end
|
52
65
|
end
|
53
66
|
end
|
67
|
+
|
68
|
+
if RUBY_VERSION =~ /1.9/
|
69
|
+
describe "Comment tests" do
|
70
|
+
before do
|
71
|
+
@comment1 = "# a\n# b\n"
|
72
|
+
@comment2 = "# a\n# b\n"
|
73
|
+
@comment3 = "# a\n#\n# b\n"
|
74
|
+
@comment4 = "# a\n# b\n"
|
75
|
+
@comment5 = "# a\n# b\n# c\n# d\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should correctly extract multi-line comments" do
|
79
|
+
method(:comment_test1).comment.should == @comment1
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should correctly strip leading whitespace before comments" do
|
83
|
+
method(:comment_test2).comment.should == @comment2
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should keep empty comment lines" do
|
87
|
+
method(:comment_test3).comment.should == @comment3
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should ignore blank lines between comments" do
|
91
|
+
method(:comment_test4).comment.should == @comment4
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should align all comments to same indent level" do
|
95
|
+
method(:comment_test5).comment.should == @comment5
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
54
99
|
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# A comment for hello
|
2
|
+
|
3
|
+
# It spans two lines and is indented by 2 spaces
|
4
|
+
def hello; :hello; end
|
5
|
+
|
6
|
+
# a
|
7
|
+
# b
|
8
|
+
def comment_test1; end
|
9
|
+
|
10
|
+
# a
|
11
|
+
# b
|
12
|
+
def comment_test2; end
|
13
|
+
|
14
|
+
# a
|
15
|
+
#
|
16
|
+
# b
|
17
|
+
def comment_test3; end
|
18
|
+
|
19
|
+
# a
|
20
|
+
|
21
|
+
# b
|
22
|
+
def comment_test4; end
|
23
|
+
|
24
|
+
|
25
|
+
# a
|
26
|
+
# b
|
27
|
+
# c
|
28
|
+
# d
|
29
|
+
def comment_test5; end
|
30
|
+
|
31
|
+
# This is a comment for MyLambda
|
32
|
+
MyLambda = lambda { :lambda }
|
33
|
+
MyProc = Proc.new { :proc }
|
34
|
+
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- John Mair (banisterfiend)
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-12-
|
17
|
+
date: 2010-12-18 00:00:00 +13:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- lib/method_source/version.rb
|
31
31
|
- lib/method_source.rb
|
32
32
|
- test/test.rb
|
33
|
+
- test/test_helper.rb
|
33
34
|
- README.markdown
|
34
35
|
- Rakefile
|
35
36
|
has_rdoc: yard
|