unparser 0.1.5 → 0.1.6

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +38 -2
  3. data/.travis.yml +3 -6
  4. data/Changelog.md +7 -0
  5. data/Gemfile +1 -0
  6. data/Gemfile.devtools +22 -17
  7. data/README.md +3 -4
  8. data/TODO +3 -2
  9. data/bin/unparser +10 -0
  10. data/circle.yml +2 -0
  11. data/config/flay.yml +1 -1
  12. data/config/flog.yml +1 -1
  13. data/config/reek.yml +10 -0
  14. data/config/rubocop.yml +9 -17
  15. data/lib/unparser.rb +8 -1
  16. data/lib/unparser/buffer.rb +2 -0
  17. data/lib/unparser/cli.rb +113 -0
  18. data/lib/unparser/cli/differ.rb +30 -0
  19. data/lib/unparser/cli/preprocessor.rb +196 -0
  20. data/lib/unparser/cli/source.rb +118 -0
  21. data/lib/unparser/comments.rb +64 -23
  22. data/lib/unparser/constants.rb +19 -7
  23. data/lib/unparser/emitter.rb +23 -25
  24. data/lib/unparser/emitter/alias.rb +2 -0
  25. data/lib/unparser/emitter/argument.rb +2 -0
  26. data/lib/unparser/emitter/assignment.rb +3 -1
  27. data/lib/unparser/emitter/begin.rb +3 -6
  28. data/lib/unparser/emitter/binary.rb +2 -0
  29. data/lib/unparser/emitter/block.rb +2 -0
  30. data/lib/unparser/emitter/break.rb +4 -5
  31. data/lib/unparser/emitter/case.rb +2 -0
  32. data/lib/unparser/emitter/cbase.rb +2 -0
  33. data/lib/unparser/emitter/class.rb +4 -3
  34. data/lib/unparser/emitter/def.rb +2 -0
  35. data/lib/unparser/emitter/defined.rb +2 -0
  36. data/lib/unparser/emitter/empty.rb +2 -0
  37. data/lib/unparser/emitter/ensure.rb +2 -0
  38. data/lib/unparser/emitter/flipflop.rb +2 -0
  39. data/lib/unparser/emitter/for.rb +2 -0
  40. data/lib/unparser/emitter/hookexe.rb +2 -0
  41. data/lib/unparser/emitter/if.rb +2 -0
  42. data/lib/unparser/emitter/literal.rb +2 -0
  43. data/lib/unparser/emitter/literal/array.rb +33 -0
  44. data/lib/unparser/emitter/literal/dynamic.rb +21 -1
  45. data/lib/unparser/emitter/literal/dynamic_body.rb +9 -5
  46. data/lib/unparser/emitter/literal/execute_string.rb +2 -0
  47. data/lib/unparser/emitter/literal/hash.rb +136 -0
  48. data/lib/unparser/emitter/literal/primitive.rb +4 -2
  49. data/lib/unparser/emitter/literal/range.rb +2 -0
  50. data/lib/unparser/emitter/literal/regexp.rb +4 -2
  51. data/lib/unparser/emitter/literal/singleton.rb +2 -0
  52. data/lib/unparser/emitter/match.rb +2 -0
  53. data/lib/unparser/emitter/module.rb +2 -3
  54. data/lib/unparser/emitter/next.rb +2 -0
  55. data/lib/unparser/emitter/op_assign.rb +3 -1
  56. data/lib/unparser/emitter/redo.rb +2 -0
  57. data/lib/unparser/emitter/repetition.rb +2 -0
  58. data/lib/unparser/emitter/resbody.rb +2 -0
  59. data/lib/unparser/emitter/rescue.rb +2 -0
  60. data/lib/unparser/emitter/retry.rb +2 -0
  61. data/lib/unparser/emitter/return.rb +19 -4
  62. data/lib/unparser/emitter/root.rb +13 -0
  63. data/lib/unparser/emitter/send.rb +26 -22
  64. data/lib/unparser/emitter/send/arguments.rb +46 -0
  65. data/lib/unparser/emitter/send/attribute_assignment.rb +35 -0
  66. data/lib/unparser/emitter/send/binary.rb +2 -0
  67. data/lib/unparser/emitter/send/index.rb +2 -0
  68. data/lib/unparser/emitter/send/regular.rb +4 -2
  69. data/lib/unparser/emitter/send/unary.rb +3 -1
  70. data/lib/unparser/emitter/splat.rb +2 -0
  71. data/lib/unparser/emitter/super.rb +2 -0
  72. data/lib/unparser/emitter/undef.rb +2 -0
  73. data/lib/unparser/emitter/variable.rb +2 -0
  74. data/lib/unparser/emitter/yield.rb +2 -0
  75. data/lib/unparser/finalize.rb +2 -0
  76. data/lib/unparser/node_helpers.rb +19 -0
  77. data/spec/spec_helper.rb +10 -0
  78. data/spec/unit/unparser/buffer/append_spec.rb +2 -0
  79. data/spec/unit/unparser/buffer/append_without_prefix_spec.rb +2 -0
  80. data/spec/unit/unparser/buffer/capture_content_spec.rb +2 -0
  81. data/spec/unit/unparser/buffer/content_spec.rb +3 -1
  82. data/spec/unit/unparser/buffer/fresh_line_spec.rb +2 -0
  83. data/spec/unit/unparser/buffer/indent_spec.rb +3 -1
  84. data/spec/unit/unparser/buffer/nl_spec.rb +2 -0
  85. data/spec/unit/unparser/buffer/unindent_spec.rb +2 -0
  86. data/spec/unit/unparser/comments/consume_spec.rb +2 -1
  87. data/spec/unit/unparser/comments/take_all_spec.rb +2 -1
  88. data/spec/unit/unparser/comments/take_before_spec.rb +6 -5
  89. data/spec/unit/unparser/comments/take_eol_comments_spec.rb +2 -1
  90. data/spec/unit/unparser/emitter/class_methods/handle_spec.rb +2 -0
  91. data/spec/unit/unparser_spec.rb +110 -57
  92. data/unparser.gemspec +5 -4
  93. metadata +32 -12
  94. data/bin/test-unparser +0 -26
  95. data/lib/unparser/emitter/literal/composed.rb +0 -64
  96. data/spec/unit/unparser/comments/skip_eol_comment_spec.rb +0 -29
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ module Unparser
4
+ class Emitter
5
+ class Send
6
+
7
+ # Emitter for arguments of send nodes
8
+ class Arguments < Emitter
9
+
10
+ private
11
+
12
+ # Perform dispatch
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ #
18
+ def dispatch
19
+ return if children.empty?
20
+
21
+ parentheses do
22
+ delimited(effective_arguments)
23
+ end
24
+ end
25
+
26
+ # Return effective arguments
27
+ #
28
+ # @return [Parser::AST::Node]
29
+ #
30
+ # @api private
31
+ #
32
+ def effective_arguments
33
+ last = children.length - 1
34
+ children.each_with_index.map do |argument, index|
35
+ if last == index && argument.type == :hash && argument.children.any?
36
+ argument.updated(:hash_body)
37
+ else
38
+ argument
39
+ end
40
+ end
41
+ end
42
+
43
+ end # Arguments
44
+ end # Send
45
+ end # Emitter
46
+ end # Unparser
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ module Unparser
4
+ class Emitter
5
+ class Send
6
+ # Emitter for send as attribute assignment
7
+ class AttributeAssignment < self
8
+
9
+ # Perform regular dispatch
10
+ #
11
+ # @return [undefined]
12
+ #
13
+ # @api private
14
+ #
15
+ def dispatch
16
+ emit_receiver
17
+ emit_selector
18
+ visit_terminated(arguments.first)
19
+ end
20
+
21
+ # Emit receiver
22
+ #
23
+ # @return [Parser::AST::Node]
24
+ #
25
+ # @api private
26
+ #
27
+ def emit_receiver
28
+ visit_terminated(receiver)
29
+ write(T_DOT)
30
+ end
31
+
32
+ end # AttributeAssignment
33
+ end # Send
34
+ end # Emitter
35
+ end # Unparser
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Send
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Send
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Send
@@ -18,9 +20,9 @@ module Unparser
18
20
  emit_arguments
