ruby2ruby 1.3.0 → 1.3.1

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.tar.gz.sig CHANGED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,22 @@
1
+ === 1.3.1 / 2011-09-22
2
+
3
+ * 1 minor enhancement:
4
+
5
+ * Added parenthesize to add parens in certain contexts.
6
+
7
+ * 10 bug fixes:
8
+
9
+ * Add newline to 'do nothing' comment in a block... seems contrived. (andreacampi)
10
+ * Binary operations not work properly with some complex statements. (smorss)
11
+ * Fixed if statements with no body (smorss)
12
+ * Fixed logic for call with hash args in various locations (smorss)
13
+ * Fixed match3 on an assignment. (smorss)
14
+ * Fixed multiple nested rescue/ensure exprs (larsch)
15
+ * Fixed process_alias to parenthesize (smorss)
16
+ * Fixed process_and to parenthenize only when it makes sense.
17
+ * Fixed rescue with 2+ statements in resbody (smorss)
18
+ * Regexps with options other than /o were not showing flags. (smorss)
19
+
1
20
  === 1.3.0 / 2011-09-01
2
21
 
3
22
  * 1 minor enhancement:
data/lib/ruby2ruby.rb CHANGED
@@ -3,14 +3,36 @@
3
3
  require 'rubygems'
4
4
  require 'sexp_processor'
5
5
 
6
+ # REFACTOR: stolen from ruby_parser
7
+ class Regexp
8
+ unless defined? ENC_NONE then
9
+ ENC_NONE = /x/n.options
10
+ ENC_EUC = /x/e.options
11
+ ENC_SJIS = /x/s.options
12
+ ENC_UTF8 = /x/u.options
13
+
14
+ CODES = {
15
+ EXTENDED => 'x',
16
+ IGNORECASE => 'i',
17
+ MULTILINE => 'm',
18
+ ENC_NONE => 'n',
19
+ ENC_EUC => 'e',
20
+ ENC_SJIS => 's',
21
+ ENC_UTF8 => 'u',
22
+ }
23
+ end
24
+ end
25
+
6
26
  class Ruby2Ruby < SexpProcessor
7
- VERSION = '1.3.0'
27
+ VERSION = '1.3.1'
8
28
  LINE_LENGTH = 78
9
29
 
10
30
  BINARY = [:<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>>, :**]
11
31
 
12
32
  ##
13
33
  # Nodes that represent assignment and probably need () around them.
34
+ #
35
+ # TODO: this should be replaced with full precedence support :/
14
36
 
15
37
  ASSIGN_NODES = [
16
38
  :dasgn,
@@ -24,6 +46,7 @@ class Ruby2Ruby < SexpProcessor
24
46
  :op_asgn_and,
25
47
  :op_asgn_or,
26
48
  :return,
49
+ :if, # HACK
27
50
  ]
28
51
 
29
52
  def initialize
@@ -42,11 +65,11 @@ class Ruby2Ruby < SexpProcessor
42
65
  # Processors
43
66
 
44
67
  def process_alias(exp)
45
- "alias #{process(exp.shift)} #{process(exp.shift)}"
68
+ parenthesize "alias #{process(exp.shift)} #{process(exp.shift)}"
46
69
  end
47
70
 
48
71
  def process_and(exp)
49
- "(#{process exp.shift} and #{process exp.shift})"
72
+ parenthesize "#{process exp.shift} and #{process exp.shift}"
50
73
  end
51
74
 
52
75
  def process_arglist(exp) # custom made node
@@ -118,7 +141,7 @@ class Ruby2Ruby < SexpProcessor
118
141
  code << "begin"
119
142
  until exp.empty?
120
143
  src = process(exp.shift)
121
- src = indent(src) unless src =~ /(^|\n)rescue/ # ensure no level 0 rescues
144
+ src = indent(src) unless src =~ /(^|\n)(rescue|ensure)/ # ensure no level 0 rescues
122
145
  code << src
123
146
  end
124
147
  code << "end"
@@ -132,24 +155,27 @@ class Ruby2Ruby < SexpProcessor
132
155
  until exp.empty? do
133
156
  code = exp.shift
