sourcify 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/.gitignore +1 -0
  2. data/HISTORY.txt +11 -0
  3. data/README.rdoc +52 -28
  4. data/VERSION +1 -1
  5. data/lib/sourcify.rb +13 -1
  6. data/lib/sourcify/proc.rb +7 -4
  7. data/lib/sourcify/proc/parser.rb +109 -40
  8. data/lib/sourcify/proc/scanner.rb +2140 -0
  9. data/lib/sourcify/proc/scanner.rl +285 -0
  10. data/lib/sourcify/proc/scanner/comment.rb +21 -0
  11. data/lib/sourcify/proc/scanner/counter.rb +44 -0
  12. data/lib/sourcify/proc/scanner/dstring.rb +58 -0
  13. data/lib/sourcify/proc/scanner/extensions.rb +135 -0
  14. data/lib/sourcify/proc/scanner/heredoc.rb +24 -0
  15. data/sourcify.gemspec +38 -9
  16. data/spec/dump_object_space_procs.rb +84 -0
  17. data/spec/proc/created_on_the_fly_proc_spec.rb +172 -0
  18. data/spec/proc/others_spec.rb +36 -0
  19. data/spec/proc/to_sexp_variables_spec.rb +6 -6
  20. data/spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb +2 -0
  21. data/spec/proc/to_source_from_multi_blocks_w_many_matches_spec.rb +105 -29
  22. data/spec/proc/to_source_from_multi_blocks_w_single_match_spec.rb +85 -17
  23. data/spec/proc_scanner/block_comment_spec.rb +59 -0
  24. data/spec/proc_scanner/double_colons_spec.rb +14 -0
  25. data/spec/proc_scanner/double_quote_str_w_interpolation_spec.rb +62 -0
  26. data/spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb +75 -0
  27. data/spec/proc_scanner/heredoc_spec.rb +142 -0
  28. data/spec/proc_scanner/kw_do_alias1_spec.rb +87 -0
  29. data/spec/proc_scanner/kw_do_alias2_spec.rb +86 -0
  30. data/spec/proc_scanner/per_line_comment_spec.rb +34 -0
  31. data/spec/proc_scanner/single_quote_str_spec.rb +68 -0
  32. data/spec/proc_scanner/spec_helper.rb +33 -0
  33. data/spec/proc_scanner/to_proc_spec.rb +15 -0
  34. data/spec/spec_helper.rb +23 -0
  35. metadata +39 -10
  36. data/lib/sourcify/proc/counter.rb +0 -41
  37. data/lib/sourcify/proc/lexer.rb +0 -40
  38. data/lib/sourcify/proc/lexer18.rb +0 -237
  39. data/lib/sourcify/proc/lexer19.rb +0 -204
  40. data/spec/proc/misc_spec.rb +0 -16
@@ -0,0 +1,15 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "#to_proc" do
4
+
5
+ should 'handle &:xxx' do
6
+ process(" &:xxx ").should.include([:to_proc, '&:xxx'])
7
+ end
8
+
9
+ %w{&xxx :xxx}.each do |expr|
10
+ should "handle not #{expr}" do
11
+ process(" #{expr} ").map(&:first).should.not.include(:to_proc)
12
+ end
13
+ end
14
+
15
+ end
@@ -6,6 +6,18 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
6
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
7
  require 'sourcify'
8
8
 
9
+ ragel_dir = File.join(File.dirname(__FILE__), '..', 'lib', 'sourcify', 'proc')
10
+ ragel_file = File.join(ragel_dir, 'scanner.rl')
11
+ ruby_file = File.join(ragel_dir, 'scanner.rb')
12
+ File.delete(ruby_file) rescue nil
13
+ system("ragel -R #{ragel_file}")
14
+
15
+ begin
16
+ require File.join(ragel_dir, 'scanner.rb')
17
+ rescue LoadError
18
+ raise $!
19
+ end
20
+
9
21
  Bacon.summary_on_exit
10
22
 
11
23
  def watever(*args, &block)
@@ -39,3 +51,14 @@ def having_sexp(expected)
39
51
  end
40
52
  end
41
53
 