19
21
  end
20
22
 
21
- # Return receiver
23
+ # Emit receiver
22
24
  #
23
- # @return [Parser::AST::Node]
25
+ # @return [undefined]
24
26
  #
25
27
  # @api private
26
28
  #
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Send
@@ -20,7 +22,7 @@ module Unparser
20
22
  def dispatch
21
23
  name = selector
22
24
  write(MAP.fetch(name, name).to_s)
23
- visit(receiver)
25
+ visit_terminated(receiver)
24
26
  end
25
27
 
26
28
  end # Unary
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for splats
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for undef nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -1 +1,3 @@
1
+ # encoding: utf-8
2
+
1
3
  Unparser::Emitter::REGISTRY.freeze
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+
3
+ module Unparser
4
+ module NodeHelpers
5
+
6
+ # Helper for building nodes
7
+ #
8
+ # @param [Symbol]
9
+ #
10
+ # @return [Parser::AST::Node]
11
+ #
12
+ # @api private
13
+ #
14
+ def s(type, *children)
15
+ Parser::AST::Node.new(type, *children)
16
+ end
17
+
18
+ end # NodeHelpers
19
+ end # Unparser
data/spec/spec_helper.rb CHANGED
@@ -1,12 +1,22 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'unparser'
2
4
  require 'devtools/spec_helper'