134
157
  if code.nil? or code.first == :nil then
135
- result << "# do nothing"
158
+ result << "# do nothing\n"
136
159
  else
137
160
  result << process(code)
138
161
  end
139
162
  end
140
163
 
141
- result = result.join "\n"
142
-
143
- result = case self.context[1]
144
- when nil, :scope, :if, :iter, :resbody, :when, :while then
145
- result + "\n"
146
- else
147
- "(#{result})"
148
- end
164
+ result = parenthesize result.join "\n"
165
+ result += "\n" unless result.start_with? "("
149
166
 
150
167
  return result
151
168
  end
152
169
 
170
+ def parenthesize exp
171
+ case self.context[1]
172
+ when nil, :scope, :if, :iter, :resbody, :when, :while then
173
+ exp
174
+ else
175
+ "(#{exp})"
176
+ end
177
+ end
178
+
153
179
  def process_block_pass exp
154
180
  raise "huh?: #{exp.inspect}" if exp.size > 1
155
181
 
@@ -169,9 +195,7 @@ class Ruby2Ruby < SexpProcessor
169
195
  def process_call(exp)
170
196
  receiver_node_type = exp.first.nil? ? nil : exp.first.first
171
197
  receiver = process exp.shift
172
-
173
- receiver = "(#{receiver})" if
174
- Ruby2Ruby::ASSIGN_NODES.include? receiver_node_type
198
+ receiver = "(#{receiver})" if ASSIGN_NODES.include? receiver_node_type
175
199
 
176
200
  name = exp.shift
177
201
  args = []
@@ -183,8 +207,20 @@ class Ruby2Ruby < SexpProcessor
183
207
 
184
208
  in_context :arglist do
185
209
  until exp.empty? do
210
+ arg_type = exp.first.sexp_type
186
211
  arg = process exp.shift
187
- args << arg unless arg.empty?
212
+
213
+ next if arg.empty?
214
+
215
+ strip_hash = (arg_type == :hash and
216
+ not BINARY.include? name and
217
+ (exp.empty? or exp.first.sexp_type == :splat))
218
+ wrap_arg = Ruby2Ruby::ASSIGN_NODES.include? arg_type
219
+
220
+ arg = arg[2..-3] if strip_hash
221
+ arg = "(#{arg})" if wrap_arg
222
+
223
+ args << arg
188
224
  end
189
225
  end
190
226
 
@@ -332,8 +368,15 @@ class Ruby2Ruby < SexpProcessor
332
368
  "(#{process exp.shift}...#{process exp.shift})"
333
369
  end
334
370
 
371
+ def re_opt options
372
+ bits = (0..8).map { |n| options[n] * 2**n }
373
+ bits.delete 0
374
+ bits.map { |n| Regexp::CODES[n] }.join
375
+ end
376
+
335
377
  def process_dregx(exp)
336
- "/" << util_dthing(:dregx, exp) << "/"
378
+ options = re_opt exp.pop if Fixnum === exp.last
379
+ "/" << util_dthing(:dregx, exp) << "/#{options}"
337
380
  end
338
381
 
339
382
  def process_dregx_once(exp)
@@ -357,8 +400,10 @@ class Ruby2Ruby < SexpProcessor
357
400
  ens = exp.shift
358
401
  ens = nil if ens == s(:nil)
359
402
  ens = process(ens) || "# do nothing"
403
+ ens = "begin\n#{ens}\nend\n" if ens =~ /(^|\n)rescue/
360
404
 
361
405
  body.sub!(/\n\s*end\z/, '')
406
+ body = indent(body) unless body =~ /(^|\n)rescue/
362
407
 
363
408
  return "#{body}\nensure\n#{indent ens}"
364
409
  end
@@ -401,6 +446,7 @@ class Ruby2Ruby < SexpProcessor
401
446
 
402
447
  def process_hash(exp)
403
448
  result = []
449
+
404
450
  until exp.empty?
405
451
  lhs = process(exp.shift)
406
452
  rhs = exp.shift
@@ -411,21 +457,7 @@ class Ruby2Ruby < SexpProcessor
411
457
  result << "#{lhs} => #{rhs}"