54
+ def capture(stdin_str = '')
55
+ begin
56
+ require 'stringio'
57
+ $o_stdin, $o_stdout, $o_stderr = $stdin, $stdout, $stderr
58
+ $stdin, $stdout, $stderr = StringIO.new(stdin_str), StringIO.new, StringIO.new
59
+ yield
60
+ {:stdout => $stdout.string, :stderr => $stderr.string}
61
+ ensure
62
+ $stdin, $stdout, $stderr = $o_stdin, $o_stdout, $o_stderr
63
+ end
64
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sourcify
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
8
  - 2
10
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - NgTzeYang
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-30 00:00:00 +08:00
18
+ date: 2010-09-11 00:00:00 +08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -67,14 +67,19 @@ files:
67
67
  - VERSION
68
68
  - lib/sourcify.rb
69
69
  - lib/sourcify/proc.rb
70
- - lib/sourcify/proc/counter.rb
71
- - lib/sourcify/proc/lexer.rb
72
- - lib/sourcify/proc/lexer18.rb
73
- - lib/sourcify/proc/lexer19.rb
74
70
  - lib/sourcify/proc/parser.rb
71
+ - lib/sourcify/proc/scanner.rb
72
+ - lib/sourcify/proc/scanner.rl
73
+ - lib/sourcify/proc/scanner/comment.rb
74
+ - lib/sourcify/proc/scanner/counter.rb
75
+ - lib/sourcify/proc/scanner/dstring.rb
76
+ - lib/sourcify/proc/scanner/extensions.rb
77
+ - lib/sourcify/proc/scanner/heredoc.rb
75
78
  - sourcify.gemspec
79
+ - spec/dump_object_space_procs.rb
76
80
  - spec/proc/19x_extras.rb
77
- - spec/proc/misc_spec.rb
81
+ - spec/proc/created_on_the_fly_proc_spec.rb
82
+ - spec/proc/others_spec.rb
78
83
  - spec/proc/readme
79
84
  - spec/proc/to_sexp_variables_spec.rb
80
85
  - spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb
@@ -99,6 +104,17 @@ files:
99
104
  - spec/proc/to_source_magic_file_var_spec.rb
100
105
  - spec/proc/to_source_magic_line_var_spec.rb
101
106
  - spec/proc/to_source_variables_spec.rb
107
+ - spec/proc_scanner/block_comment_spec.rb
108
+ - spec/proc_scanner/double_colons_spec.rb
109
+ - spec/proc_scanner/double_quote_str_w_interpolation_spec.rb
110
+ - spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb
111
+ - spec/proc_scanner/heredoc_spec.rb
112
+ - spec/proc_scanner/kw_do_alias1_spec.rb
113
+ - spec/proc_scanner/kw_do_alias2_spec.rb
114
+ - spec/proc_scanner/per_line_comment_spec.rb
115
+ - spec/proc_scanner/single_quote_str_spec.rb
116
+ - spec/proc_scanner/spec_helper.rb
117
+ - spec/proc_scanner/to_proc_spec.rb
102
118
  - spec/spec_helper.rb
103
119
  has_rdoc: true
104
120
  homepage: http://github.com/ngty/sourcify
@@ -135,9 +151,21 @@ signing_key:
135
151
  specification_version: 3
136
152
  summary: Workarounds before ruby-core officially supports Proc#to_source (& friends)
137
153
  test_files:
154
+ - spec/proc_scanner/kw_do_alias1_spec.rb
155
+ - spec/proc_scanner/single_quote_str_spec.rb
156
+ - spec/proc_scanner/to_proc_spec.rb
157
+ - spec/proc_scanner/kw_do_alias2_spec.rb
158
+ - spec/proc_scanner/double_colons_spec.rb
159
+ - spec/proc_scanner/block_comment_spec.rb
160
+ - spec/proc_scanner/per_line_comment_spec.rb
161
+ - spec/proc_scanner/heredoc_spec.rb
162
+ - spec/proc_scanner/double_quote_str_w_interpolation_spec.rb
163
+ - spec/proc_scanner/spec_helper.rb
164
+ - spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb
138
165
  - spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb
