sourcify 0.3.0 → 0.4.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.
Files changed (69) hide show
  1. data/.infinity_test +32 -0
  2. data/HISTORY.txt +12 -0
  3. data/README.rdoc +69 -30
  4. data/Rakefile +2 -3
  5. data/VERSION +1 -1
  6. data/lib/sourcify.rb +2 -2
  7. data/lib/sourcify/proc.rb +144 -65
  8. data/lib/sourcify/proc/methods.rb +3 -0
  9. data/lib/sourcify/proc/methods/source_location.rb +61 -0
  10. data/lib/sourcify/proc/methods/to_sexp.rb +40 -0
  11. data/lib/sourcify/proc/methods/to_source.rb +48 -0
  12. data/lib/sourcify/proc/parser.rb +36 -17
  13. data/lib/sourcify/proc/scanner.rb +317 -271
  14. data/lib/sourcify/proc/scanner.rl +13 -2
  15. data/lib/sourcify/proc/scanner/extensions.rb +34 -10
  16. data/sourcify.gemspec +36 -6
  17. data/spec/proc/created_on_the_fly_proc_spec.rb +1 -1
  18. data/spec/proc/others_spec.rb +6 -2
  19. data/spec/proc/spec_helper.rb +1 -0
  20. data/spec/proc/to_sexp_from_multi_blocks_w_specified_attached_to_spec.rb +46 -0
  21. data/spec/proc/to_sexp_variables_spec.rb +1 -1
  22. data/spec/proc/to_sexp_w_specified_strip_enclosure_spec.rb +60 -0
  23. data/spec/proc/to_sexp_within_irb_spec.rb +1 -1
  24. data/spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb +1 -1
  25. data/spec/proc/to_source_from_braced_block_w_nested_hash_spec.rb +2 -2
  26. data/spec/proc/to_source_from_braced_block_wo_nesting_complication_spec.rb +1 -1
  27. data/spec/proc/to_source_from_do_end_block_w_nested_begin_spec.rb +1 -1
  28. data/spec/proc/to_source_from_do_end_block_w_nested_case_spec.rb +1 -1
  29. data/spec/proc/to_source_from_do_end_block_w_nested_class_spec.rb +1 -1
  30. data/spec/proc/to_source_from_do_end_block_w_nested_do_end_block_spec.rb +1 -1
  31. data/spec/proc/to_source_from_do_end_block_w_nested_for_spec.rb +1 -1
  32. data/spec/proc/to_source_from_do_end_block_w_nested_if_spec.rb +1 -1
  33. data/spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb +1 -1
  34. data/spec/proc/to_source_from_do_end_block_w_nested_method_spec.rb +1 -1
  35. data/spec/proc/to_source_from_do_end_block_w_nested_module_spec.rb +1 -1
  36. data/spec/proc/to_source_from_do_end_block_w_nested_unless_spec.rb +1 -1
  37. data/spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb +1 -1
  38. data/spec/proc/to_source_from_do_end_block_w_nested_while_spec.rb +1 -1
  39. data/spec/proc/to_source_from_do_end_block_wo_nesting_complication_spec.rb +1 -1
  40. data/spec/proc/to_source_from_multi_blocks_w_many_matches_spec.rb +20 -126
  41. data/spec/proc/to_source_from_multi_blocks_w_single_match_spec.rb +10 -89
  42. data/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_many_matches_spec.rb +45 -0
  43. data/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_no_match_spec.rb +45 -0
  44. data/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_single_match_spec.rb +22 -0
  45. data/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_spec.rb +83 -0
  46. data/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_many_matches_spec.rb +45 -0
  47. data/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_no_match_spec.rb +45 -0
  48. data/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_single_match_spec.rb +22 -0
  49. data/spec/proc/to_source_from_multi_blocks_w_specified_ignore_nested_spec.rb +43 -0
  50. data/spec/proc/to_source_from_multi_do_end_blocks_w_single_match_spec.rb +1 -1
  51. data/spec/proc/to_source_magic_file_var_spec.rb +1 -1
  52. data/spec/proc/to_source_magic_line_var_spec.rb +1 -1
  53. data/spec/proc/to_source_variables_spec.rb +1 -1
  54. data/spec/proc/to_source_w_specified_strip_enclosure_spec.rb +33 -0
  55. data/spec/proc/to_source_within_irb_spec.rb +1 -1
  56. data/spec/proc_scanner/block_comment_spec.rb +1 -1
  57. data/spec/proc_scanner/double_colons_spec.rb +1 -1
  58. data/spec/proc_scanner/double_quote_str_w_interpolation_spec.rb +9 -9
  59. data/spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb +13 -13
  60. data/spec/proc_scanner/heredoc_spec.rb +1 -1
  61. data/spec/proc_scanner/kw_do_alias1_spec.rb +1 -1
  62. data/spec/proc_scanner/kw_do_alias2_spec.rb +1 -1
  63. data/spec/proc_scanner/per_line_comment_spec.rb +1 -1
  64. data/spec/proc_scanner/single_quote_str_spec.rb +1 -1
  65. data/spec/proc_scanner/slash_operator_spec.rb +75 -0
  66. data/spec/proc_scanner/spec_helper.rb +1 -1
  67. data/spec/spec_helper.rb +53 -45
  68. metadata +46 -16
  69. data/ext/sourcify/extconf.rb +0 -2