412
458
  end
413
459
 
414
- case self.context[1]
415
- when :arglist, :argscat then
416
- unless result.empty? then
417
- # HACK - this will break w/ 2 hashes as args
418
- if BINARY.include? @calls.last then
419
- return "{ #{result.join(', ')} }"
420
- else
421
- return "#{result.join(', ')}"
422
- end
423
- else
424
- return "{}"
425
- end
426
- else
427
- return "{ #{result.join(', ')} }"
428
- end
460
+ return "{ #{result.join(', ')} }"
429
461
  end
430
462
 
431
463
  def process_iasgn(exp)
@@ -461,12 +493,15 @@ class Ruby2Ruby < SexpProcessor
461
493
  r << "end"
462
494
 
463
495
  r
464
- else
496
+ elsif f
465
497
  unless expand then
466
498
  r = "#{f} unless #{c}"
467
499
  return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/
468
500
  end
469
501
  "unless #{c} then\n#{indent(f)}\nend"
502
+ else
503
+ # empty if statement, just do it in case of side effects from condition
504
+ "if #{c} then\n#{indent '# do nothing'}\nend"
470
505
  end
471
506
  end
472
507
 
@@ -587,8 +622,14 @@ class Ruby2Ruby < SexpProcessor
587
622
 
588
623
  def process_match3(exp)
589
624
  rhs = process(exp.shift)
625
+ left_type = exp.first.sexp_type
590
626
  lhs = process(exp.shift)
591
- "#{lhs} =~ #{rhs}"
627
+
628
+ if ASSIGN_NODES.include? left_type then
629
+ "(#{lhs}) =~ #{rhs}"
630
+ else
631
+ "#{lhs} =~ #{rhs}"
632
+ end
592
633
  end
593
634
 
594
635
  def process_module(exp)
@@ -681,12 +722,14 @@ class Ruby2Ruby < SexpProcessor
681
722
  els = process(exp.pop) unless exp.last.first == :resbody
682
723
 
683
724
  body ||= "# do nothing"
684
- simple = exp.size == 1
725
+ simple = exp.size == 1 && !exp.resbody.block
726
+
685
727
 
686
728
  resbodies = []
687
729
  until exp.empty? do
688
730
  resbody = exp.shift
689
- simple &&= resbody[1] == s(:array) && resbody[2] != nil
731
+ simple &&= resbody[1] == s(:array)
732
+ simple &&= resbody[2] != nil && resbody[2].node_type != :block
690
733
  resbodies << process(resbody)
691
734
  end
692
735
 
@@ -866,9 +909,10 @@ class Ruby2Ruby < SexpProcessor
866
909
  def rewrite_rescue exp
867
910
  complex = false
868
911
  complex ||= exp.size > 3
869
- complex ||= exp.block
912
+ complex ||= exp.resbody.block
870
913
  complex ||= exp.find_nodes(:resbody).any? { |n| n[1] != s(:array) }
871
914
  complex ||= exp.find_nodes(:resbody).any? { |n| n.last.nil? }
915
+ complex ||= exp.find_nodes(:resbody).any? { |n| n[2] and n[2].node_type == :block }
872
916
 
873
917
  handled = context.first == :ensure
874
918
 
@@ -924,8 +968,7 @@ class Ruby2Ruby < SexpProcessor
924
968
  raise "unknown type: #{pt.inspect}"
925
969
  end
926
970
  else
927
- # HACK: raise "huh?: #{pt.inspect}" -- hitting # constants in regexps
928
- # do nothing for now
971
+ raise "unhandled value in d-thing: #{pt.inspect}"
929
972
  end
930
973
  end
931
974
 
@@ -72,6 +72,12 @@ class TestRuby2Ruby < R2RTestCase
72
72
  assert_equal exp, eval(out)
73
73
  end
74
74
 
75
+ def test_and_alias
76
+ inn = s(:and, s(:true), s(:alias, s(:lit, :a), s(:lit, :b)))
77
+ out = "true and (alias :a :b)"
78
+ util_compare inn, out
79
+ end
80
+
75
81
  def test_dregx_slash
76
82
  inn = util_thingy(:dregx)
