unparser 0.6.15 → 0.8.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/lib/unparser/anima.rb +11 -0
  4. data/lib/unparser/ast/local_variable_scope.rb +28 -24
  5. data/lib/unparser/ast.rb +18 -22
  6. data/lib/unparser/buffer.rb +44 -2
  7. data/lib/unparser/cli.rb +28 -5
  8. data/lib/unparser/color.rb +2 -2
  9. data/lib/unparser/either.rb +6 -6
  10. data/lib/unparser/emitter/args.rb +5 -1
  11. data/lib/unparser/emitter/array.rb +0 -4
  12. data/lib/unparser/emitter/array_pattern.rb +1 -9
  13. data/lib/unparser/emitter/assignment.rb +17 -8
  14. data/lib/unparser/emitter/begin.rb +0 -6
  15. data/lib/unparser/emitter/binary.rb +1 -1
  16. data/lib/unparser/emitter/block.rb +13 -6
  17. data/lib/unparser/emitter/def.rb +1 -1
  18. data/lib/unparser/emitter/dstr.rb +6 -5
  19. data/lib/unparser/emitter/dsym.rb +1 -1
  20. data/lib/unparser/emitter/ensure.rb +16 -0
  21. data/lib/unparser/emitter/flow_modifier.rb +1 -7
  22. data/lib/unparser/emitter/for.rb +1 -1
  23. data/lib/unparser/emitter/hash.rb +0 -8
  24. data/lib/unparser/emitter/hash_pattern.rb +1 -1
  25. data/lib/unparser/emitter/in_pattern.rb +9 -1
  26. data/lib/unparser/emitter/index.rb +0 -4
  27. data/lib/unparser/emitter/kwbegin.rb +1 -1
  28. data/lib/unparser/emitter/match_pattern.rb +6 -1
  29. data/lib/unparser/emitter/match_pattern_p.rb +6 -1
  30. data/lib/unparser/emitter/mlhs.rb +7 -1
  31. data/lib/unparser/emitter/op_assign.rb +0 -10
  32. data/lib/unparser/emitter/primitive.rb +0 -13
  33. data/lib/unparser/emitter/range.rb +23 -2
  34. data/lib/unparser/emitter/regexp.rb +5 -17
  35. data/lib/unparser/emitter/rescue.rb +7 -1
  36. data/lib/unparser/emitter/root.rb +2 -9
  37. data/lib/unparser/emitter/send.rb +1 -5
  38. data/lib/unparser/emitter/string.rb +31 -0
  39. data/lib/unparser/emitter/xstr.rb +8 -1
  40. data/lib/unparser/emitter.rb +9 -10
  41. data/lib/unparser/generation.rb +14 -14
  42. data/lib/unparser/node_details.rb +1 -0
  43. data/lib/unparser/node_helpers.rb +18 -9
  44. data/lib/unparser/util.rb +23 -0
  45. data/lib/unparser/validation.rb +68 -28
  46. data/lib/unparser/writer/array.rb +51 -0
  47. data/lib/unparser/writer/binary.rb +8 -4
  48. data/lib/unparser/writer/dynamic_string.rb +128 -135
  49. data/lib/unparser/writer/regexp.rb +101 -0
  50. data/lib/unparser/writer/resbody.rb +37 -3
  51. data/lib/unparser/writer/rescue.rb +3 -7
  52. data/lib/unparser/writer/send/unary.rb +9 -4
  53. data/lib/unparser/writer/send.rb +8 -14
  54. data/lib/unparser/writer.rb +31 -1
  55. data/lib/unparser.rb +149 -38
  56. metadata +33 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d1d0033d21b1c64de6affcc9c555797edf5206dc2947484ff8391e3c8e739ce
4
- data.tar.gz: 60732ffbcc8a43cd2f04a6cba76e955b7e764ada9d201cd51a0a624d093b3659
3
+ metadata.gz: e0e776dd7b47efb62b8ad18d7262d247362944f28ea67edb7e518d8a94c74649
4
+ data.tar.gz: 759ec6fb240c4c62835bd8c789877fc26fc974563d2566687a63b2c0dec1072f
5
5
  SHA512:
