sourcify 0.1.2 → 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.
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,24 @@
1
+ module Sourcify
2
+ module Proc
3
+ module Scanner #:nodoc:all
4
+ class Heredoc < Struct.new(:tag, :indented)
5
+
6
+ def <<(content)
7
+ (@contents ||= []) << content
8
+ end
9
+
10
+ def to_s
11
+ @contents.join
12
+ end
13
+
14
+ def closed?(sealer)
15
+ return false unless sealer == "\n"
16
+ parts = @contents[-1].split("\n")
17
+ return true if parts[-1] == tag
18
+ indented && parts[-1].sub(/^\s*(.*)$/,'\1') == tag
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{sourcify}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["NgTzeYang"]
12
- s.date = %q{2010-08-30}
12
+ s.date = %q{2010-09-11}
13
13
  s.description = %q{}
14
14
  s.email = %q{ngty77@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -26,14 +26,19 @@ Gem::Specification.new do |s|
26
26
  "VERSION",
27
27
  "lib/sourcify.rb",
28
28
  "lib/sourcify/proc.rb",
29
- "lib/sourcify/proc/counter.rb",
30
- "lib/sourcify/proc/lexer.rb",
31
- "lib/sourcify/proc/lexer18.rb",
32
- "lib/sourcify/proc/lexer19.rb",
33
29
  "lib/sourcify/proc/parser.rb",
30
+ "lib/sourcify/proc/scanner.rb",
31
+ "lib/sourcify/proc/scanner.rl",
32
+ "lib/sourcify/proc/scanner/comment.rb",
33
+ "lib/sourcify/proc/scanner/counter.rb",
34
+ "lib/sourcify/proc/scanner/dstring.rb",
35
+ "lib/sourcify/proc/scanner/extensions.rb",
36
+ "lib/sourcify/proc/scanner/heredoc.rb",
34
37
  "sourcify.gemspec",
38
+ "spec/dump_object_space_procs.rb",
35
39
  "spec/proc/19x_extras.rb",
36
- "spec/proc/misc_spec.rb",
40
+ "spec/proc/created_on_the_fly_proc_spec.rb",
41
+ "spec/proc/others_spec.rb",
37
42
  "spec/proc/readme",
38
43
  "spec/proc/to_sexp_variables_spec.rb",
39
44
  "spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb",
@@ -58,6 +63,17 @@ Gem::Specification.new do |s|
58
63
  "spec/proc/to_source_magic_file_var_spec.rb",
59
64
  "spec/proc/to_source_magic_line_var_spec.rb",
60
65
  "spec/proc/to_source_variables_spec.rb",
66
+ "spec/proc_scanner/block_comment_spec.rb",
67
+ "spec/proc_scanner/double_colons_spec.rb",
68
+ "spec/proc_scanner/double_quote_str_w_interpolation_spec.rb",
69
+ "spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb",
70
+ "spec/proc_scanner/heredoc_spec.rb",
71
+ "spec/proc_scanner/kw_do_alias1_spec.rb",
72
+ "spec/proc_scanner/kw_do_alias2_spec.rb",
73
+ "spec/proc_scanner/per_line_comment_spec.rb",
74
+ "spec/proc_scanner/single_quote_str_spec.rb",
75
+ "spec/proc_scanner/spec_helper.rb",
76
+ "spec/proc_scanner/to_proc_spec.rb",
61
77
  "spec/spec_helper.rb"
62
78
  ]