77
83
  out = '/a"b#{(1 + 1)}c"d\/e/'
@@ -103,6 +109,51 @@ class TestRuby2Ruby < R2RTestCase
103
109
  "self[42] = 24")
104
110
  end
105
111
 
112
+ def test_call_arglist_hash_first
113
+ inn = s(:call, nil, :method,
114
+ s(:arglist,
115
+ s(:hash, s(:lit, :a), s(:lit, 1)),
116
+ s(:call, nil, :b, s(:arglist))))
117
+ out = "method({ :a => 1 }, b)"
118
+
119
+ util_compare inn, out
120
+ end
121
+
122
+ def test_call_arglist_hash_first_last
123
+ inn = s(:call, nil, :method,
124
+ s(:arglist,
125
+ s(:hash, s(:lit, :a), s(:lit, 1)),
126
+ s(:call, nil, :b, s(:arglist)),
127
+ s(:hash, s(:lit, :c), s(:lit, 1))))
128
+ out = "method({ :a => 1 }, b, :c => 1)"
129
+
130
+ util_compare inn, out
131
+ end
132
+
133
+ def test_call_arglist_hash_last
134
+ inn = s(:call, nil, :method,
135
+ s(:arglist,
136
+ s(:call, nil, :b, s(:arglist)),
137
+ s(:hash, s(:lit, :a), s(:lit, 1))))
138
+ out = "method(b, :a => 1)"
139
+
140
+ util_compare inn, out
141
+ end
142
+
143
+ def test_call_arglist_if
144
+ inn = s(:call,
145
+ s(:call, nil, :a, s(:arglist)),
146
+ :+,
147
+ s(:arglist,
148
+ s(:if,
149
+ s(:call, nil, :b, s(:arglist)),
150
+ s(:call, nil, :c, s(:arglist)),
151
+ s(:call, nil, :d, s(:arglist)))))
152
+
153
+ out = "(a + (b ? (c) : (d)))"
154
+ util_compare inn, out
155
+ end
156
+
106
157
  def test_masgn_wtf
