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.
@@ -5,23 +5,25 @@ method_source
5
5
 
6
6
  _retrieve the sourcecode for a method_
7
7
 
8
- *NOTE:* This is nothing fancy; it simply utilizes `Method#source_location`
9
- in Ruby 1.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` method to the `Method` and
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: methods
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+ (YARV)
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
+
@@ -20,9 +20,8 @@ module MethodSource
20
20
  !!Ripper::SexpBuilder.new(code).parse
21
21
  end
22
22
 
23
- # Helper method responsible for opening source file and advancing to
24
- # the correct linenumber. Defined here to avoid polluting `Method`
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
- file
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
- file = MethodSource.source_helper(source_location)
89
+ source = MethodSource.source_helper(source_location)
56
90
 
57
- raise "Cannot locate source for this method: #{name}" if !file
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
- code = ""
63
- loop do
64
- val = file.readline
65
- code += val
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
- return code if MethodSource.valid_expression?(code)
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
- ensure
71
- file.close if file
114
+
115
+ comment
72
116
  end
73
117
  end
74
118
  end
@@ -1,3 +1,3 @@
1
1
  module MethodSource
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -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
@@ -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
- - 1
8
- - 4
9
- version: 0.1.4
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 00:00:00 +13:00
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