@@ -0,0 +1,32 @@
1
+ # Hacking RVM
2
+ module RVM
3
+ module Shell
4
+ class AbstractWrapper
5
+ def raw_stdout_to_parts(c)
6
+ raise IncompleteCommandError if !command_complete?(c)
7
+ before, after = c.split(COMMAND_EPILOG_START, 2)
8
+ epilog, after = after.split(COMMAND_EPILOG_END, 2)
9
+ # HACK .. need to apply gsub to prevent yaml-related error
10
+ return before, YAML.load(epilog.strip.gsub("\\\"\n","\"\n")), after
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ # See http://github.com/tomas-stefano/infinity_test/wiki/Customize-Infinity-Test
17
+ infinity_test do
18
+
19
+ # Sets bacon mute to avoid excessive noise that makes it hard to pinpoint errors
20
+ ENV['MUTE_BACON'] = 'true'
21
+
22
+ use \
23
+ :test_framework => :bacon,
24
+ :rubies => %w(
25
+ ruby-1.8.6-p399@parsetree
26
+ ruby-1.8.7-p302
27
+ ree-1.8.7-2010.02
28
+ ruby-1.9.1-p376
29
+ ruby-1.9.2-p0
30
+ jruby-1.5.3
31
+ )
32
+ end
@@ -1,3 +1,15 @@
1
+ === 0.4.0 (Oct 15, 2010)
2
+
3
+ * adds Proc#to_source(:strip_enclosure => ...) (& the Proc#to_sexp equivalent) to ease
4
+ stripping of enclosing 'proc {|params| ... }', returning only the inner code body
5
+ '...' [#ngty]
6
+ * adds Proc#to_source(:attached_to => ..., :ignore_nested => ..., &body_matcher) (& the
7
+ Proc#to_sexp equivalent) to narrow down code scanning, avoiding unnecessary
8
+ Sourcify::MultipleMatchingProcsPerLineError, useful for libs that can anticipate
9
+ how the proc should look like [#ngty]
10
+ * adds support for running in MRI-1.9.2 [#ngty]
11
+ * fixes '/' operator always treated as start of regexp [#ngty & #seamusabshere]
12
+
1
13
  === 0.3.0 (Sep 23, 2010)
2
14
 
3
15
  * Proc#to_source & friends now work in IRB as well [#ngty]
@@ -5,7 +5,8 @@ ParseTree[http://github.com/seattlerb/parsetree] is great, it accesses the runti
5
5
  S-expression, BUT ParseTree doesn't work for 1.9.* & JRuby.
6
6
 
7
7
  RubyParser[http://github.com/seattlerb/ruby_parser] is great, and it works for any rubies
8
- (of course, not 100% compatible for 1.9.* syntax yet), BUT it works only with static code.
8
+ (of course, not 100% compatible for 1.8.7 & 1.9.* syntax yet), BUT it works only with
9
+ static code.
9
10
 
10
11
  I truely enjoy using the above tools, but with my other projects, the absence of ParseTree
11
12
  on the different rubies is forcing me to hand-baked my own solution each time to extract
@@ -14,8 +15,8 @@ never perfect, and i'm reinventing the wheel each time just to address a particu
14
15
  pattern of usage (using regexp kungfu).
15
16
 
16
17
  Enough is enough, and now we have Sourcify, a unified solution to extract proc code.
17
- When ParseTree is available, it simply works as a wrapper round it, otherwise, it uses
18
- a home-baked ragel-generated scanner to extract the proc code. Further processing
18
+ When ParseTree is available, it simply works as a thin wrapper round it, otherwise, it
19
+ uses a home-baked ragel-generated scanner to extract the proc code. Further processing
19
20
  with RubyParser & Ruby2Ruby to ensure 100% with ParseTree (yup, there is no denying that
20
21
  i really like ParseTree).
21
22
 
@@ -39,29 +40,40 @@ Returns the code representation of the proc:
39
40
 
40
41
  require 'sourcify'
41
42
 
42
- proc1 = lambda { x + y }
43
- puts proc1.to_source # proc { (x + y) }
43
+ lambda { x + y }.to_source
44
+ # >> "proc { (x + y) }"
44
45
 
45
- proc2 = proc { x + y }
46
- puts proc2.to_source # proc { (x + y) }
46
+ proc { x + y }.to_source
47
+ # >> "proc { (x + y) }"
47
48
 
48
49
  Like it or not, a lambda is represented as a proc when converted to source (exactly the
49
- same way as ParseTree).
50
+ same way as ParseTree). It is possible to only extract the body of the proc by passing
51
+ in {:strip_enclosure => true}:
52
+
53
+ lambda { x + y }.to_source(:strip_enclosure => true)
54
+ # >> "(x + y)"
55
+
56
+ lambda {|i| i + 2 }.to_source(:strip_enclosure => true)
57
+ # >> "(i + 2)"
50
58
 
51
59
  === 2. Proc#to_sexp
52
60
 
53
61
  Returns the S-expression of the proc:
54
62
 
55
63
  require 'sourcify'
56
- require 'pp'
57
64
 
58
65
  x = 1
59
- pp lambda { x + y }.to_sexp
66
+ lambda { x + y }.to_sexp
60
67
  # >> s(:iter,
61
68
  # >> s(:call, nil, :proc, s(:arglist)),
62
69
  # >> nil,
63
70
  # >> s(:call, s(:lvar, :x), :+, s(:arglist, s(:call, nil, :y, s(:arglist)))))
64
71
 
72
+ To extract only the body of the proc:
73
+
74
+ lambda { x + y }.to_sexp(:strip_enclosure => true)
75
+ # >> s(:call, s(:lvar, :x), :+, s(:arglist, s(:call, nil, :y, s(:arglist)))))
76
+
65
77
  === 3. Proc#source_location
66
78
 
67
79
  By default, this is only available on 1.9.*, it is added (as a bonus) to provide
@@ -69,9 +81,8 @@ consistency under 1.8.*:
69
81
 
70
82
  # /tmp/test.rb
71
83
  require 'sourcify'
72
- require 'pp'
73
84
 
74
- pp lambda { x + y }.source_location
85
+ lambda { x + y }.source_location
75
86
  # >> ["/tmp/test.rb", 5]
76
87
 
77
88
  == Performance
@@ -105,10 +116,10 @@ will not work:
105
116
  eval('lambda { x + y }')
106
117
  end
107
118
 
108
- pp test.source_location
119
+ test.source_location
109
120
  # >> ["(eval)", 1]
110
121
 
111
- puts test.to_source
122
+ test.to_source
112
123
  # >> Sourcify::CannotParseEvalCodeError
113
124
 
114
125
  The same applies to *Blah#to_proc* & *&:blah*:
@@ -131,7 +142,7 @@ subject proc has arity that is unique from others:
131
142
 
132
143
  # Yup, this works as expected :)
133
144
  b1 = lambda {|a| a+1 }; b2 = lambda { 1+2 }
134
- puts b2.to_source
145
+ b2.to_source
135
146
  # >> proc { (1 + 2) }
136
147
 
137
148
  # Nope, this won't work :(
@@ -139,33 +150,56 @@ subject proc has arity that is unique from others:
139
150
  b2.to_source
140
151
  # >> raises Sourcify::MultipleMatchingProcsPerLineError
141
152
 
142
- Using Proc#arity is a pretty good way to uniquely identify the subject proc, since having
143
- too many procs per line is not a good practice as it reduces readability. However, the
144
- following bug[http://redmine.ruby-lang.org/issues/show/574] under 1.8.* may trip u over:
153
+ As observed, the above does not work when there are multiple procs having the same arity,
154
+ on the same line. Furthermore, this bug[http://redmine.ruby-lang.org/issues/show/574]
155
+ under 1.8.* affects the accuracy of this approach.
156
+
157
+ To better narrow down the scanning, try:
158
+
159
+ * passing in the {:attached_to => ...} option
160
+
161
+ x = lambda { proc { :blah } }
162
+
163
+ x.to_source
164
+ # >> Sourcify::MultipleMatchingProcsPerLineError
165
+
166
+ x.to_source(:attached_to => :lambda)
167
+ # >> "proc { proc { :blah } }"
145
168
 
146
- lambda { }.arity # 1.8.* (-1) / 1.9.* (0) (?!)
147
- lambda {|| }.arity # 1.8.* (0) / 1.9.* (0)
148
- lambda {|x| }.arity # 1.8.* (1) / 1.9.* (1)
149
- lambda {|x,y| }.arity # 1.8.* (2) / 1.9.* (2)
150
- lambda {|*x| }.arity # 1.8.* (-1) / 1.9.* (-1)
151
- lambda {|x, *y| }.arity # 1.8.* (-2) / 1.9.* (-2)
152
- lambda {|(x,y)| }.arity # 1.8.* (1) / 1.9.* (1)
169
+ * passing in the {:ignore_nested => ...} option
153
170
 
154
- This is another reason to install ParseTree when u are on 1.8.*. On JRuby, where u don't
155
- have the choice, just avoid multiple procs per line.
171
+ x = lambda { lambda { :blah } }
172
+
173
+ x.to_source
174
+ # >> Sourcify::MultipleMatchingProcsPerLineError
175
+
176
+ x.to_source(:ignore_nested => true)
177
+ # >> "proc { lambda { :blah } }"
178
+
179
+ * attaching a body matcher proc
180
+
181
+ x, y = lambda { def secret; 1; end }, lambda { :blah }
182
+
183
+ x.to_source
184
+ # >> Sourcify::MultipleMatchingProcsPerLineError
185
+
186
+ x.to_source{|body| body =~ /^(.*\W|)def\W/ }
187
+ # >> 'proc { def secret; 1; end }'
188
+
189
+ Pls refer to the rdoc for more details.
156
190
 
157
191
  === 3. Occasional Racc::ParseError
158
192
 
159
193
  Under the hood, sourcify relies on RubyParser to yield s-expression, and since RubyParser
160
- does not yet fully handle 1.8.7/1.9.* syntax, you will get a nasty Racc::ParseError when
194
+ does not yet fully handle 1.8.7 & 1.9.* syntax, you will get a nasty Racc::ParseError when
161
195
  you have any code that is not compatible with 1.8.6.
162
196
 
163
- == Is it working ??
197
+ == Is it really working ??
164
198
 
165
199
  Sourcify spec suite currently passes in the following rubies:
166
200
  * MRI-1.8.6 (ParseTree mode ONLY)
167
201
  * MRI-1.8.7, REE-1.8.7 (ParseTree & static scanner modes)
168
- * JRuby-1.5.1+, MRI-1.9.1 (static scanner ONLY)
202
+ * JRuby-1.5.1+, MRI-1.9.1, MRI-1.9.2 (static scanner ONLY)
169
203
 
170
204
  Besides its own spec suite, sourcify has also been tested to handle:
171
205
 
@@ -177,6 +211,11 @@ For projects:
177
211
 
178
212
  (TODO: the more the merrier)
179
213
 
214
+ == Projects using it
215
+
216
+ Projects using sourcify include:
217
+ * wrong[http://github.com/sconover/wrong]
218
+
180
219
  == Additional Resources
181
220
 
182
221
  Sourcify is heavily inspired by many ideas gathered from the ruby community:
data/Rakefile CHANGED
@@ -13,16 +13,15 @@ begin
13
13
  gem.authors = ["NgTzeYang"]
14
14
  gem.required_ruby_version = '>= 1.8.6'
15
15
  gem.add_dependency 'ruby2ruby', '>= 1.2.5'
16
+ gem.add_dependency "sexp_processor", ">= 3.0.5"
16
17
  gem.add_development_dependency "bacon", ">= 0"
17
- gem.add_development_dependency "otaku", ">= 0.4.0"
18
18
  # Plus one of the following groups:
19
19
  #
20
20
  # 1). ParseTree (better performance + dynamic goodness, but not supported on java & 1.9.*)
21
21
  # >> gem.add_dependency "ParseTree", ">= 3.0.6"
22
22
  #
23
- # 2). RubyParser (supported for all)
23
+ # 2). RubyParser (supported for all except 1.8.6)
24
24
  # >> gem.add_dependency "ruby_parser", ">= 2.0.5"
25
- # >> gem.add_dependency "sexp_processor", ">= 3.0.5"
26
25
  # >> gem.add_dependency "file-tail", ">= 1.0.5"
27
26
  end
28
27
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'ruby2ruby'
3
+ require 'sexp_processor'
3
4
 
4
5
  begin
5
6
  require 'parse_tree'
@@ -7,11 +8,10 @@ begin
7
8
  rescue LoadError
8
9
  raise if RUBY_VERSION == '1.8.6' # support for code scanner in 1.8.6 is too tedious
9
10
  require 'ruby_parser'
10
- require 'sexp_processor'
11
11
  require 'file/tail'
12
12
  end
13
13
 
14
- module Sourcify
14
+ module Sourcify #:nodoc:
15
15
  class << self
16
16
 
17
17
  def require_rb(*args)
@@ -1,85 +1,164 @@
1
1
  module Sourcify
2
2
 
3
3
  class MultipleMatchingProcsPerLineError < Exception; end
4
+ class NoMatchingProcError < Exception; end
4
5
  class ParserInternalError < Exception; end
5
6
  class CannotParseEvalCodeError < Exception; end
6
7
  class CannotHandleCreatedOnTheFlyProcError < Exception; end
7
8
 
8
9
  module Proc
9
- def self.included(base)
10
- base.class_eval do
11
-
12
- ref_proc = lambda {}
13
-
14
- # == Proc#source_location
15
-
16
- unless ref_proc.respond_to?(:source_location)
17
-
18
- # Added as a bonus, by default, only 1.9.* implements this.
19
- def source_location
20
- unless created_on_the_fly?
21
- @source_location ||= (
22
- file, line = /^#<Proc:0x[0-9A-Fa-f]+@(.+):(\d+).*?>$/.match(inspect)[1..2]
23
- [file, line.to_i]
24
- )
25
- end
26
- end
27
-
28
- # HACK to make it easy to determine if a proc is created on the fly
29
- ::Proc.class_eval do
30
- attr_writer :created_on_the_fly
31
- def created_on_the_fly?
32
- !!@created_on_the_fly
33
- end
34
- end
35
-
36
- [::Method, ::Symbol].each do |klass|
37
- begin
38
- klass.class_eval do
39
- alias_method :__pre_sourcified_to_proc, :to_proc
40
- def to_proc
41
- (_proc = __pre_sourcified_to_proc).created_on_the_fly = true
42
- _proc
43
- end
44
- end
45
- rescue NameError
46
- end
47
- end
48
-
49
- end
50
-
51
- # == Proc#to_source
52
-
53
- if Object.const_defined?(:ParseTree)
54
10
 
55
- # When ParseTree is available, we just make use of all the convenience it offers :)
56
- alias_method :to_source, :to_ruby
57
-
58
- elsif !ref_proc.respond_to?(:to_source)
59
-
60
- # Otherwise, we are going to do abit of static text parsing :(
61
- def to_source
62
- Sourcify.require_rb('proc', 'parser')
63
- (@parser ||= Parser.new(self)).source
64
- end
65
-
66
- end
11
+ def self.included(base) #:nodoc:
12
+ base.class_eval do
13
+ Sourcify.require_rb('proc', 'methods')
14
+ include Methods::SourceLocation
15
+ include Methods::ToSource
16
+ include Methods::ToSexp
17
+ end
18
+ end
67
19
 
68
- # == Proc#to_sexp
20
+ module Stubs
21
+
22
+ ###
23
+ # Returns the ruby source filename and line number containing this proc.
24
+ #
25
+ # # /tmp/test.rb
26
+ # x = lambda { 1 }
27
+ # x.source_location # >> ["/tmp/test.rb", 2]
28
+ #
29
+ # When proc is not defined in ruby (i.e. native), or when the proc is created using
30
+ # Method#to_proc or Symbol#to_proc, nil is returned.
31
+ #
32
+ # class AA
33
+ # class << self
34
+ # def m1; 1; end
35
+ # def m2(&block); block; end
36
+ # end
37
+ # end
38
+ #
39
+ # AA.method(:m1).to_proc.source_location # >> nil
40
+ # AA.m2(&:m1).source_location # >> nil
41
+ #
42
+ # For 1.9.2, the proc obtained using Method#to_proc by default yields info pointing
43
+ # to where the method is located. Sourcify respects this builtin implementation and
44
+ # assumes you usually want it. It is possible to get info that is consistent with all
45
+ # other rubies by passing in +get_original+ as false:
46
+ #
47
+ # # /tmp/test.rb
48
+ # class AA
49
+ # def m; 1; end
50
+ # end
51
+ #
52
+ # x = AA.new.method(:m).to_proc
53
+ # x.source_location # >> ["/tmp/test.rb", 2]
54
+ # x.source_location(false) # >> nil
55
+ #
56
+ def source_location(get_original = true)
57
+ # NOTE: this is a stub for the actual one in Methods::SourceLocation
58
+ end
69
59
 
70
- unless ref_proc.respond_to?(:to_sexp)
71
- def to_sexp
72
- Sourcify.require_rb('proc', 'parser')
73
- (@parser ||= Parser.new(self)).sexp
74
- end
75
- end
60
+ ###
61
+ # Returns the code representation of this proc.
62
+ #
63
+ # lambda {|i| i+1 }.to_source
64
+ # # >> "proc {|i| i+1 }"
65
+ #
66
+ # The following options are supported:
67
+ #
68
+ # * +:strip_enclosure+ when set to true, strips the enclosing "proc { ... }" to get
69
+ # just the meat within.
70
+ #
71
+ # lambda {|i| i+1 }.to_source(:strip_enclosure => true)
72
+ # # >> "i+2"
73
+ #
74
+ # (this option is effective regardless of presence of ParseTree)
75
+ #
76
+ # * +:attached_to+ is useful to avoid the nasty
77
+ # Sourcify::MultipleMatchingProcsPerLineError (as a result of ambiguities when doing
78
+ # static code analysis), it declares the condition that must be met prior grabbing
79
+ # the code block:
80
+ #
81
+ # x = lambda { proc { :blah } }
82
+ #
83
+ # x.to_source
84
+ # # >> Sourcify::MultipleMatchingProcsPerLineError
85
+ #
86
+ # x.to_source(:attached_to => :lambda)
87
+ # # >> "proc { proc { :blah } }"
88
+ #
89
+ # Sometimes more control is needed:
90
+ #
91
+ # # We want to ignore everything associated with ignore
92
+ # def ignore(&block); block; end
93
+ # x = lambda { ignore { :blah } }
94
+ #
95
+ # x.to_source
96
+ # # >> Sourcify::MultipleMatchingProcsPerLineError
97
+ #
98
+ # x.to_source(:attached_to => /^(.*\W|)(lambda|proc)\W/)
99
+ # # >> "proc { ignore { :blah } }"
100
+ #
101
+ # (this option is effective ONLY when ParseTree is not available)
102
+ #
103
+ # * +:ignore_nested+ is useful when only the outermost proc matters and we want to
104
+ # ignore all other nested proc(s):
105
+ #
106
+ # x = lambda { lambda { :blah } }
107
+ #
108
+ # x.to_source
109
+ # # >> Sourcify::MultipleMatchingProcsPerLineError
110
+ #
111
+ # x.to_source(:ignore_nested => true)
112
+ # # >> "proc { lambda { :blah } }"
113
+ #
114
+ # However, since code scanning stops at the outermost proc, beware of the following:
115
+ #
116
+ # x = lambda {|_| lambda { lambda { :blah } } }.call(nil)
117
+ #
118
+ # x.to_source
119
+ # # >> "proc { lambda { :blah } }"
120
+ #
121
+ # x.to_source(:ignore_nested => true)
122
+ # # >> Sourcify::NoMatchingProcError
123
+ #
124
+ # (this option is effective ONLY when ParseTree is not available)
125
+ #
126
+ # When in static code analysis (non-ParseTree) mode, it is even possible to
127
+ # specify how the proc body should look like by passing in a code block:
128
+ #
129
+ # x, y = lambda { def secret; 1; end }, lambda { :blah }
130
+ #
131
+ # x.to_source
132
+ # # >> Sourcify::MultipleMatchingProcsPerLineError
133
+ #
134
+ # x.to_source{|body| body =~ /^(.*\W|)def\W/ }
135
+ # # >> "proc { def secret; 1; end }"
136
+ #
137
+ def to_source(opts={}, &body_matcher)
138
+ # NOTE: this is a stub for the actual one in Methods::ToSource
139
+ end
76
140
 
141
+ ###
142
+ # Returns the S-expression representation of this proc.
143
+ #
144
+ # lambda {|i| i+1 }.to_sexp
145
+ # # >> s(:iter,
146
+ # # >> s(:call, nil, :proc, s(:arglist)),
147
+ # # >> s(:lasgn, :i),
148
+ # # >> s(:call, s(:lvar, :i), :+, s(:arglist, s(:lit, 1))))
149
+ #
150
+ # (pls see #to_source for options/arguments supported)
151
+ #
152
+ def to_sexp(opts={}, &body_matcher)
153
+ # NOTE: this is a stub for the actual one in Methods::ToSexp
77
154
  end
155
+
78
156
  end
157
+
79
158
  end
80
159
 
81
160
  end
82
161
 
83
- ::Proc.class_eval do
162
+ Proc.class_eval do
84
163
  include Sourcify::Proc
85
164
  end