107
158
  inn = s(:block,
108
159
  s(:masgn,
@@ -124,7 +175,6 @@ class TestRuby2Ruby < R2RTestCase
124
175
  util_compare inn, out
125
176
  end
126
177
 
127
-
128
178
  def test_masgn_splat_wtf
129
179
  inn = s(:masgn,
130
180
  s(:array, s(:lasgn, :k), s(:lasgn, :v)),
@@ -138,6 +188,13 @@ class TestRuby2Ruby < R2RTestCase
138
188
  util_compare inn, out
139
189
  end
140
190
 
191
+ def test_match3_asgn
192
+ inn = s(:match3, s(:lit, //), s(:lasgn, :y, s(:call, nil, :x, s(:arglist))))
193
+ out = "(y = x) =~ //"
194
+ # "y = x =~ //", which matches on x and assigns to y (not what sexp says).
195
+ util_compare inn, out
196
+ end
197
+
141
198
  def test_splat_call
142
199
  inn = s(:call, nil, :x,
143
200
  s(:arglist,
@@ -151,6 +208,19 @@ class TestRuby2Ruby < R2RTestCase
151
208
  util_compare inn, out
152
209
  end
153
210
 
211
+ def test_resbody_block
212
+ inn = s(:rescue,
213
+ s(:call, nil, :x1, s(:arglist)),
214
+ s(:resbody,
215
+ s(:array),
216
+ s(:block,
217
+ s(:call, nil, :x2, s(:arglist)),
218
+ s(:call, nil, :x3, s(:arglist)))))
219
+
220
+ out = "begin\n x1\nrescue\n x2\n x3\nend"
221
+ util_compare inn, out
222
+ end
223
+
154
224
  def test_resbody_short_with_begin_end
155
225
  # "begin; blah; rescue; []; end"
156
226
  inn = s(:rescue,
@@ -160,6 +230,18 @@ class TestRuby2Ruby < R2RTestCase
160
230
  util_compare inn, out
161
231
  end
162
232
 
233
+ def test_regexp_options
234
+ inn = s(:match3,
235
+ s(:dregx,
236
+ "abc",
237
+ s(:evstr, s(:call, nil, :x, s(:arglist))),
238
+ s(:str, "def"),
239
+ 4),
240
+ s(:str, "a"))
241
+ out = '"a" =~ /abc#{x}def/m'
242
+ util_compare inn, out
243
+ end
244
+
163
245
  def test_resbody_short_with_rescue_args
164
246
  inn = s(:rescue,
165
247
  s(:call, nil, :blah, s(:arglist)),
@@ -184,6 +266,12 @@ class TestRuby2Ruby < R2RTestCase
184
266
  util_compare inn, out
185
267
  end
186
268
 
269
+ def test_if_empty
270
+ inn = s(:if, s(:call, nil, :x, s(:arglist)), nil, nil)
271
+ out = "if x then\n # do nothing\nend"
272
+ util_compare inn, out
273
+ end
274
+
187
275
  def test_interpolation_and_escapes
188
276
  # log_entry = " \e[#{message_color}m#{message}\e[0m "
189
277
  inn = s(:lasgn, :log_entry,
@@ -218,6 +306,47 @@ class TestRuby2Ruby < R2RTestCase
218
306
  util_compare inn, out
219
307
  end
220
308
 
309
+ def test_basic_ensure
310
+ inn = s(:ensure, s(:lit, 1), s(:lit, 2))
311
+ out = "begin\n 1\nensure\n 2\nend"
312
+ util_compare inn, out
313
+ end
314
+
315
+ def test_nested_ensure
316
+ inn = s(:ensure, s(:lit, 1), s(:ensure, s(:lit, 2), s(:lit, 3)))
317
+ out = "begin\n 1\nensure\n begin\n 2\n ensure\n 3\n end\nend"
318
+ util_compare inn, out
319
+ end
320
+
321
+ def test_nested_rescue
322
+ inn = s(:ensure, s(:lit, 1), s(:rescue, s(:lit, 2), s(:resbody, s(:array), s(:lit, 3))))
323
+ out = "begin\n 1\nensure\n 2 rescue 3\nend"
324
+ util_compare inn, out
325
+ end
326
+
327
+ def test_nested_rescue_exception
328
+ inn = s(:ensure, s(:lit, 1), s(:rescue, s(:lit, 2), s(:resbody, s(:array, s(:const, :Exception)), s(:lit, 3))))
329
+ out = "begin\n 1\nensure\n begin\n 2\n rescue Exception\n 3\n end\nend"
330
+ util_compare inn, out
331
+ end
332
+
333
+ def test_nested_rescue_exception2
334
+ inn = s(:ensure, s(:rescue, s(:lit, 2), s(:resbody, s(:array, s(:const, :Exception)), s(:lit, 3))), s(:lit, 1))
335
+ out = "begin\n 2\nrescue Exception\n 3\nensure\n 1\nend"
336
+ util_compare inn, out
337
+ end
338
+
339
+ def test_rescue_block
340
+ inn = s(:rescue,
341
+ s(:call, nil, :alpha, s(:arglist)),
342
+ s(:resbody, s(:array),
343
+ s(:block,
344
+ s(:call, nil, :beta, s(:arglist)),
345
+ s(:call, nil, :gamma, s(:arglist)))))
346
+ out = "begin\n alpha\nrescue\n beta\n gamma\nend"
347
+ util_compare inn, out
348
+ end
349
+
221
350
  def util_compare sexp, expected_ruby, expected_eval = nil
222
351
  assert_equal expected_ruby, @processor.process(sexp)
223
352
  assert_equal expected_eval, eval(expected_ruby) if expected_eval
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby2ruby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 3
9
- - 0
10
- version: 1.3.0
9
+ - 1
10
+ version: 1.3.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ryan Davis
@@ -36,7 +36,7 @@ cert_chain:
36
36
  FBHgymkyj/AOSqKRIpXPhjC6
37
37
  -----END CERTIFICATE-----
38
38
 
39
- date: 2011-09-01 00:00:00 Z
39
+ date: 2011-09-22 00:00:00 Z
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: sexp_processor
metadata.gz.sig CHANGED
Binary file