3
5
 
6
+ require 'parser/current'
4
7
  require 'parser/ruby21'
5
8
 
6
9
  module SpecHelper
7
10
  def s(type, *children)
8
11
  Parser::AST::Node.new(type, children)
9
12
  end
13
+
14
+ def strip(source)
15
+ source = source.rstrip
16
+ indent = source.scan(/^\s*/).min_by(&:length)
17
+ source.gsub(/^#{indent}/, '')
18
+ end
19
+
10
20
  end
11
21
 
12
22
  RSpec.configure do |config|
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser::Buffer, '#append' do
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser::Buffer, '#append_without_prefix' do
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser::Buffer, '#capture_content' do
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser::Buffer, '#content' do
@@ -16,7 +18,7 @@ describe Unparser::Buffer, '#content' do
16
18
  first = object.content
17
19
  second = object.content
18
20
  expect(first).to eql(second)
19
- expect(first).to_not be(second)
21
+ expect(first).not_to be(second)
20
22
  end
21
23
  end
22
24
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser::Buffer, '#fresh_line?' do
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser::Buffer, '#indent' do
@@ -5,7 +7,7 @@ describe Unparser::Buffer, '#indent' do
5
7
 
6
8
  subject { object.indent }
7
9
 
8
- it 'should indent with two chars' do
10
+ it 'should indent with two spaces' do
9
11
  object.append('foo')
10
12
  object.nl
11
13
  object.indent
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser::Buffer, '#nl' do
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser::Buffer, '#unindent' do
@@ -1,5 +1,6 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
- require 'parser/current'
3
4
 
4
5
  describe Unparser::Comments, '#consume' do
5
6
 
@@ -1,5 +1,6 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
- require 'parser/current'
3
4
 
4
5
  describe Unparser::Comments, '#take_all' do
5
6
 
@@ -1,5 +1,6 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
- require 'parser/current'
3
4
 
4
5
  describe Unparser::Comments, '#take_before' do
5
6
 
@@ -17,11 +18,11 @@ describe Unparser::Comments, '#take_before' do
17
18
  RUBY
18
19
  end
19
20
 
20
- it 'should return no comments none are before the node' do
21
+ it 'should return no comments if none are before the node' do
21
22
  expect(object.take_before(ast, :expression)).to eql([])
22
23
  end
23
24
 
24
- it 'should only the comments that are before the specified part of the node' do
25
+ it 'should return only the comments that are before the specified part of the node' do
25
26
  expect(object.take_before(ast, :end)).to eql(comments.first(2))
26
27
  expect(object.take_all).to eql([comments[2]])
27
28
  end
@@ -36,11 +37,11 @@ describe Unparser::Comments, '#take_before' do
36
37
  RUBY
37
38
  end
38
39
 
39
- it 'should return no comments none are before the node' do
40
+ it 'should return no comments if none are before the node' do
40
41
  expect(object.take_before(ast, :expression)).to eql([])
41
42
  end
42
43
 
43
- it 'should only the comments that are before the specified part of the node' do
44
+ it 'should return only the comments that are before the specified part of the node' do
44
45
  expect(object.take_before(ast, :end)).to eql([])
45
46
  end
46
47
  end
@@ -1,5 +1,6 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
- require 'parser/current'
3
4
 
4
5
  describe Unparser::Comments, '#take_eol_comments' do
5
6
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser::Emitter, '.handle' do
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Unparser do
@@ -19,62 +21,45 @@ describe Unparser do
19
21
 
20
22
  def self.with_versions(versions)
21
23
  versions.each do |version|
22
- parser = parser_for_ruby_version(version)
23
- yield version, parser
24
+ yield parser_for_ruby_version(version)
24
25
  end
25
26
  end
26
27
 
27
- def self.strip(ruby)
28
- return ruby if ruby.empty?
29
- lines = ruby.lines
30
- match = /\A[ ]*/.match(lines.first)
31
- length = match[0].length
32
- source = lines.map do |line|
33
- line[(length..-1)]
34
- end.join
35
- source.chomp
36
- end
37
-
38
- def assert_round_trip(input, parser_class)
39
- ast, comments = parser_class.parse_with_comments(input)
28
+ def assert_round_trip(input, parser)
29
+ ast, comments = parser.parse_with_comments(input)
40
30
  generated = Unparser.unparse(ast, comments)
41
31
  generated.should eql(input)
42
32
  end
43
33
 
44
- def self.assert_generates_one_way(ast, expected, versions = RUBIES)
45
- with_versions(versions) do |version, parser_class|
46
- it "should generate #{ast.inspect} as #{expected} under #{version}" do
47
- comments = []
48
- if ast.kind_of?(String)
49
- ast, comments = parser_class.parse_with_comments(input)
50
- end
51
- generated = Unparser.unparse(ast, comments)
52
- generated.should eql(expected)
53
- end
54
- end
34
+ def assert_generates_from_string(parser, string, expected)
35
+ string = strip(string)
36
+ ast_with_comments = parser.parse_with_comments(string)
37
+ assert_generates_from_ast(parser, ast_with_comments, expected)
38
+ end
39
+
40
+ def assert_generates_from_ast(parser, ast_with_comments, expected)
41
+ generated = Unparser.unparse(*ast_with_comments)
42
+ generated.should eql(expected)
43
+ ast, comments = parser.parse_with_comments(generated)
44
+ Unparser.unparse(ast, comments).should eql(expected)
55
45
  end
56
46
 
57
47
  def self.assert_generates(ast_or_string, expected, versions = RUBIES)
58
- ast_or_string = strip(ast_or_string) if ast_or_string.is_a?(String)
59
- expected = strip(expected)
60
- with_versions(versions) do |version, parser_class|
61
- it "should generate #{ast_or_string.inspect} as #{expected} under #{version}" do
62
- ast, comments = if ast_or_string.kind_of?(String)
63
- parser_class.parse_with_comments(ast_or_string)
64
- else
65
- [ast_or_string, []]
66
- end
67
- generated = Unparser.unparse(ast, comments)
68
- generated.should eql(expected)
69
- ast, comments = parser_class.parse_with_comments(generated)
70
- Unparser.unparse(ast, comments).should eql(expected)
48
+ with_versions(versions) do |parser|
49
+ it "should generate #{ast_or_string} as #{expected} under #{parser.inspect}" do
50
+ if ast_or_string.kind_of?(String)
51
+ expected = strip(expected)
52
+ assert_generates_from_string(parser, ast_or_string, expected)
53
+ else
54
+ assert_generates_from_ast(parser, [ast_or_string, []], expected)
55
+ end
71
56
  end
72
57
  end
73
58
  end
74
59
 
75
60
  def self.assert_round_trip(input, versions = RUBIES)
76
- with_versions(versions) do |version, parser|
77
- it "should round trip #{input.inspect} under #{version}" do
61
+ with_versions(versions) do |parser|
62
+ it "should round trip #{input} under #{parser.inspect}" do
78
63
  assert_round_trip(input, parser)
79
64
  end
80
65
  end
@@ -92,15 +77,35 @@ describe Unparser do
92
77
  assert_generates '0x1', '1'
93
78
  assert_generates '1_000', '1000'
94
79
  assert_generates '1e10', '10000000000.0'
95
- assert_generates '?c', '"c"'
96
80
  end
97
81
 
98
82
  context 'string' do
99
- assert_generates %q("foo" "bar"), %q("foobar")
100
- assert_generates %q(%Q(foo"#{@bar})), %q("foo\"#{@bar}")
83
+ assert_generates '?c', '"c"'
84
+ assert_source %q("foo" "bar")
85
+ assert_generates %q(%Q(foo"#{@bar})), %q("foo\\"#{@bar}")
101
86
  assert_source %q("\"")
102
87
  assert_source %q("foo#{1}bar")
103
88
  assert_source %q("\"#{@a}")
89
+ assert_source %q("\\\\#{}")
90
+ assert_source %q("foo bar")
91
+ assert_source %q("foo\nbar")
92
+ assert_source %q("foo bar #{}")
93
+ assert_source %q("foo\nbar #{}")
94
+ # Within indentation
95
+ assert_generates <<-'RUBY', <<-'RUBY'
96
+ if foo
97
+ "
98
+ #{foo}
99
+ "
100
+ end
101
+ RUBY
102
+ if foo
103
+ "\n #{foo}\n "
104
+ end
105
+ RUBY
106
+
107
+ assert_source %q("foo#{@bar}")
108
+ assert_source %q("fo\no#{bar}b\naz")
104
109
  end
105
110
 
106
111
  context 'execute string' do
@@ -128,14 +133,17 @@ describe Unparser do
128
133
  assert_source "/\n/"
129
134
  assert_source '/\n/'
130
135
  assert_source "/\n/x"
136
+ # Within indentation
137
+ assert_source <<-RUBY
138
+ if foo
139
+ /
140
+ /
141
+ end
142
+ RUBY
131
143
  assert_generates '%r(/)', '/\//'
132
144
  assert_generates '%r(\))', '/)/'
133
145
  assert_generates '%r(#{@bar}baz)', '/#{@bar}baz/'
134
- end
135
-
136
- context 'dynamic string' do
137
- assert_source %q("foo#{@bar}")
138
- assert_source %q("fo\no#{bar}b\naz")
146
+ assert_source '/\/\//x'
139
147
  end
140
148
 
141
149
  context 'dynamic symbol' do
@@ -175,8 +183,15 @@ describe Unparser do
175
183
 
176
184
  context 'hash' do
177
185
  assert_source '{}'
178
- assert_source '{1 => 2}'
179
- assert_source '{1 => 2, 3 => 4}'
186
+ assert_source '{ 1 => 2 }'
187
+ assert_source '{ 1 => 2, 3 => 4 }'
188
+
189
+ context 'with symbol keys' do
190
+ assert_source '{ a: 1, b: 2 }'
191
+ assert_source '{ a: :a }'
192
+ assert_source '{ :"a b" => 1 }'
193
+ assert_source '{ :-@ => 1 }'
194
+ end
180
195
  end
181
196
  end
182
197
 
@@ -192,11 +207,6 @@ describe Unparser do
192
207
  assert_source '::TOPLEVEL::CONST'
193
208
  end
194
209
 
195
- context 'break' do
196
- assert_source 'break'
197
- assert_source 'break(a)'
198
- end
199
-
200
210
  context 'next' do
201
211
  assert_source 'next'
202
212
  assert_source 'next(bar)'
@@ -231,6 +241,7 @@ describe Unparser do
231
241
  assert_source '$a = 1'
232
242
  assert_source 'CONST = 1'
233
243
  assert_source 'Name::Spaced::CONST = 1'
244
+ assert_source '::Foo = ::Bar'
234
245
  end
235
246
 
236
247
  context 'multiple' do
@@ -247,7 +258,6 @@ describe Unparser do
247
258
  assert_source '$a, $b = 1, 2'
248
259
  assert_source 'a, b = foo'
249
260
  assert_source 'a, (b, c) = 1, [2, 3]'
250
- assert_generates_one_way s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b)), 'a, b'
251
261
  end
252
262
  end
253
263
 
@@ -259,6 +269,26 @@ describe Unparser do
259
269
  assert_source <<-'RUBY'
260
270
  return(1)
261
271
  RUBY
272
+
273
+ assert_source <<-'RUBY'
274
+ return(1), (2)
275
+ RUBY
276
+
277
+ assert_generates <<-'RUBY', <<-'RUBY'
278
+ return(a ? b : c)
279
+ RUBY
280
+ return(if a
281
+ b
282
+ else
283
+ c
284
+ end)
285
+ RUBY
286
+ end
287
+
288
+ context 'break' do
289
+ assert_source 'break'
290
+ assert_source 'break(a)'
291
+ assert_source 'break(a), (b)'
262
292
  end
263
293
 
264
294
  context 'send' do
@@ -359,6 +389,13 @@ describe Unparser do
359
389
  assert_source '(array[i] = 1).foo'
360
390
  assert_source 'array[1..2].foo'
361
391
  assert_source '(a.attribute ||= foo).bar'
392
+ assert_source 'foo.bar=baz[1]'
393
+ assert_source 'foo.bar=(baz || foo)'
394
+ assert_source 'foo.bar=baz.bar'
395
+ assert_source 'foo << (bar * baz)'
396
+ assert_source <<-'RUBY'
397
+ foo ||= (a, _ = b)
398
+ RUBY
362
399
 
363
400
  assert_source <<-'RUBY'
364
401
  begin
@@ -439,6 +476,11 @@ describe Unparser do
439
476
  assert_source 'foo.bar(:baz, &baz)'
440
477
  assert_source 'foo.bar=(:baz)'
441
478
  assert_source 'self.foo=(:bar)'
479
+
480
+ assert_source 'foo.bar(baz: boz)'
481
+ assert_source 'foo.bar(foo, "baz" => boz)'
482
+ assert_source 'foo.bar({ foo: boz }, boz)'
483
+ assert_source 'foo.bar(foo, {})'
442
484
  end
443
485
 
444
486
  context 'begin; end' do
@@ -1134,6 +1176,7 @@ describe Unparser do
1134
1176
  context 'unary operators' do
1135
1177
  assert_source '!1'
1136
1178
  assert_source '!!1'
1179
+ assert_source '!!(foo || bar)'
1137
1180
  assert_source '!(!1).baz'
1138
1181
  assert_source '~a'
1139
1182
  assert_source '-a'
@@ -1215,6 +1258,16 @@ describe Unparser do
1215
1258
  # last
1216
1259
  RUBY
1217
1260
 
1261
+ assert_generates <<-'RUBY', <<-'RUBY'
1262
+ foo if bar
1263
+ # comment
1264
+ RUBY
1265
+ if bar
1266
+ foo
1267
+ end
1268
+ # comment
1269
+ RUBY
1270
+
1218
1271
  assert_source <<-'RUBY'
1219
1272
  def noop
1220
1273
  # do nothing