rspec 0.5.7 → 0.5.8
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/CHANGES +9 -0
- data/Rakefile +7 -10
- data/bin/spec +1 -1
- data/bin/test2spec +93 -0
- data/doc/src/default.template +1 -1
- data/doc/src/documentation/index.page +37 -37
- data/doc/src/documentation/mocks.page +88 -60
- data/doc/src/tools/index.page +2 -2
- data/doc/src/tools/meta.info +1 -1
- data/doc/src/tools/test2spec.page +73 -0
- data/doc/src/tutorials/notes.txt +1 -1
- data/doc/src/tutorials/stack_01.page +4 -4
- data/doc/src/tutorials/stack_02.page +6 -6
- data/doc/src/tutorials/stack_03.page +8 -8
- data/doc/src/tutorials/stack_04.page +2 -2
- data/doc/src/tutorials/stack_05.page +1 -1
- data/lib/spec/api/sugar.rb +3 -3
- data/lib/spec/runner/base_text_formatter.rb +11 -5
- data/lib/spec/runner/option_parser.rb +1 -1
- data/lib/spec/runner/progress_bar_formatter.rb +1 -1
- data/lib/spec/runner/rdoc_formatter.rb +1 -1
- data/lib/spec/runner/reporter.rb +6 -3
- data/lib/spec/runner/specdoc_formatter.rb +1 -1
- data/lib/spec/runner/specification.rb +1 -0
- data/lib/spec/tool/ruby2ruby.rb +485 -0
- data/lib/spec/tool/test_unit_translator.rb +114 -83
- data/lib/spec/tool/translation_test_runner.rb +118 -0
- data/lib/spec/version.rb +1 -1
- data/test/spec/runner/context_test.rb +4 -0
- data/test/spec/runner/progress_bar_formatter_test.rb +1 -1
- data/test/spec/runner/rdoc_formatter_test.rb +1 -1
- data/test/spec/runner/reporter_test.rb +24 -7
- data/test/spec/runner/specdoc_formatter_test.rb +1 -1
- data/test/spec/runner/specification_test.rb +8 -0
- data/test/spec/tool/ruby_to_ruby_test.rb +79 -0
- data/test/spec/tool/test_unit_api_spec.rb +45 -31
- data/test/spec/tool/test_unit_api_test.rb +13 -6
- data/test/spec/tool/test_unit_translator_test.rb +6 -1
- metadata +11 -10
- data/bin/test2rspec +0 -35
- data/doc/src/tools/test2rspec.page +0 -13
- data/lib/spec/tool/command_line.rb +0 -39
- data/test/spec/tool/command_line_test.rb +0 -21
data/doc/src/tools/index.page
CHANGED
@@ -45,5 +45,5 @@ it right away.
|
|
45
45
|
|
46
46
|
h3. 7) Test::Unit translation
|
47
47
|
|
48
|
-
Did you invest a lot of time in writing Test::Unit tests and want to switch to RSpec? Try out the
|
49
|
-
tool, which will do most of the translation for you. (
|
48
|
+
Did you invest a lot of time in writing Test::Unit tests and want to switch to RSpec? Try out the test2spec
|
49
|
+
tool, which will do most of the translation for you. (test2spec tool is experimental)
|
data/doc/src/tools/meta.info
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
---
|
2
|
+
title: Test::Unit Migration
|
3
|
+
inMenu: true
|
4
|
+
---
|
5
|
+
h2. Test::Unit migration
|
6
|
+
|
7
|
+
RSpec's test2spec command line tool translates existing Test::Unit classes to RSpec.
|
8
|
+
|
9
|
+
Before you can use test2spec you must gem install ParseTree and RubyInline.
|
10
|
+
RubyInline only work on systems that have a C compiler - i.e. most anything except Windows.
|
11
|
+
|
12
|
+
If you're stuck on Windows, ask a friend who has a POSIX system to translate your specs.
|
13
|
+
Once translated they can run on any Ruby platform (including Windows). After all, it's
|
14
|
+
just Ruby.
|
15
|
+
|
16
|
+
h2. The test2spec command line
|
17
|
+
|
18
|
+
<pre>
|
19
|
+
test2spec --help
|
20
|
+
{execute: ruby ../bin/test2spec --help}
|
21
|
+
</pre>
|
22
|
+
|
23
|
+
A typical invocation might look like this:
|
24
|
+
|
25
|
+
<pre>
|
26
|
+
test2spec --specdir spec test
|
27
|
+
</pre>
|
28
|
+
|
29
|
+
h2. Sample output
|
30
|
+
|
31
|
+
<notextile>
|
32
|
+
<table>
|
33
|
+
<thead>
|
34
|
+
<tr>
|
35
|
+
<td>Test::Unit</td>
|
36
|
+
<td>RSpec (translated by test2spec)</td>
|
37
|
+
</tr>
|
38
|
+
</thead>
|
39
|
+
<tbody>
|
40
|
+
<tr>
|
41
|
+
<td>
|
42
|
+
<ruby file="../test/spec/tool/test_unit_api_test.rb"/>
|
43
|
+
</td>
|
44
|
+
<td>
|
45
|
+
<ruby file="../test/spec/tool/test_unit_api_spec.rb"/>
|
46
|
+
</td>
|
47
|
+
</tr>
|
48
|
+
</tbody>
|
49
|
+
</table>
|
50
|
+
</notextile>
|
51
|
+
|
52
|
+
h2. Troubleshooting
|
53
|
+
|
54
|
+
In some cases, test2spec will not be able to translate a test class. In that case, please submit a bug report
|
55
|
+
at RSpec's bug report system along with some code so we can reproduce (and hopefully - fix) the problem.
|
56
|
+
-Or better - submit a patch.
|
57
|
+
|
58
|
+
h2. Internals
|
59
|
+
|
60
|
+
The test2spec tool is based on three other tools:
|
61
|
+
|
62
|
+
* "RubyToRuby":http://blog.zenspider.com/archives/2005/02/rubytoruby.html
|
63
|
+
* "ParseTree":http://rubyforge.org/projects/parsetree/
|
64
|
+
* "RubyInline":http://rubyforge.org/projects/rubyinline/
|
65
|
+
|
66
|
+
In fact, it's based on a modified version of "George Moschovitis' RubyToRuby enhancement":http://dark.fhtr.org/ruby2ruby.rb
|
67
|
+
of "Ryan Davis' original RubyToRuby":http://blog.zenspider.com/archives/2005/02/rubytoruby.html.
|
68
|
+
|
69
|
+
It has been modified to fix some subtle bugs that were not found by Gerorge's tests. The modified RubyToRuby
|
70
|
+
currently lives in RSpec's subversion repository.
|
71
|
+
|
72
|
+
The translation is done by TestUnitTranslator - subclass of RubyToRuby that writes out the syntax tree a little differently than
|
73
|
+
its superclass. TestUnitTranslator looks for certain Test::Unit patterns and writes out an RSpec translation instead.
|
data/doc/src/tutorials/notes.txt
CHANGED
@@ -68,7 +68,7 @@ context "A new stack" do
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
</ruby>
|
71
|
-
|
71
|
+
|
72
72
|
<pre>
|
73
73
|
$ spec stack_spec.rb -f s
|
74
74
|
|
@@ -153,7 +153,7 @@ context "A new stack" do
|
|
153
153
|
end
|
154
154
|
end
|
155
155
|
</ruby>
|
156
|
-
|
156
|
+
|
157
157
|
<pre>
|
158
158
|
$ spec stack_spec.rb -f s
|
159
159
|
|
@@ -180,7 +180,7 @@ class Stack
|
|
180
180
|
end
|
181
181
|
end
|
182
182
|
</ruby>
|
183
|
-
|
183
|
+
|
184
184
|
<pre>
|
185
185
|
$ spec stack_spec.rb -f s
|
186
186
|
|
@@ -206,7 +206,7 @@ class Stack
|
|
206
206
|
end
|
207
207
|
end
|
208
208
|
</ruby>
|
209
|
-
|
209
|
+
|
210
210
|
<pre>
|
211
211
|
spec stack_spec.rb -f s
|
212
212
|
|
@@ -12,7 +12,7 @@ context "An empty stack" do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
</ruby>
|
15
|
-
|
15
|
+
|
16
16
|
<pre>
|
17
17
|
$ spec stack_spec.rb -f s
|
18
18
|
|
@@ -38,7 +38,7 @@ context "An empty stack" do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
</ruby>
|
41
|
-
|
41
|
+
|
42
42
|
<pre>
|
43
43
|
$ spec stack_spec.rb -f s
|
44
44
|
|
@@ -65,7 +65,7 @@ context "An empty stack" do
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
</ruby>
|
68
|
-
|
68
|
+
|
69
69
|
<pre>
|
70
70
|
$ spec stack_spec.rb -f s
|
71
71
|
|
@@ -96,7 +96,7 @@ class Stack
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
</ruby>
|
99
|
-
|
99
|
+
|
100
100
|
<pre>
|
101
101
|
$ spec stack_spec.rb -f s
|
102
102
|
|
@@ -126,7 +126,7 @@ context "An empty stack" do
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
</ruby>
|
129
|
-
|
129
|
+
|
130
130
|
<pre>
|
131
131
|
$ spec stack_spec.rb -f s
|
132
132
|
|
@@ -161,7 +161,7 @@ class Stack
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
</ruby>
|
164
|
-
|
164
|
+
|
165
165
|
<pre>
|
166
166
|
$ spec stack_spec.rb -f s
|
167
167
|
|
@@ -18,7 +18,7 @@ context "A stack with one item" do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
</ruby>
|
21
|
-
|
21
|
+
|
22
22
|
<pre>
|
23
23
|
$ spec stack_spec.rb -f s
|
24
24
|
|
@@ -49,7 +49,7 @@ context "A stack with one item" do
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
</ruby>
|
52
|
-
|
52
|
+
|
53
53
|
<pre>
|
54
54
|
$ spec stack_spec.rb -f s
|
55
55
|
|
@@ -81,7 +81,7 @@ context "A stack with one item" do
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
</ruby>
|
84
|
-
|
84
|
+
|
85
85
|
<pre>
|
86
86
|
$ spec stack_spec.rb -f s
|
87
87
|
|
@@ -113,7 +113,7 @@ class Stack
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
</ruby>
|
116
|
-
|
116
|
+
|
117
117
|
<pre>
|
118
118
|
$ spec stack_spec.rb -f s
|
119
119
|
|
@@ -146,7 +146,7 @@ class Stack
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
</ruby>
|
149
|
-
|
149
|
+
|
150
150
|
<pre>
|
151
151
|
$ spec stack_spec.rb -f s
|
152
152
|
|
@@ -187,7 +187,7 @@ class Stack
|
|
187
187
|
end
|
188
188
|
end
|
189
189
|
</ruby>
|
190
|
-
|
190
|
+
|
191
191
|
<pre>
|
192
192
|
$ spec stack_spec.rb -f s
|
193
193
|
|
@@ -224,7 +224,7 @@ class Stack
|
|
224
224
|
end
|
225
225
|
end
|
226
226
|
</ruby>
|
227
|
-
|
227
|
+
|
228
228
|
<pre>
|
229
229
|
$ spec stack_spec.rb -f s
|
230
230
|
|
@@ -257,7 +257,7 @@ class Stack
|
|
257
257
|
end
|
258
258
|
end
|
259
259
|
</ruby>
|
260
|
-
|
260
|
+
|
261
261
|
<pre>
|
262
262
|
$ spec stack_spec.rb -f s
|
263
263
|
|
@@ -95,7 +95,7 @@ context "A stack with one item" do
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
</ruby>
|
98
|
-
|
98
|
+
|
99
99
|
<pre>
|
100
100
|
$ spec stack_spec.rb -f s
|
101
101
|
|
@@ -143,7 +143,7 @@ context "A stack with one item" do
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
</ruby>
|
146
|
-
|
146
|
+
|
147
147
|
<pre>
|
148
148
|
$ spec stack_spec.rb -f s
|
149
149
|
|
data/lib/spec/api/sugar.rb
CHANGED
@@ -17,13 +17,13 @@ module Spec
|
|
17
17
|
__orig_method_missing(sym, *args, &block)
|
18
18
|
end
|
19
19
|
|
20
|
-
def __is_sweetened?
|
20
|
+
def __is_sweetened?(sym) #:nodoc:
|
21
21
|
return true if sym.to_s =~ /^should_/
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
module MessageExpectationSugar
|
26
|
-
def __is_sweetened?
|
26
|
+
def __is_sweetened?(sym) #:nodoc:
|
27
27
|
return true if sym.to_s =~ /^and_|^at_|^any_|^once_/
|
28
28
|
end
|
29
29
|
end
|
@@ -35,7 +35,7 @@ class Object #:nodoc:
|
|
35
35
|
end
|
36
36
|
|
37
37
|
class Spec::Api::Mock #:nodoc:
|
38
|
-
#NOTE: this resolves a bug caused by a conflict between Sugar#method_missing and Mock#method_missing, specifically
|
38
|
+
# NOTE: this resolves a bug caused by a conflict between Sugar#method_missing and Mock#method_missing, specifically
|
39
39
|
# when the mock is set null_object=>true. It would be nice to get rid of this.
|
40
40
|
def should_receive(sym, &block)
|
41
41
|
return receive(sym, &block)
|
@@ -22,18 +22,24 @@ module Spec
|
|
22
22
|
# +name+ is the name of the context and +first+ is true if it is the
|
23
23
|
# first context - otherwise it's false.
|
24
24
|
#
|
25
|
+
# The next method to be invoked after this is #spec_started
|
26
|
+
def add_context(name, first)
|
27
|
+
end
|
28
|
+
|
29
|
+
# This method is invoked right before a spec is executed.
|
25
30
|
# The next method to be invoked after this one is one of #spec_failed
|
26
31
|
# or #spec_passed.
|
27
|
-
def
|
32
|
+
def spec_started(name)
|
28
33
|
end
|
29
34
|
|
30
|
-
# This method is invoked
|
35
|
+
# This method is invoked when a spec fails, i.e. an exception occurred
|
31
36
|
# inside it (such as a failed should or other exception). +name+ is the name
|
32
|
-
# of the specification.
|
33
|
-
|
37
|
+
# of the specification. +counter+ is the sequence number of the failure
|
38
|
+
# (starting at 1) and +failure+ is the associated Failure object.
|
39
|
+
def spec_failed(name, counter, failure)
|
34
40
|
end
|
35
41
|
|
36
|
-
# This method is invoked
|
42
|
+
# This method is invoked when a spec passes. +name+ is the name of the
|
37
43
|
# specification.
|
38
44
|
def spec_passed(name)
|
39
45
|
end
|
data/lib/spec/runner/reporter.rb
CHANGED
@@ -16,6 +16,11 @@ module Spec
|
|
16
16
|
@context_names << name
|
17
17
|
end
|
18
18
|
|
19
|
+
def spec_started(name)
|
20
|
+
@spec_names << name
|
21
|
+
@formatter.spec_started(name)
|
22
|
+
end
|
23
|
+
|
19
24
|
def spec_finished(name, error=nil, failure_location=nil)
|
20
25
|
if error.nil?
|
21
26
|
spec_passed(name)
|
@@ -58,14 +63,12 @@ module Spec
|
|
58
63
|
end
|
59
64
|
|
60
65
|
def spec_passed(name)
|
61
|
-
@spec_names << name
|
62
66
|
@formatter.spec_passed(name)
|
63
67
|
end
|
64
68
|
|
65
69
|
def spec_failed(name, failure)
|
66
|
-
@spec_names << name
|
67
70
|
@failures << failure
|
68
|
-
@formatter.spec_failed(name, @failures.length)
|
71
|
+
@formatter.spec_failed(name, @failures.length, failure)
|
69
72
|
end
|
70
73
|
|
71
74
|
class Failure
|
@@ -0,0 +1,485 @@
|
|
1
|
+
# Taken from http://dark.fhtr.org/ruby2ruby.rb
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'parse_tree'
|
5
|
+
require 'support'
|
6
|
+
require 'sexp_processor'
|
7
|
+
|
8
|
+
|
9
|
+
class RubySource < String
|
10
|
+
|
11
|
+
def inspect
|
12
|
+
"\n"+to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
class Object
|
19
|
+
|
20
|
+
def parse_tree(method_name=nil)
|
21
|
+
if method_name
|
22
|
+
m = method(method_name)
|
23
|
+
klass = m.defined_in
|
24
|
+
method_name = m.name
|
25
|
+
return ParseTree.new.parse_tree_for_method(klass, method_name)
|
26
|
+
elsif is_a?(Class)
|
27
|
+
klass = self
|
28
|
+
else
|
29
|
+
klass = self.class
|
30
|
+
end
|
31
|
+
ParseTree.new.parse_tree(klass).first
|
32
|
+
end
|
33
|
+
|
34
|
+
def source(method_name=nil)
|
35
|
+
RubySource.new RubyToRuby.new.process(parse_tree(method_name))
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
class Method
|
42
|
+
|
43
|
+
def defined_in
|
44
|
+
full_name = to_s.split(" ").last.chop
|
45
|
+
klass_name = full_name.split(/[\#\.]/).first
|
46
|
+
if klass_name.include?("(")
|
47
|
+
klass_name = klass_name.split("(").last.chop
|
48
|
+
end
|
49
|
+
klass = klass_name.split("::").inject(Object){|o,n| o.const_get(n)}
|
50
|
+
klass
|
51
|
+
end
|
52
|
+
|
53
|
+
def name
|
54
|
+
full_name = to_s.split(" ").last.chop
|
55
|
+
full_name.split(/[\#\.]/).last
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
class RubyToRuby < SexpProcessor
|
62
|
+
|
63
|
+
def self.translate(klass, method=nil)
|
64
|
+
RubySource.new(
|
65
|
+
unless method.nil? then
|
66
|
+
self.new.process(ParseTree.new.parse_tree_for_method(klass, method))
|
67
|
+
else
|
68
|
+
self.new.process(ParseTree.new.parse_tree(klass).first) # huh? why is the :class node wrapped?
|
69
|
+
end
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
def initialize
|
74
|
+
super
|
75
|
+
@env = Environment.new
|
76
|
+
@indent = " "
|
77
|
+
self.auto_shift_type = true
|
78
|
+
self.strict = true
|
79
|
+
self.expected = String
|
80
|
+
end
|
81
|
+
|
82
|
+
def indent(s)
|
83
|
+
s.to_s.map{|line| @indent + line}.join
|
84
|
+
end
|
85
|
+
|
86
|
+
def process_and(exp)
|
87
|
+
"(#{process exp.shift} and #{process exp.shift})"
|
88
|
+
end
|
89
|
+
|
90
|
+
def process_args(exp)
|
91
|
+
args = []
|
92
|
+
|
93
|
+
until exp.empty? do
|
94
|
+
arg = exp.shift
|
95
|
+
if arg.is_a? Array
|
96
|
+
args[-(arg.size-1)..-1] = arg[1..-1].map{|a| process a}
|
97
|
+
else
|
98
|
+
args << arg
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
args.empty? ? "" : "(#{args.join ', '})"
|
103
|
+
end
|
104
|
+
|
105
|
+
def process_array(exp)
|
106
|
+
code = []
|
107
|
+
until exp.empty? do
|
108
|
+
code << process(exp.shift)
|
109
|
+
end
|
110
|
+
return "[" + code.join(", ") + "]"
|
111
|
+
end
|
112
|
+
|
113
|
+
def process_attrasgn(exp)
|
114
|
+
process_call(exp)
|
115
|
+
end
|
116
|
+
|
117
|
+
def process_begin(exp)
|
118
|
+
s = "begin\n"
|
119
|
+
s << (process(exp.shift).to_s + "\n") until exp.empty?
|
120
|
+
s + "\nend"
|
121
|
+
end
|
122
|
+
|
123
|
+
def process_block(exp)
|
124
|
+
code = []
|
125
|
+
catch_block_arg = false
|
126
|
+
until exp.empty? do
|
127
|
+
if catch_block_arg
|
128
|
+
if exp.first and exp.first.first == :block_arg
|
129
|
+
code[-1] = code[-1][0..-2] + ", #{process(exp.shift)})"
|
130
|
+
end
|
131
|
+
catch_block_arg = false
|
132
|
+
else
|
133
|
+
if exp.first.first == :args
|
134
|
+
catch_block_arg = true
|
135
|
+
end
|
136
|
+
if [:ensure, :rescue].include? exp.first.first
|
137
|
+
code << process(exp.shift)
|
138
|
+
else
|
139
|
+
code << indent(process(exp.shift))
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
body = code.join("\n")
|
145
|
+
body += "\n"
|
146
|
+
|
147
|
+
return body
|
148
|
+
end
|
149
|
+
|
150
|
+
def process_block_arg(exp)
|
151
|
+
"&#{exp.shift}"
|
152
|
+
end
|
153
|
+
|
154
|
+
def process_block_pass(exp)
|
155
|
+
bname = process(exp.shift)
|
156
|
+
fcall = process(exp.shift)
|
157
|
+
if fcall[-1,1] == ')'
|
158
|
+
"#{fcall[0..-2]}, &(#{bname}))"
|
159
|
+
else
|
160
|
+
"#{fcall}(&(#{bname}))"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def process_call(exp)
|
165
|
+
receiver = process exp.shift
|
166
|
+
name = exp.shift
|
167
|
+
args_exp = exp.shift
|
168
|
+
if args_exp && args_exp.first == :array
|
169
|
+
args = "#{process(args_exp)[1..-2]}"
|
170
|
+
else
|
171
|
+
args = process args_exp
|
172
|
+
end
|
173
|
+
|
174
|
+
case name
|
175
|
+
when :<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :% then #
|
176
|
+
"(#{receiver} #{name} #{args})"
|
177
|
+
when :[] then
|
178
|
+
"#{receiver}[#{args}]"
|
179
|
+
else
|
180
|
+
"#{receiver}.#{name}#{args ? "(#{args})" : args}"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def process_case(exp)
|
185
|
+
s = "case #{process exp.shift}\n"
|
186
|
+
until exp.empty?
|
187
|
+
pt = exp.shift
|
188
|
+
if pt and pt.first == :when
|
189
|
+
s << "#{process(pt)}\n"
|
190
|
+
else
|
191
|
+
s << "else\n#{indent(process(pt))}\n"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
s + "\nend"
|
195
|
+
end
|
196
|
+
|
197
|
+
def process_class(exp)
|
198
|
+
s = "class #{exp.shift} < #{exp.shift}\n"
|
199
|
+
body = ""
|
200
|
+
body << "#{process exp.shift}\n\n" until exp.empty?
|
201
|
+
s + indent(body) + "end"
|
202
|
+
end
|
203
|
+
|
204
|
+
def process_colon2(exp)
|
205
|
+
"#{process(exp.shift)}::#{exp.shift}"
|
206
|
+
end
|
207
|
+
|
208
|
+
def process_const(exp)
|
209
|
+
exp.shift.to_s
|
210
|
+
end
|
211
|
+
|
212
|
+
def process_dasgn_curr(exp)
|
213
|
+
s = exp.shift.to_s
|
214
|
+
unless exp.empty?
|
215
|
+
s += "=" + process(exp.shift)
|
216
|
+
else
|
217
|
+
if(@block_params)
|
218
|
+
s
|
219
|
+
else
|
220
|
+
""
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def process_defn(exp)
|
226
|
+
if exp[1].first == :cfunc
|
227
|
+
s = "# method '#{exp.shift}' defined in a C function"
|
228
|
+
exp.shift
|
229
|
+
return s
|
230
|
+
else
|
231
|
+
name = exp.shift
|
232
|
+
args = process(exp.shift)
|
233
|
+
return "def #{name}#{args}end".gsub(/\n\s*\n+/, "\n")
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def process_dot2(exp)
|
238
|
+
"(#{process exp.shift}..#{process exp.shift})"
|
239
|
+
end
|
240
|
+
|
241
|
+
def process_dot3(exp)
|
242
|
+
"(#{process exp.shift}...#{process exp.shift})"
|
243
|
+
end
|
244
|
+
|
245
|
+
def process_dstr(exp)
|
246
|
+
s = exp.shift.dump[0..-2]
|
247
|
+
until exp.empty?
|
248
|
+
pt = exp.shift
|
249
|
+
if pt.first == :str
|
250
|
+
s << process(pt)[1..-2]
|
251
|
+
else
|
252
|
+
s << '#{' + process(pt) + '}'
|
253
|
+
end
|
254
|
+
end
|
255
|
+
s + '"'
|
256
|
+
end
|
257
|
+
|
258
|
+
def process_dvar(exp)
|
259
|
+
exp.shift.to_s
|
260
|
+
end
|
261
|
+
|
262
|
+
def process_ensure(exp)
|
263
|
+
process(exp.shift) + "\n" +
|
264
|
+
"ensure\n" +
|
265
|
+
indent(process(exp.shift))
|
266
|
+
end
|
267
|
+
|
268
|
+
def process_false(exp)
|
269
|
+
"false"
|
270
|
+
end
|
271
|
+
|
272
|
+
def process_fbody(exp)
|
273
|
+
process(exp.shift)
|
274
|
+
end
|
275
|
+
|
276
|
+
def process_fcall(exp)
|
277
|
+
exp_orig = exp.deep_clone
|
278
|
+
# [:fcall, :puts, [:array, [:str, "This is a weird loop"]]]
|
279
|
+
name = exp.shift.to_s
|
280
|
+
args = exp.shift
|
281
|
+
code = []
|
282
|
+
unless args.nil? then
|
283
|
+
assert_type args, :array
|
284
|
+
args.shift # :array
|
285
|
+
until args.empty? do
|
286
|
+
code << process(args.shift)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
return "#{name}(#{code.join(', ')})"
|
290
|
+
end
|
291
|
+
|
292
|
+
def process_for(exp)
|
293
|
+
s = "for #{process(exp[1])} in #{process(exp[0])}\n"
|
294
|
+
2.times{ exp.shift }
|
295
|
+
s += indent("#{process(exp.shift)}\n")
|
296
|
+
s += "end"
|
297
|
+
end
|
298
|
+
|
299
|
+
def process_gvar(exp)
|
300
|
+
exp.shift.to_s
|
301
|
+
end
|
302
|
+
|
303
|
+
def process_hash(exp)
|
304
|
+
body = []
|
305
|
+
body << "#{process(exp.shift)} => #{process(exp.shift)}" until exp.empty?
|
306
|
+
body_str = ""
|
307
|
+
body_str = "\n"+indent(body.join(",\n"))+"\n" unless body.empty?
|
308
|
+
"{" + body_str + "}"
|
309
|
+
end
|
310
|
+
|
311
|
+
def process_iasgn(exp)
|
312
|
+
"#{exp.shift} = #{process exp.shift}"
|
313
|
+
end
|
314
|
+
|
315
|
+
def cond_indent_process(pt)
|
316
|
+
(pt and pt.first == :block) ? process(pt) : indent(process(pt))
|
317
|
+
end
|
318
|
+
|
319
|
+
def process_if(exp)
|
320
|
+
s = ["if (#{process exp.shift})"]
|
321
|
+
s << "#{cond_indent_process(exp.shift)}"
|
322
|
+
s << "else\n#{cond_indent_process(exp.shift)}" until exp.empty?
|
323
|
+
s << "end"
|
324
|
+
s.join("\n")
|
325
|
+
end
|
326
|
+
|
327
|
+
def process_iter(exp)
|
328
|
+
owner = exp.shift
|
329
|
+
args = exp.shift
|
330
|
+
if !args.nil?
|
331
|
+
@block_params = true
|
332
|
+
end
|
333
|
+
processed_args = process args
|
334
|
+
block_args = processed_args.nil? ? "" : "|#{processed_args}|"
|
335
|
+
|
336
|
+
result = "#{process owner} {#{block_args}\n" +
|
337
|
+
indent("#{process exp.shift}\n") +
|
338
|
+
"}"
|
339
|
+
@block_params = false
|
340
|
+
result
|
341
|
+
end
|
342
|
+
|
343
|
+
def process_ivar(exp)
|
344
|
+
exp.shift.to_s
|
345
|
+
end
|
346
|
+
|
347
|
+
def process_lasgn(exp)
|
348
|
+
s = "#{exp.shift}"
|
349
|
+
s += " = #{process exp.shift}" unless exp.empty?
|
350
|
+
s
|
351
|
+
end
|
352
|
+
|
353
|
+
def process_lit(exp)
|
354
|
+
obj = exp.shift
|
355
|
+
if obj.is_a? Range # to get around how parsed ranges turn into lits and lose parens
|
356
|
+
"(" + obj.inspect + ")"
|
357
|
+
else
|
358
|
+
obj.inspect
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def process_lvar(exp)
|
363
|
+
exp.shift.to_s
|
364
|
+
end
|
365
|
+
|
366
|
+
def process_masgn(exp)
|
367
|
+
process(exp.shift)[1..-2]
|
368
|
+
end
|
369
|
+
|
370
|
+
def process_module(exp)
|
371
|
+
s = "module #{exp.shift}\n"
|
372
|
+
body = ""
|
373
|
+
body << "#{process exp.shift}\n\n" until exp.empty?
|
374
|
+
s + indent(body) + "end"
|
375
|
+
end
|
376
|
+
|
377
|
+
def process_nil(exp)
|
378
|
+
"nil"
|
379
|
+
end
|
380
|
+
|
381
|
+
def process_not(exp)
|
382
|
+
"(not #{process exp.shift})"
|
383
|
+
end
|
384
|
+
|
385
|
+
def process_or(exp)
|
386
|
+
"(#{process exp.shift} or #{process exp.shift})"
|
387
|
+
end
|
388
|
+
|
389
|
+
def process_resbody(exp)
|
390
|
+
s = "rescue "
|
391
|
+
unless exp.empty?
|
392
|
+
if exp.first.first == :array
|
393
|
+
s << process(exp.shift)[1..-2]
|
394
|
+
end
|
395
|
+
s << "\n"
|
396
|
+
end
|
397
|
+
s << (process(exp.shift).to_s + "\n") until exp.empty?
|
398
|
+
s
|
399
|
+
end
|
400
|
+
|
401
|
+
def process_rescue(exp)
|
402
|
+
s = ""
|
403
|
+
s << (process(exp.shift).to_s + "\n") until exp.empty?
|
404
|
+
s
|
405
|
+
end
|
406
|
+
|
407
|
+
def process_retry(exp)
|
408
|
+
"retry"
|
409
|
+
end
|
410
|
+
|
411
|
+
def process_return(exp)
|
412
|
+
return "return #{process exp.shift}"
|
413
|
+
end
|
414
|
+
|
415
|
+
def process_scope(exp)
|
416
|
+
return process(exp.shift)
|
417
|
+
end
|
418
|
+
|
419
|
+
def process_self(exp)
|
420
|
+
"self"
|
421
|
+
end
|
422
|
+
def process_str(exp)
|
423
|
+
return exp.shift.dump
|
424
|
+
end
|
425
|
+
|
426
|
+
def process_super(exp)
|
427
|
+
"super(#{process(exp.shift)})"
|
428
|
+
end
|
429
|
+
|
430
|
+
def process_true(exp)
|
431
|
+
"true"
|
432
|
+
end
|
433
|
+
|
434
|
+
def process_until(exp)
|
435
|
+
cond_loop(exp, 'until')
|
436
|
+
end
|
437
|
+
|
438
|
+
def process_vcall(exp)
|
439
|
+
return exp.shift.to_s
|
440
|
+
end
|
441
|
+
|
442
|
+
def process_when(exp)
|
443
|
+
"when #{process(exp.shift).to_s[1..-2]}\n#{indent(process(exp.shift))}"
|
444
|
+
end
|
445
|
+
|
446
|
+
def process_while(exp)
|
447
|
+
cond_loop(exp, 'while')
|
448
|
+
end
|
449
|
+
|
450
|
+
def process_yield(exp)
|
451
|
+
body = process(exp.shift)[1..-2] unless exp.empty?
|
452
|
+
"yield#{body and "(#{body})"}"
|
453
|
+
end
|
454
|
+
|
455
|
+
def process_zarray(exp)
|
456
|
+
"[]"
|
457
|
+
end
|
458
|
+
|
459
|
+
def process_zsuper(exp)
|
460
|
+
"super"
|
461
|
+
end
|
462
|
+
|
463
|
+
# def process_dxstr(exp)
|
464
|
+
# puts "DXSTR:#{exp.shift}"
|
465
|
+
# end
|
466
|
+
|
467
|
+
def cond_loop(exp, name)
|
468
|
+
cond = process(exp.shift)
|
469
|
+
body = cond_indent_process(exp.shift)
|
470
|
+
head_controlled = exp.empty? ? false : exp.shift
|
471
|
+
|
472
|
+
code = []
|
473
|
+
if head_controlled then
|
474
|
+
code << "#{name} (#{cond}) do"
|
475
|
+
code << body
|
476
|
+
code << "end"
|
477
|
+
else
|
478
|
+
code << "begin"
|
479
|
+
code << body
|
480
|
+
code << "end #{name} (#{cond})"
|
481
|
+
end
|
482
|
+
code.join("\n")
|
483
|
+
end
|
484
|
+
|
485
|
+
end
|