63
79
  s.homepage = %q{http://github.com/ngty/sourcify}
@@ -66,9 +82,21 @@ Gem::Specification.new do |s|
66
82
  s.rubygems_version = %q{1.3.7}
67
83
  s.summary = %q{Workarounds before ruby-core officially supports Proc#to_source (& friends)}
68
84
  s.test_files = [
69
- "spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb",
85
+ "spec/proc_scanner/kw_do_alias1_spec.rb",
86
+ "spec/proc_scanner/single_quote_str_spec.rb",
87
+ "spec/proc_scanner/to_proc_spec.rb",
88
+ "spec/proc_scanner/kw_do_alias2_spec.rb",
89
+ "spec/proc_scanner/double_colons_spec.rb",
90
+ "spec/proc_scanner/block_comment_spec.rb",
91
+ "spec/proc_scanner/per_line_comment_spec.rb",
92
+ "spec/proc_scanner/heredoc_spec.rb",
93
+ "spec/proc_scanner/double_quote_str_w_interpolation_spec.rb",
94
+ "spec/proc_scanner/spec_helper.rb",
95
+ "spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb",
96
+ "spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb",
70
97
  "spec/proc/to_source_from_do_end_block_w_nested_begin_spec.rb",
71
98
  "spec/proc/to_source_from_braced_block_w_nested_hash_spec.rb",
99
+ "spec/proc/created_on_the_fly_proc_spec.rb",
72
100
  "spec/proc/to_source_from_braced_block_wo_nesting_complication_spec.rb",
73
101
  "spec/proc/to_source_from_do_end_block_w_nested_while_spec.rb",
74
102
  "spec/proc/to_source_from_multi_do_end_blocks_w_single_match_spec.rb",
@@ -82,15 +110,16 @@ Gem::Specification.new do |s|
82
110
  "spec/proc/to_source_magic_line_var_spec.rb",
83
111
  "spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb",
84
112
  "spec/proc/to_source_from_do_end_block_w_nested_unless_spec.rb",
113
+ "spec/proc/others_spec.rb",
85
114
  "spec/proc/19x_extras.rb",
86
115
  "spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb",
87
116
  "spec/proc/to_source_from_do_end_block_wo_nesting_complication_spec.rb",
88
117
  "spec/proc/to_source_variables_spec.rb",
89
118
  "spec/proc/to_sexp_variables_spec.rb",
90
119
  "spec/proc/to_source_magic_file_var_spec.rb",
91
- "spec/proc/misc_spec.rb",
92
120
  "spec/proc/to_source_from_do_end_block_w_nested_if_spec.rb",
93
121
  "spec/proc/to_source_from_do_end_block_w_nested_for_spec.rb",
122
+ "spec/dump_object_space_procs.rb",
94
123
  "spec/spec_helper.rb"
95
124
  ]
96
125
 
@@ -0,0 +1,84 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), '..', 'lib', 'sourcify')
2
+ require 'benchmark'
3
+ require 'pp'
4
+
5
+ if RUBY_PLATFORM =~ /java/i
6
+ require 'jruby'
7
+ JRuby.objectspace = true
8
+ reload! rescue nil
9
+ end
10
+
11
+ DUMPED_OBJECT_SPACE_PROCS = {:max => nil, :done => 0}
12
+ DUMP_OBJECT_SPACE_PROCS_ERRORS = []
13
+ class STOP_DUMPING_OBJECT_SPACE_PROCS < Exception; end
14
+
15
+ def dump_object_space_procs(debug = false)
16
+ # Determine working dir
17
+ name = [
18
+ RUBY_DESCRIPTION =~ /enterprise/i ? 'ree' : (RUBY_PLATFORM =~ /java/i ? 'jruby' : 'mri'),
19
+ RUBY_VERSION,
20
+ Object.const_defined?(:ParseTree) ? 'parsetree' : nil
21
+ ].compact.join('~')
22
+ dump_dir = File.join(File.dirname(File.expand_path(__FILE__)), '..', 'tmp', name)
23
+ Dir.mkdir(dump_dir) unless File.exists?(dump_dir)
24
+
25
+ puts '',
26
+ '== NOTE: dump files can be found at %s' % dump_dir
27
+
28
+ # Core processing
29
+ ObjectSpace.each_object(Proc).to_a.
30
+ group_by{|o| o.source_location[0] }.each do |ofile, objs|
31
+ nfile = File.join(dump_dir, ofile.gsub('/','~'))
32
+ File.open(nfile,'w') do |f|
33
+ objs.sort_by{|o| o.source_location[1] }.map do |o|
34
+ DUMPED_OBJECT_SPACE_PROCS[:done] += 1
35
+ begin
36
+ data = {
37
+ :location => o.source_location,
38
+ :sexp => o.to_sexp,
39
+ :source => o.to_source
40
+ }
41
+ f.puts(data.pretty_inspect)
42
+ print '.'
43
+ rescue Exception
44
+ data = {
45
+ :location => o.source_location,
46
+ :error => $!.inspect
47
+ }
48
+ DUMP_OBJECT_SPACE_PROCS_ERRORS << data
49
+ f.puts(data.pretty_inspect)
50
+ pp(data) if debug
51
+ print 'x'
52
+ ensure
53
+ raise STOP_DUMPING_OBJECT_SPACE_PROCS \
54
+ if DUMPED_OBJECT_SPACE_PROCS.values.uniq.size == 1
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ # Dumping in action
62
+ figures = Benchmark.measure do
63
+ begin
64
+ dump_object_space_procs
65
+ rescue STOP_DUMPING_OBJECT_SPACE_PROCS
66
+ end
67
+ end
68
+
69
+ # Printout the failures/passes
70
+ unless DUMP_OBJECT_SPACE_PROCS_ERRORS.empty?
71
+ puts '', '== OOPS, we have some erorrs :('
72
+ DUMP_OBJECT_SPACE_PROCS_ERRORS.each_with_index do |e, i|
73
+ print "#{i}). %s" % e.pretty_inspect
74
+ end
75
+ else
76
+ puts '', '== YEAH, no errors :)'
77
+ end
78
+
79
+ # Printout the benchmark results
80
+ puts '',
81
+ '== Benchmark results for processing %s procs:' % DUMPED_OBJECT_SPACE_PROCS[:done],
82
+ figures.to_s, ''
83
+
84
+ # __END__
@@ -0,0 +1,172 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe "Created on the fly proc" do
4
+ unless Object.const_defined?(:ParseTree)
5
+
6
+ klass = Class.new do
7
+ def test(&block); block ; end
8
+ def blah; 1+2; end
9
+ end
10
+
11
+ describe 'Blah#to_proc raising Sourcify::CannotHandleCreatedOnTheFlyProcError' do
12
+
13
+ should "raise when created by :to_proc" do
14
+ lambda {
15
+ x, y = klass.new.method(:test).to_proc, lambda { 1+2 }
16
+ x.to_source
17
+ }.should.raise(Sourcify::CannotHandleCreatedOnTheFlyProcError)
18
+ end
19
+
20
+ should "not raise even with prepending :to_proc on the same line" do
21
+ x, y = klass.new.method(:test).to_proc, lambda { 1+2 }
22
+ y.to_source.should.not.be.nil
23
+ end
24
+
25
+ should "not raise even with appending :to_proc on the same line" do
26
+ x, y = lambda { 1+2 }, klass.new.method(:test).to_proc
27
+ x.to_source.should.not.be.nil
28
+ end
29
+
30
+ should "not raise even with nested :to_proc on the same line" do
31
+ x = lambda { klass.new.method(:test).to_proc }
32
+ x.to_source.should.not.be.nil
33
+ end
34
+
35
+ end
36
+
37
+ if RUBY_VERSION.include?('1.9.') or RUBY_PLATFORM =~ /java/i
38
+
39
+ describe '&:blah raising Sourcify::CannotHandleCreatedOnTheFlyProcError' do
40
+
41
+ should "raise when created by &:blah" do
42
+ lambda {
43
+ x, y = klass.new.test(&:blah), lambda { 1+2 }
44
+ x.to_source
45
+ }.should.raise(Sourcify::CannotHandleCreatedOnTheFlyProcError)
46
+ end
47
+
48
+ should "not raise even with prepending &:blah on the same line" do
49
+ x, y = klass.new.test(&:blah), lambda { 1+2 }
50
+ y.to_source.should.not.be.nil
51
+ end
52
+
53
+ should "not raise even with appending &:blah on the same line" do
54
+ x, y = lambda { 1+2 }, klass.new.test(&:blah)
55
+ x.to_source.should.not.be.nil
56
+ end
57
+
58
+ should "not raise even with nested &:blah on the same line" do
59
+ x = lambda { klass.new.test(&:blah) }
60
+ x.to_source.should.not.be.nil
61
+ end
62
+
63
+ should "not raise with nested &:blah on diff line" do
64
+ (
65
+ lambda do
66
+ klass.new.test(&:blah)
67
+ end
68
+ ).to_source.should.not.be.nil
69
+ end
70
+
71
+ end
72
+
73
+ else
74
+
75
+ describe '&:blah raising Sourcify::CannotHandleCreatedOnTheFlyProcError' do
76
+
77
+ should "raise w no other proc on the same line" do
78
+ lambda {
79
+ x = klass.new.test(&:blah)
80
+ x.to_source
81
+ }.should.raise(Sourcify::CannotHandleCreatedOnTheFlyProcError)
82
+ end
83
+
84
+ should "raise w prepending proc of different arity on the same line" do
85
+ lambda {
86
+ y, x = lambda {|a| 1+2 }, klass.new.test(&:blah)
87
+ x.to_source
88
+ }.should.raise(Sourcify::CannotHandleCreatedOnTheFlyProcError)
89
+ end
90
+
91
+ should "raise w appending proc of different arity on the same line" do
92
+ lambda {
93
+ x, y = klass.new.test(&:blah), lambda {|a| 1+2 }
94
+ x.to_source
95
+ }.should.raise(Sourcify::CannotHandleCreatedOnTheFlyProcError)
96
+ end
97
+
98
+ should "raise w nested proc of different arity on the same line" do
99
+ lambda {
100
+ y = lambda {|a| klass.new.test(&:blah) }
101
+ x = y.call(1).to_source
102
+ }.should.raise(Sourcify::CannotHandleCreatedOnTheFlyProcError)
103
+ end
104
+
105
+ should "not raise with nested &:blah on diff line" do
106
+ (
107
+ lambda do
108
+ klass.new.test(&:blah)
109
+ end
110
+ ).to_source.should.not.be.nil
111
+ end
112
+
113
+ end
114
+
115
+ describe '&:blah raising Sourcify::MultipleMatchingProcsPerLineError' do
116
+
117
+ should 'raise w prepending proc w zero arg (arity -1) on the same line' do
118
+ lambda {
119
+ y, x = lambda { 1+2 }, klass.new.test(&:blah)
120
+ x.to_source
121
+ }.should.raise(Sourcify::MultipleMatchingProcsPerLineError)
122
+ end
123
+
124
+ should 'raise w appending proc w zero arg (arity -1) on the same line' do
125
+ lambda {
126
+ x, y = klass.new.test(&:blah), lambda { 1+2 }
127
+ x.to_source
128
+ }.should.raise(Sourcify::MultipleMatchingProcsPerLineError)
129
+ end
130
+
131
+ should 'raise w nested proc w zero arg (arity -1) on the same line' do
132
+ lambda {
133
+ x = lambda { klass.new.test(&:blah) }
134
+ x.call.to_source
135
+ }.should.raise(Sourcify::MultipleMatchingProcsPerLineError)
136
+ end
137
+
138
+ should 'raise w prepending proc w single optional arg (arity -1) on the same line' do
139
+ lambda {
140
+ y, x = lambda {|*a| 1+2 }, klass.new.test(&:blah)
141
+ x.to_source
142
+ }.should.raise(Sourcify::MultipleMatchingProcsPerLineError)
143
+ end
144
+
145
+ should 'raise w appending proc w single optional arg (arity -1) on the same line' do
146
+ lambda {
147
+ x, y = klass.new.test(&:blah), lambda {|*a| 1+2 }
148
+ x.to_source
149
+ }.should.raise(Sourcify::MultipleMatchingProcsPerLineError)
150
+ end
151
+
152
+ should 'raise w nested proc w single optional arg (arity -1) on the same line' do
153
+ lambda {
154
+ x = lambda {|*a| klass.new.test(&:blah) }
155
+ x.call.to_source
156
+ }.should.raise(Sourcify::MultipleMatchingProcsPerLineError)
157
+ end
158
+
159
+ should "not raise with nested &:blah on diff line" do
160
+ (
161
+ lambda do
162
+ x = klass.new.test(&:blah)
163
+ end
164
+ ).to_source.should.not.be.nil
165
+ end
166
+
167
+ end
168
+
169
+ end
170
+
171
+ end
172
+ end
@@ -0,0 +1,36 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe "Misc" do
4
+
5
+ should 'handle accessing #to_sexp after #to_source' do
6
+ (s_proc = lambda { :test }).to_source
7
+ s_proc.should.be having_sexp(s(:iter, s(:call, nil, :proc, s(:arglist)), nil, s(:lit, :test)))
8
+ end
9
+
10
+ should 'handle accessing #to_source after #to_sexp' do
11
+ (s_proc = lambda { :test }).to_sexp
12
+ s_proc.should.be having_source('proc { :test }')
13
+ end
14
+
15
+ should "handle lexer bug in missing trailing chars after '=>' operator" do
16
+ # This example addresses bug @ http://redmine.ruby-lang.org/issues/show/3765
17
+ {
18
+ __LINE__ => lambda { :test }
19
+ }.values.last.should.be having_source('proc { :test }')
20
+ end
21
+
22
+ should "handle lexer bug in missing trailing chars after '=>' operator" do
23
+ # This example addresses bug @ http://redmine.ruby-lang.org/issues/show/3765
24
+ {
25
+ __LINE__ => lambda do :test end
26
+ }.values.last.should.be having_source('proc { :test }')
27
+ end
28
+
29
+ unless Object.const_defined?(:ParseTree)
30
+ should "raise Sourcify::CannotParseEvalCodeError when proc is created from eval" do
31
+ lambda { eval("proc {:test }").to_source }.should.
32
+ raise(Sourcify::CannotParseEvalCodeError)
33
+ end
34
+ end
35
+
36
+ end
@@ -30,14 +30,14 @@ describe "Proc#to_sexp (variables)" do
30
30
  should 'handle class_eval scoped local var' do
