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.
- data/.infinity_test +32 -0
- data/HISTORY.txt +12 -0
- data/README.rdoc +69 -30
- data/Rakefile +2 -3
- data/VERSION +1 -1
- data/lib/sourcify.rb +2 -2
- data/lib/sourcify/proc.rb +144 -65
- data/lib/sourcify/proc/methods.rb +3 -0
- data/lib/sourcify/proc/methods/source_location.rb +61 -0
- data/lib/sourcify/proc/methods/to_sexp.rb +40 -0
- data/lib/sourcify/proc/methods/to_source.rb +48 -0
- data/lib/sourcify/proc/parser.rb +36 -17
- data/lib/sourcify/proc/scanner.rb +317 -271
- data/lib/sourcify/proc/scanner.rl +13 -2
- data/lib/sourcify/proc/scanner/extensions.rb +34 -10
- data/sourcify.gemspec +36 -6
- data/spec/proc/created_on_the_fly_proc_spec.rb +1 -1
- data/spec/proc/others_spec.rb +6 -2
- data/spec/proc/spec_helper.rb +1 -0
- data/spec/proc/to_sexp_from_multi_blocks_w_specified_attached_to_spec.rb +46 -0
- data/spec/proc/to_sexp_variables_spec.rb +1 -1
- data/spec/proc/to_sexp_w_specified_strip_enclosure_spec.rb +60 -0
- data/spec/proc/to_sexp_within_irb_spec.rb +1 -1
- data/spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb +1 -1
- data/spec/proc/to_source_from_braced_block_w_nested_hash_spec.rb +2 -2
- data/spec/proc/to_source_from_braced_block_wo_nesting_complication_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_begin_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_case_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_class_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_do_end_block_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_for_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_if_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_method_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_module_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_unless_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_w_nested_while_spec.rb +1 -1
- data/spec/proc/to_source_from_do_end_block_wo_nesting_complication_spec.rb +1 -1
- data/spec/proc/to_source_from_multi_blocks_w_many_matches_spec.rb +20 -126
- data/spec/proc/to_source_from_multi_blocks_w_single_match_spec.rb +10 -89
- data/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_many_matches_spec.rb +45 -0
- data/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_no_match_spec.rb +45 -0
- data/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_single_match_spec.rb +22 -0
- data/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_spec.rb +83 -0
- data/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_many_matches_spec.rb +45 -0
- data/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_no_match_spec.rb +45 -0
- data/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_single_match_spec.rb +22 -0
- data/spec/proc/to_source_from_multi_blocks_w_specified_ignore_nested_spec.rb +43 -0
- data/spec/proc/to_source_from_multi_do_end_blocks_w_single_match_spec.rb +1 -1
- data/spec/proc/to_source_magic_file_var_spec.rb +1 -1
- data/spec/proc/to_source_magic_line_var_spec.rb +1 -1
- data/spec/proc/to_source_variables_spec.rb +1 -1
- data/spec/proc/to_source_w_specified_strip_enclosure_spec.rb +33 -0
- data/spec/proc/to_source_within_irb_spec.rb +1 -1
- data/spec/proc_scanner/block_comment_spec.rb +1 -1
- data/spec/proc_scanner/double_colons_spec.rb +1 -1
- data/spec/proc_scanner/double_quote_str_w_interpolation_spec.rb +9 -9
- data/spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb +13 -13
- data/spec/proc_scanner/heredoc_spec.rb +1 -1
- data/spec/proc_scanner/kw_do_alias1_spec.rb +1 -1
- data/spec/proc_scanner/kw_do_alias2_spec.rb +1 -1
- data/spec/proc_scanner/per_line_comment_spec.rb +1 -1
- data/spec/proc_scanner/single_quote_str_spec.rb +1 -1
- data/spec/proc_scanner/slash_operator_spec.rb +75 -0
- data/spec/proc_scanner/spec_helper.rb +1 -1
- data/spec/spec_helper.rb +53 -45
- metadata +46 -16
- data/ext/sourcify/extconf.rb +0 -2
data/.infinity_test
ADDED
@@ -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
|
data/HISTORY.txt
CHANGED
@@ -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]
|
data/README.rdoc
CHANGED
@@ -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
|
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
|
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
|
-
|
43
|
-
|
43
|
+
lambda { x + y }.to_source
|
44
|
+
# >> "proc { (x + y) }"
|
44
45
|
|
45
|
-
|
46
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
119
|
+
test.source_location
|
109
120
|
# >> ["(eval)", 1]
|
110
121
|
|
111
|
-
|
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
|
-
|
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
|
-
|
143
|
-
|
144
|
-
|
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
|
-
|
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
|
-
|
155
|
-
|
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
|
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.
|
1
|
+
0.4.0
|
data/lib/sourcify.rb
CHANGED
@@ -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)
|
data/lib/sourcify/proc.rb
CHANGED
@@ -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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
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
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
-
|
162
|
+
Proc.class_eval do
|
84
163
|
include Sourcify::Proc
|
85
164
|
end
|