139
166
  - spec/proc/to_source_from_do_end_block_w_nested_begin_spec.rb
140
167
  - spec/proc/to_source_from_braced_block_w_nested_hash_spec.rb
168
+ - spec/proc/created_on_the_fly_proc_spec.rb
141
169
  - spec/proc/to_source_from_braced_block_wo_nesting_complication_spec.rb
142
170
  - spec/proc/to_source_from_do_end_block_w_nested_while_spec.rb
143
171
  - spec/proc/to_source_from_multi_do_end_blocks_w_single_match_spec.rb
@@ -151,13 +179,14 @@ test_files:
151
179
  - spec/proc/to_source_magic_line_var_spec.rb
152
180
  - spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb
153
181
  - spec/proc/to_source_from_do_end_block_w_nested_unless_spec.rb
182
+ - spec/proc/others_spec.rb
154
183
  - spec/proc/19x_extras.rb
155
184
  - spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb
156
185
  - spec/proc/to_source_from_do_end_block_wo_nesting_complication_spec.rb
157
186
  - spec/proc/to_source_variables_spec.rb
158
187
  - spec/proc/to_sexp_variables_spec.rb
159
188
  - spec/proc/to_source_magic_file_var_spec.rb
160
- - spec/proc/misc_spec.rb
161
189
  - spec/proc/to_source_from_do_end_block_w_nested_if_spec.rb
162
190
  - spec/proc/to_source_from_do_end_block_w_nested_for_spec.rb
191
+ - spec/dump_object_space_procs.rb
163
192
  - spec/spec_helper.rb