31
31
  (
32
32
  x = 1
33
- lambda { Object.class_eval { y = x } }
33
+ lambda { Object.class_eval {|x| y = x } }
34
34
  ).should.be having_sexp(
35
35
  s(:iter,
36
36
  s(:call, nil, :proc, s(:arglist)),
37
37
  nil,
38
38
  s(:iter,
39
39
  s(:call, s(:const, :Object), :class_eval, s(:arglist)),
40
- nil,
40
+ s(:lasgn, :x),
41
41
  s(:lasgn, :y, s(:lvar, :x))))
42
42
  )
43
43
  end
@@ -45,14 +45,14 @@ describe "Proc#to_sexp (variables)" do
45
45
  should 'handle instance_eval scoped local var' do
46
46
  (
47
47
  x = 1
48
- lambda { 'aa'.instance_eval { y = x } }
48
+ lambda { 'aa'.instance_eval {|x| y = x } }
49
49
  ).should.be having_sexp(
50
50
  s(:iter,
51
51
  s(:call, nil, :proc, s(:arglist)),
52
52
  nil,
53
53
  s(:iter,
54
54
  s(:call, s(:str, "aa"), :instance_eval, s(:arglist)),
55
- nil,
55
+ s(:lasgn, :x),
56
56
  s(:lasgn, :y, s(:lvar, :x))))
57
57
  )
58
58
  end
@@ -60,7 +60,7 @@ describe "Proc#to_sexp (variables)" do
60
60
  should 'handle define_method scoped local var' do
61
61
  (
62
62
  x = 1
63
- lambda { Object.send(:define_method, :aa) { y = x } }
63
+ lambda { Object.send(:define_method, :aa) {|x| y = x } }
64
64
  ).should.be having_sexp(
65
65
  s(:iter,
66
66
  s(:call, nil, :proc, s(:arglist)),
@@ -70,7 +70,7 @@ describe "Proc#to_sexp (variables)" do
70
70
  s(:const, :Object),
71
71
  :send,
72
72
  s(:arglist, s(:lit, :define_method), s(:lit, :aa))),
73
- nil,
73
+ s(:lasgn, :x),
74
74
  s(:lasgn, :y, s(:lvar, :x))))
75
75
  )
76
76
  end