6
- metadata.gz: 77db441f3e4da2b584065c597796d4adbb08b07e481b43ee85c80218375cbf8932bae847727afa9abee0be02ee5dea1c2effd5caa70216a5bafa34007d0c3820
7
- data.tar.gz: c180d28c4ac14fe5d6b5756350592b472cd084ce932309fd6cc87f042dffb1f1870dd194260e71b53dbac71fa648bd359c7b4d3c8860c7508f7cc854c9d2ef25
6
+ metadata.gz: 11fe99943d2575e00ca2fc150a78cad1f2f830b3249f3692f473da7e520775fc9423b254fb2f7613e4b6811f03dd3d2af0d4bba1d0f2f143e048ab65281771ff
7
+ data.tar.gz: f08db4117aa2ebba9c5ac7a9e057ca7ddc9fc0613170752ac10cc7515058f491fe756b880db73629e2e7a8328cc979872b4c682197c061de39da52a44796587f
data/README.md CHANGED
@@ -10,7 +10,7 @@ The following constraints apply:
10
10
 
11
11
  * No support for macruby extensions
12
12
  * Only support for the [modern AST](https://github.com/whitequark/parser/#usage) format
13
- * Only support for Ruby >= 3.1
13
+ * Only support for Ruby >= 3.2
14
14
 
15
15
  Notable Users:
16
16
 
@@ -44,9 +44,9 @@ To preserve the comments from the source:
44
44
  require 'parser/current'
45
45
  require 'unparser'
46
46
 
47
- ast, comments = Unparser.parse_with_comments('your(ruby(code)) # with comments')
47
+ ast, comments = Unparser.parser.parse_with_comments(Unparser.buffer('your(ruby(code)) # with comments'))
48
48
 
49
- Unparser.unparse(ast, comments) # => 'your(ruby(code)) # with comments'
49
+ Unparser.unparse(ast, comments: comments) # => 'your(ruby(code)) # with comments'
50
50
  ```
51
51
 
52
52
  Passing in manually constructed AST:
@@ -114,7 +114,7 @@ Unparser currently successfully round trips almost all ruby code around. Using R
114
114
  If there is a non round trippable example that is NOT subjected to known [Limitations](#limitations).
115
115
  please report a bug.
116
116
 
117
- On CI unparser is currently tested against rubyspec with minor [excludes](https://github.com/mbj/unparser/blob/master/spec/integrations.yml).
117
+ On CI unparser is currently tested against rubyspec with minor [excludes](https://github.com/mbj/unparser/blob/main/spec/integrations.yml).
118
118
 
119
119
  Limitations:
120
120
  ------------
@@ -134,14 +134,25 @@ module Unparser
134
134
  # @param [Class, Module] scope
135
135
  #
136
136
  # @return [undefined]
137
+ #
138
+ # mutant:disable
137
139
  def included(descendant)
138
140
  descendant.instance_exec(self, attribute_names) do |anima, names|
139
141
  # Define anima method
142
+
143
+ class << self
144
+ undef_method(:anima) if method_defined?(:anima)
145
+ end
146
+
140
147
  define_singleton_method(:anima) { anima }
141
148
 
142
149
  # Define instance methods
143
150
  include InstanceMethods
144
151
 
152
+ names.each do |name|
153
+ undef_method(name) if method_defined?(name)
154
+ end
155
+
145
156
  # Define attribute readers
146
157
  attr_reader(*names)
147
158
 
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Unparser
4
- module AST
5
-
4
+ class AST
6
5
  # Calculated local variable scope for a given node
7
6
  class LocalVariableScope
8
- include Enumerable, Adamantium
7
+ include Adamantium, Anima.new(:static_local_variables, :node)
9
8
 
10
9
  # Initialize object
11
10
  #
@@ -13,13 +12,17 @@ module Unparser
13
12
  #
14
13
  # @return [undefined]
15
14
  #
16
- # @api private
17
- #
18
- def initialize(node)
15
+ # mutant:disable
16
+ def initialize(*arguments)
17
+ super
18
+
19
19
  items = []
20
- LocalVariableScopeEnumerator.each(node) do |*scope|
21
- items << scope
22
- end
20
+
21
+ LocalVariableScopeEnumerator.each(
22
+ node: node,
23
+ stack: static_local_variables.dup
24
+ ) { |*scope| items << scope }
25
+
23
26
  @items = items
24
27
  end
25
28
 
@@ -53,6 +56,15 @@ module Unparser
53
56
  end
54
57
  end
55
58
 
59
+ # mutant:disable
60
+ def local_variables_for_node(needle)
61
+ @items.each do |node, current|
62
+ return current if node.equal?(needle)
63
+ end
64
+
65
+ Set.new
66
+ end
67
+
56
68
  # Test if local variables where first assigned in body and read by conditional
57
69
  #
58
70
  # @param [Parser::AST::Node] body
@@ -90,21 +102,13 @@ module Unparser
90
102
  #
91
103
  # @api private
92
104
  #
93
- def initialize
94
- @stack = [Set.new]
105
+ def initialize(stack:)
106
+ @stack = [stack]
95
107
  end
96
108
 
97
109
  # Enumerate each node with its local variable scope
98
- #
99
- # @param [Parser::AST::Node] node
100
- #
101
- # @return [self]
102
- #
103
- # @api private
104
- #
105
- def self.each(node, &block)
106
- new.each(node, &block)
107
- self
110
+ def self.each(node:, stack:, &block)
111
+ new(stack: stack).each(node: node, &block)
108
112
  end
109
113
 
110
114
  # Enumerate local variable scope scope
@@ -117,7 +121,7 @@ module Unparser
117
121
  #
118
122
  # @api private
119
123
  #
120
- def each(node, &block)
124
+ def each(node:, &block)
121
125
  visit(node, &block)
122
126
  end
123
127
 
@@ -132,7 +136,7 @@ module Unparser
132
136
  enter(node)
133
137
  yield node, current.dup, before
134
138
  node.children.each do |child|
135
- visit(child, &block) if child.is_a?(Parser::AST::Node)
139
+ visit(child, &block) if child.instance_of?(Parser::AST::Node)
136
140
  end
137
141
  leave(node)
138
142
  end
@@ -142,7 +146,7 @@ module Unparser
142
146
  when *RESET_NODES
143
147
  push_reset
144
148
  when ASSIGN_NODES
145
- define(node.children.first)
149
+ value = node.children.first and define(value)
146
150
  when *INHERIT_NODES
147
151
  push_inherit
148
152
  end
data/lib/unparser/ast.rb CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  module Unparser
4
4
  # Namespace for AST processing tools
5
- module AST
5
+ class AST
6
+ include Anima.new(:comments, :explicit_encoding, :node, :static_local_variables)
7
+
6
8
  FIRST_CHILD = ->(node) { node.children.first }.freeze
7
- TAUTOLOGY = ->(_node) { true }.freeze
8
9
 
9
10
  RESET_NODES = %i[module class sclass def defs].freeze
10
11
  INHERIT_NODES = [:block].freeze
@@ -16,12 +17,22 @@ module Unparser
16
17
  arg
17
18
  kwarg
18
19
  kwoptarg
20
+ kwrestarg
19
21
  lvasgn
20
22
  optarg
21
- procarg0
22
23
  restarg
23
24
  ].to_set.freeze
24
25
 
26
+ # mutant:disable
27
+ def self.from_node(node:)
28
+ new(
29
+ comments: EMPTY_ARRAY,
30
+ explicit_encoding: nil,
31
+ node:,
32
+ static_local_variables: Set.new
33
+ )
34
+ end
35
+
25
36
  # Test for local variable inherited scope reset
26
37
  #
27
38
  # @param [Parser::AST::Node] node
@@ -69,6 +80,7 @@ module Unparser
69
80
  #
70
81
  # @api private
71
82
  #
83
+ # mutant:disable
72
84
  def self.local_variable_reads(node)
73
85
  Enumerator.new(
74
86
  node,
@@ -80,19 +92,6 @@ module Unparser
80
92
  class Enumerator
81
93
  include Adamantium, Concord.new(:node, :controller), Enumerable
82
94
 
83
- # Return new instance
84
- #
85
- # @param [Parser::AST::Node] node
86
- # @param [#call(node)] controller
87
- #
88
- # @return [Enumerator]
89
- #
90
- # @api private
91
- #
92
- def self.new(node, controller = TAUTOLOGY)
93
- super
94
- end
95
-
96
95
  # Return each node
97
96
  #
98
97
  # @return [Enumerator<Parser::AST::Node>]
@@ -103,8 +102,8 @@ module Unparser
103
102
  #
104
103
  # @api private
105
104
  #
106
- def each(&block)
107
- Walker.call(node, controller, &block)
105
+ def each(&)
106
+ Walker.call(node, controller, &)
108
107
  end
109
108
 
110
109
  # Return nodes selected by types
@@ -168,13 +167,10 @@ module Unparser
168
167
  #
169
168
  # @param [Parser::AST::Node] node
170
169
  #
171
- # @return [self]
172
- #
173
170
  # @api private
174
171
  #
175
- def self.call(node, controller = TAUTOLOGY, &block)
172
+ def self.call(node, controller, &block)
176
173
  new(block, controller).call(node)
177
- self
178
174
  end
179
175
 
180
176
  # Call walker with node
@@ -14,8 +14,10 @@ module Unparser
14
14
  # @api private
15
15
  #
16
16
  def initialize
17
- @content = +''
18
- @indent = 0
17
+ @content = +''
18
+ @heredocs = []
19
+ @indent = 0
20
+ @no_nl = true
19
21
  end
20
22
 
21
23
  # Append string
@@ -34,6 +36,13 @@ module Unparser
34
36
  self
35
37
  end
36
38
 
39
+ # Push to heredoc stack
40
+ #
41
+ # @param [String] heredoc
42
+ def push_heredoc(heredoc)
43
+ @heredocs << heredoc
44
+ end
45
+
37
46
  # Append a string without an indentation prefix
38
47
  #
39
48
  # @param [String] string
@@ -68,6 +77,10 @@ module Unparser
68
77
  self
69
78
  end
70
79
 
80
+ def ensure_nl
81
+ nl unless fresh_line?
82
+ end
83
+
71
84
  # Write newline
72
85
  #
73
86
  # @return [self]
@@ -75,7 +88,27 @@ module Unparser
75
88
  # @api private
76
89
  #
77
90
  def nl
91
+ @no_nl = false
78
92
  write(NL)
93
+ flush_heredocs
94
+ self
95
+ end
96
+
97
+ # Write final newline
98
+ def final_newline
99
+ return if fresh_line? || @no_nl
100
+
101
+ write(NL)
102
+ end
103
+
104
+ def nl_flush_heredocs
105
+ return if @heredocs.empty?
106
+
107
+ if fresh_line?
108
+ flush_heredocs
109
+ else
110
+ nl
111
+ end
79
112
  end
80
113
 
81
114
  def root_indent
@@ -117,6 +150,10 @@ module Unparser
117
150
  self
118
151
  end
119
152
 
153
+ def write_encoding(encoding)
154
+ write("# -*- encoding: #{encoding} -*-\n")
155
+ end
156
+
120
157
  private
121
158
 
122
159
  INDENT_SPACE = ' '.freeze
@@ -125,5 +162,10 @@ module Unparser
125
162
  write(INDENT_SPACE * @indent)
126
163
  end
127
164
 
165
+ def flush_heredocs
166
+ @heredocs.each(&public_method(:write))
167
+ @heredocs = []
168
+ end
169
+
128
170
  end # Buffer
129
171
  end # Unparser
data/lib/unparser/cli.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pathname'
4
+
3
5
  module Unparser
4
6
  # Unparser CLI implementation
5
7
  class CLI
@@ -60,6 +62,7 @@ module Unparser
60
62
  #
61
63
  # @api private
62
64
  #
65
+ # mutant:disable
63
66
  def self.run(*arguments)
64
67
  new(*arguments).exit_status
65
68
  end
@@ -71,15 +74,17 @@ module Unparser
71
74
  # @return [undefined]
72
75
  #
73
76
  # @api private
77
+ # mutant:disable
74
78
  def initialize(arguments)
75
79
  @ignore = Set.new
76
80
  @targets = []
77
81
 
78
- @fail_fast = false
79
- @start_with = nil
80
- @success = true
81
- @validation = :validation
82
- @verbose = false
82
+ @fail_fast = false
83
+ @start_with = nil
84
+ @success = true
85
+ @validation = :validation
86
+ @verbose = false
87
+ @ignore_original_syntax_error = false
83
88
 
84
89
  opts = OptionParser.new do |builder|
85
90
  add_options(builder)
@@ -98,6 +103,7 @@ module Unparser
98
103
  #
99
104
  # @api private
100
105
  #
106
+ # mutant:disable
101
107
  # rubocop:disable Metrics/MethodLength
102
108
  def add_options(builder)
103
109
  builder.banner = 'usage: unparse [options] FILE [FILE]'
@@ -114,6 +120,9 @@ module Unparser
114
120
  builder.on('-l', '--literal') do
115
121
  @validation = :literal_validation
116
122
  end
123
+ builder.on('--ignore-original-syntax-error') do
124
+ @ignore_original_syntax_error = true
125
+ end
117
126
  builder.on('--ignore FILE') do |file|
118
127
  @ignore.merge(targets(file))
119
128
  end
@@ -129,6 +138,7 @@ module Unparser
129
138
  #
130
139
  # @api private
131
140
  #
141
+ # mutant:disable
132
142
  def exit_status
133
143
  effective_targets.each do |target|
134
144
  process_target(target)
@@ -140,11 +150,15 @@ module Unparser
140
150
 
141
151
  private
142
152
 
153
+ # mutant:disable
143
154
  def process_target(target)
144
155
  validation = target.public_send(@validation)
145
156
  if validation.success?
146
157
  puts validation.report if @verbose
147
158
  puts "Success: #{validation.identification}"
159
+ elsif ignore_original_syntax_error?(validation)
160
+ exception = validation.original_node.from_left
161
+ puts "#{exception.class}: #{validation.identification} #{exception}"
148
162
  else
149
163
  puts validation.report
150
164
  puts "Error: #{validation.identification}"
@@ -152,6 +166,14 @@ module Unparser
152
166
  end
153
167
  end
154
168
 
169
+ # mutant:disable
170
+ def ignore_original_syntax_error?(validation)
171
+ @ignore_original_syntax_error && validation.original_node.from_left do
172
+ nil
173
+ end.instance_of?(Parser::SyntaxError)
174
+ end
175
+
176
+ # mutant:disable
155
177
  def effective_targets
156
178
  if @start_with
157
179
  reject = true
@@ -167,6 +189,7 @@ module Unparser
167
189
  end.reject(&@ignore.method(:include?))
168
190
  end
169
191
 
192
+ # mutant:disable
170
193
  def targets(file_name)
171
194
  if File.directory?(file_name)
172
195
  Dir.glob(File.join(file_name, '**/*.rb'))
@@ -30,10 +30,10 @@ module Unparser
30
30
 
31
31
  # Well rubocop you are static so you do not have a clue here ;)
32
32
  # rubocop:disable Style/RedundantInitialize
33
- # rubocop:disable Style/MissingSuper
33
+ # rubocop:disable Lint/MissingSuper
34
34
  def initialize; end
35
35
  # rubocop:enable Style/RedundantInitialize
36
- # rubocop:enable Style/MissingSuper
36
+ # rubocop:enable Lint/MissingSuper
37
37
 
38
38
  end.new
39
39
 
@@ -54,15 +54,15 @@ module Unparser
54
54
  # Evaluate functor block
55
55
  #
56
56
  # @return [Either::Left<Object>]
57
- def fmap(&block)
58
- require_block(&block)
57
+ def fmap(&)
58
+ require_block(&)
59
59
  end
60
60
 
61
61
  # Evaluate applicative block
62
62
  #
63
63
  # @return [Either::Left<Object>]
64
- def bind(&block)
65
- require_block(&block)
64
+ def bind(&)
65
+ require_block(&)
66
66
  end
67
67
 
68
68
  # Unwrap value from left
@@ -137,8 +137,8 @@ module Unparser
137
137
  # Map over left value
138
138
  #
139
139
  # @return [Either::Right<Object>]
140
- def lmap(&block)
141
- require_block(&block)
140
+ def lmap(&)
141
+ require_block(&)
142
142
  end
143
143
 
144
144
  # Evaluate right side of branch
@@ -13,7 +13,11 @@ module Unparser
13
13
  end
14
14
 
15
15
  def emit_def_arguments
16
- delimited(normal_arguments)
16
+ if children.one? && n_mlhs?(Util.one(children))
17
+ emitter(Util.one(children)).dispatch_def
18
+ else
19
+ delimited(normal_arguments)
20
+ end
17
21
  end
18
22
 
19
23
  def emit_lambda_arguments
@@ -6,10 +6,6 @@ module Unparser
6
6
  class Array < self
7
7
  handle :array
8
8
 
9
- def emit_heredoc_reminders
10
- emitters.each(&:emit_heredoc_reminders)
11
- end
12
-
13
9
  private
14
10
 
15
11
  def dispatch
@@ -12,18 +12,10 @@ module Unparser
12
12
 
13
13
  def dispatch
14
14
  write('[')
15
- delimited(children, &method(:emit_member))
15
+ delimited(children)
16
16
  write(', ') if node_type.equal?(:array_pattern_with_tail)
17
17
  write(']')
18
18
  end
19
-
20
- def emit_member(node)
21
- if n_match_rest?(node)
22
- writer_with(MatchRest, node).emit_array_pattern
23
- else
24
- visit(node)
25
- end
26
- end
27
19
  end # Pin
28
20
  end # Emitter
29
21
  end # Unparser
@@ -11,12 +11,6 @@ module Unparser
11
11
  true
12
12
  end
13
13
 
14
- def emit_heredoc_reminders
15
- return unless right
16
-
17
- emitter(right).emit_heredoc_reminders
18
- end
19
-
20
14
  private
21
15
 
22
16
  def dispatch
@@ -30,12 +24,27 @@ module Unparser
30
24
  write(' = ')
31
25
 
32
26
  if BINARY_OPERATOR.include?(right.type)
33
- writer_with(Writer::Binary, right).emit_operator
27
+ writer_with(Writer::Binary, node: right).emit_operator
28
+ elsif n_array?(right)
29
+ emit_array
30
+ else
31
+ right_emitter.write_to_buffer
32
+ end
33
+ end
34
+
35
+ def emit_array
36
+ if right.children.size > 1
37
+ delimited(right.children)
34
38
  else
35
- visit(right)
39
+ right_emitter.write_to_buffer
36
40
  end
37
41
  end
38
42
 
43
+ def right_emitter
44
+ emitter(right)
45
+ end
46
+ memoize :right_emitter
47
+
39
48
  abstract_method :emit_left
40
49
 
41
50
  # Variable assignment emitter
@@ -8,12 +8,6 @@ module Unparser
8
8
  handle :begin
9
9
  children :body
10
10
 
11
- def emit_heredoc_reminders
12
- children.each do |child|
13
- emitter(child).emit_heredoc_reminders
14
- end
15
- end
16
-
17
11
  private
18
12
 
19
13
  def dispatch
@@ -13,7 +13,7 @@ module Unparser
13
13
  end
14
14
 
15
15
  def writer
16
- writer_with(Writer::Binary, node)
16
+ writer_with(Writer::Binary, node:)
17
17
  end
18
18
  memoize :writer
19
19
  end # Binary
@@ -5,7 +5,7 @@ module Unparser
5
5
 
6
6
  # Block emitter
7
7
  class Block < self
8
- handle :block, :numblock
8
+ handle :block, :numblock, :itblock
9
9
 
10
10
  children :target, :arguments, :body
11
11
 
@@ -16,7 +16,6 @@ module Unparser
16
16
  ws
17
17
  write_open
18
18
  emit_block_arguments unless n_lambda?(target)
19
- target_writer.emit_heredoc_reminders if n_send?(target)
20
19
  emit_optional_body_ensure_rescue(body)
21
20
  write_close
22
21
  end
@@ -42,7 +41,7 @@ module Unparser
42
41
  end
43
42
 
44
43
  def target_writer
45
- writer_with(Writer::Send::Regular, target)
44
+ writer_with(Writer::Send::Regular, node: target)
46
45
  end
47
46
  memoize :target_writer
48
47
 
@@ -65,20 +64,28 @@ module Unparser
65
64
  end
66
65
 
67
66
  def emit_lambda_arguments
68
- parentheses { writer_with(Args, arguments).emit_lambda_arguments }
67
+ parentheses { writer_with(Args, node: arguments).emit_lambda_arguments }
69
68
  end
70
69
 
71
70
  def numblock?
72
71
  node.type.equal?(:numblock)
73
72
  end
74
73
 
74
+ # NOTE: mutant fails on Ruby < 3.4
75
+ # mutant:disable
76
+ def itblock?
77
+ node.type.equal?(:itblock)
78
+ end
79
+
80
+ # NOTE: mutant fails on Ruby < 3.4
81
+ # mutant:disable
75
82
  def emit_block_arguments
76
- return if numblock? || arguments.children.empty?
83
+ return if numblock? || itblock? || arguments.children.empty?
77
84
 
78
85
  ws
79
86
 
80
87
  parentheses('|', '|') do
81
- writer_with(Args, arguments).emit_block_arguments
88
+ writer_with(Args, node: arguments).emit_block_arguments
82
89
  end
83
90
  end
84
91
 
@@ -26,7 +26,7 @@ module Unparser
26
26
  return if arguments.children.empty?
27
27
 
28
28
  parentheses do
29
- writer_with(Args, arguments).emit_def_arguments
29
+ writer_with(Args, node: arguments).emit_def_arguments
30
30
  end
31
31
  end
32
32