@@ -1,41 +0,0 @@
1
- module Sourcify
2
- module Proc
3
- class Counter #:nodoc:all
4
-
5
- attr_accessor :marker
6
-
7
- def initialize
8
- @marker, @counter = nil, {:start => 0, :end => 0}
9
- end
10
-
11
- def [](key)
12
- @counter[key]
13
- end
14
-
15
- def started?
16
- @counter.values != [0,0]
17
- end
18
-
19
- def telly?
20
- @counter[:start] == @counter[:end]
21
- end
22
-
23
- def decrement_start
24
- @counter[:start] -= 1
25
- self
26
- end
27
-
28
- def increment_start
29
- @counter[:start] += 1
30
- self
31
- end
32
-
33
- def increment_end
34
- @counter[:end] += 1
35
- self
36
- end
37
-
38
- end
39
- end
40
- end
41
-
@@ -1,40 +0,0 @@
1
- module Sourcify
2
- module Proc
3
- module Lexer #:nodoc:all
4
-
5
- class << self
6
- def new(*args)
7
- begin
8
- require 'sourcify/proc/lexer19'
9
- Lexer19.new(*args)
10
- rescue LoadError
11
- require 'sourcify/proc/lexer18'
12
- Lexer18.new(*args)
13
- end
14
- end
15
- end
16
-
17
- module Commons
18
-
19
- class EndOfBlock < Exception ; end
20
- class EndOfLine < Exception ; end
21
-
22
- def work
23
- begin
24
- @results ||= []
25
- @do_end_counter = Sourcify::Proc::Counter.new
26
- @braced_counter = Sourcify::Proc::Counter.new
27
- lex
28
- rescue EndOfBlock
29
- @results << @result.dup
30
- @is_multiline_block ? @results : retry
31
- rescue EndOfLine
32
- @results
33
- end
34
- end
35
-
36
- end
37
-
38
- end
39
- end
40
- end
@@ -1,237 +0,0 @@
1
- require 'irb/ruby-lex'
2
- require 'irb/ruby-token'
3
-
4
- module Sourcify
5
- module Proc
6
- class Lexer18 #:nodoc:all
7
-
8
- # NOTE: Implementation of this class has been heavily inspired by:
9
- # * the discussion @ http://www.justskins.com/forums/breaking-ruby-code-into-117453.html
10
- # * Florian Groß's solution for ruby quiz 'SerializableProc (#38)'
11
- # @ http://rubyquiz.com/quiz38.html
12
-
13
- include Lexer::Commons
14
-
15
- def initialize(io, file, line)
16
- @file, @line, @io, @pos = file, line, io, io.pos
17
- @lex = RubyLex.new
18
- @lex.set_input(@io)
19
- @lex.get_readed
20
- end
21
-
22
- def lex
23
- (@tokens = []).extend(Extensions)
24
- @magic_lines = []
25
-
26
- while @tk = @lex.token
27
- tkc = @tk.class.to_s.sub(/\ARubyToken::/, '').downcase.to_sym
28
- @tokens << [@tk.line_no, @tk.char_no, tkc]
29
- post_qstring if @qstring_data
30
- @lex.get_readed if tkc == :tknl
31
- next if @do_end_counter.started? && @tokens.curr.symbolized_keyword?
32
- send(:"on_#{tkc}") rescue NoMethodError
33
- end
34
- end
35
-
36
- def on_tknl
37
- raise EndOfLine unless @results.empty?
38
- end
39
-
40
- def on_tk__line__
41
- @magic_lines << [@tk.seek, @tk.line_no + @line]
42
- end
43
-
44
- def on_tkdstring
45
- @qstring_data = [@tk.seek, @tk.line_no + @line]
46
- end
47
-
48
- alias_method :on_tkstring, :on_tkdstring # heredoc
49
- alias_method :on_tkdregexp, :on_tkdstring # regexp
50
- alias_method :on_tkdxstring, :on_tkdstring # ` command
51
-
52
- def post_qstring
53
- seek, line = @qstring_data
54
- @magic_lines << [(seek .. @tk.seek), line]
55
- @qstring_data = nil
56
- end
57
-
58
- def on_tkdo
59
- if !@do_end_counter.started?
60
- @do_end_counter.marker = @tk.seek
61
- @do_end_counter.increment_start
62
- elsif @tokens.same_as_curr_line.keywords(:tkfor, :tkwhile, :tkuntil).empty?
63
- # It is possible for a 'for', 'while' or 'until' to have an attached 'do',
64
- # for such a case, we want to skip it
65
- @do_end_counter.increment_start
66
- end
67
- end
68
-
69
- def on_tkend
70
- if @do_end_counter.started? && @do_end_counter.increment_end.telly?
71
- @result = grab_result_and_reset_lex(@do_end_counter.marker, 3)
72
- @is_multiline_block = @tokens.multiline?
73
- raise EndOfBlock
74
- end
75
- end
76
-
77
- def on_tkclass
78
- # Pretty straightforward for these, each of them will consume an 'end' close it
79
- @do_end_counter.increment_start if @do_end_counter.started?
80
- end
81
-
82
- # These work the same as 'class', the exception is 'for', which can have an optional
83
- # 'do' attached:
84
- # * for a in [1,2] do ... end
85
- # * for a in [1,2] \n ... end
86
- %w{def module begin case for}.each{|kw| alias_method :"on_tk#{kw}", :on_tkclass }
87
-
88
- def on_tkwhile
89
- # This has optional trailing 'do', and can work as a modifier as well, eg:
90
- # * while true do ... end # => 'do' must be on the same line as 'while'
91
- # * while true \n ... end
92
- # * ... while true # => 'while' is pre-pended with non-spaces
93
- if @do_end_counter.started? && @tokens.start_of_line?
94
- @do_end_counter.increment_start
95
- end
96
- end
97
-
98
- # These work exactly the same as 'while'.
99
- %w{until if unless}.each{|kw| alias_method :"on_tk#{kw}", :on_tkwhile }
100
-
101
- def on_tklbrace
102
- unless @do_end_counter.started?
103
- @braced_counter.marker = @tk.seek unless @braced_counter.started?
104
- @braced_counter.increment_start
105
- end
106
- end
107
-
108
- def on_tkrbrace
109
- if @braced_counter.started? && @braced_counter.increment_end.telly?
110
- @result = grab_result_and_reset_lex(@braced_counter.marker, 1)
111
- @is_multiline_block = @tokens.multiline?
112
- raise EndOfBlock
113
- end
114
- end
115
-
116
- alias_method :on_tkflbrace, :on_tklbrace
117
- alias_method :on_tkfrbrace, :on_tkrbrace
118
-
119
- def on_tkassoc
120
- if @braced_counter.started? && @braced_counter[:start] == 1
121
- @braced_counter.decrement_start
122
- end
123
- end
124
-
125
- def on_tkgt
126
- on_tkassoc if @tokens[-2 .. -1].map(&:last) == [:tkassign, :tkgt]
127
- end
128
-
129
- def grab_result_and_reset_lex(marker, offset)
130
- @io.seek(@pos+marker)
131
- diff = @tk.seek - marker + offset
132
- result = replace_magic_lines(@io.read(diff), marker)
133
- @io.seek(@pos + diff)
134
- @lex.set_input(@io)
135
- @lex.get_readed
136
- result
137
- end
138
-
139
- def replace_magic_lines(result, marker, offset = 0)
140
- @magic_lines.inject(result) do |rs, (pos,val)|
141
- meth = :"replace_magic_line_by_#{pos.class.to_s.downcase}"
142
- n_rs = send(meth, rs, marker + offset, pos, val)
143
- offset = result.length - n_rs.length
144
- n_rs
145
- end
146
- end
147
-
148
- def replace_magic_line_by_fixnum(rs, offset, pos, val)
149
- m = rs.match(/^(.{#{pos - offset}})__LINE__(.*)$/m)
150
- m[1] + val.pred.to_s + m[2]
151
- end
152
-
153
- def replace_magic_line_by_range(rs, offset, pos, lineno)
154
- @io.seek(@pos + pos.begin)
155
- subject = @io.read(pos.end - pos.begin)
156
- return rs if %w{' %q %w}.any?{|q| subject.start_with?(q) }
157
- prepend, append = rs.match(/^(.*?)#{Regexp.quote(subject)}(.*)$/m)[1..2]
158
- middle = subject.split("\n").each_with_index do |line, i|
159
- line.gsub!(pattern = /(.*?\#\{)__LINE__(\})/) do |s|
160
- (m = s.match(pattern)[1..2])[0].end_with?('\\#{') ?
161
- s : m.insert(1, (lineno + i).pred.to_s).join
162
- end
163
- end.join("\n")
164
- prepend + middle + append
165
- end
166
-
167
- # Ease working with the hybrid token set collected from RubyLex
168
- module Extensions
169
-
170
- ROW, COL, TYP = 0, 1, 2
171
-
172
- def same_as_curr_line
173
- same_line(curr_line)
174
- end
175
-
176
- def multiline?
177
- self[0][ROW] != self[-1][ROW]
178
- end
179
-
180
- def curr_line
181
- curr[ROW]
182
- end
183
-
184
- def curr
185
- (self[-1]).respond_to?(:symbolized_keyword?) ? self[-1] : (
186
- preceding, current = self[-2 .. -1]
187
- (class << current ; self ; end).class_eval do
188
- define_method(:symbolized_keyword?) do
189
- preceding[TYP] == :tksymbeg && %w{
190
- class module def while until if unless for do begin case end
191
- }.include?(current[TYP].to_s.sub('tk',''))
192
- end
193
- end
194
- current
195
- )
196
- self[-1]
197
- end
198
-
199
- def same_line(line)
200
- (
201
- # ignore the current node
202
- self[0..-2].reverse.take_while do |e|
203
- if e[TYP] == :tsemi
204
- false
205
- elsif e[ROW] == line
206
- true
207
- elsif e[ROW] == line.pred && e[TYP] != :tknl
208
- line -= 1
209
- true
210
- end
211
- end.reverse
212
- ).extend(Extensions)
213
- end
214
-
215
- def keywords(*types)
216
- (
217
- types = [types].flatten
218
- select{|e| types.include?(e[TYP]) }
219
- ).extend(Extensions)
220
- end
221
-
222
- def non_spaces(*types)
223
- (
224
- types = [types].flatten
225
- reject{|e| types.empty? or types.include?(e[TYP]) }
226
- ).extend(Extensions)
227
- end
228
-
229
- def start_of_line?
230
- same_as_curr_line.non_spaces.empty?
231
- end
232
-
233
- end
234
-
235
- end
236
- end
237
- end