ruby-next-core 0.10.5 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/README.md +25 -16
  4. data/lib/.rbnext/2.1/ruby-next/core.rb +206 -0
  5. data/lib/.rbnext/2.1/ruby-next/language.rb +227 -0
  6. data/lib/.rbnext/2.3/ruby-next/commands/nextify.rb +2 -2
  7. data/lib/.rbnext/2.3/ruby-next/language/eval.rb +4 -4
  8. data/lib/.rbnext/2.3/ruby-next/language/rewriters/base.rb +23 -5
  9. data/lib/.rbnext/2.3/ruby-next/language/rewriters/endless_range.rb +1 -1
  10. data/lib/.rbnext/2.3/ruby-next/language/rewriters/pattern_matching.rb +20 -17
  11. data/lib/.rbnext/2.3/ruby-next/utils.rb +1 -1
  12. data/lib/.rbnext/2.7/ruby-next/core.rb +206 -0
  13. data/lib/ruby-next/commands/nextify.rb +1 -1
  14. data/lib/ruby-next/config.rb +50 -0
  15. data/lib/ruby-next/core/array/deconstruct.rb +1 -1
  16. data/lib/ruby-next/core/array/intersect.rb +9 -0
  17. data/lib/ruby-next/core/constants/frozen_error.rb +15 -0
  18. data/lib/ruby-next/core/constants/no_matching_pattern_error.rb +1 -1
  19. data/lib/ruby-next/core/enumerable/tally.rb +46 -7
  20. data/lib/ruby-next/core/hash/deconstruct_keys.rb +1 -1
  21. data/lib/ruby-next/core/struct/deconstruct_keys.rb +3 -3
  22. data/lib/ruby-next/core.rb +8 -4
  23. data/lib/ruby-next/core_ext.rb +3 -1
  24. data/lib/ruby-next/language/bootsnap.rb +1 -1
  25. data/lib/ruby-next/language/edge.rb +0 -6
  26. data/lib/ruby-next/language/eval.rb +3 -3
  27. data/lib/ruby-next/language/parser.rb +16 -0
  28. data/lib/ruby-next/language/rewriters/args_forward.rb +14 -6
  29. data/lib/ruby-next/language/rewriters/args_forward_leading.rb +75 -0
  30. data/lib/ruby-next/language/rewriters/base.rb +19 -1
  31. data/lib/ruby-next/language/rewriters/in_pattern.rb +56 -0
  32. data/lib/ruby-next/language/rewriters/method_reference.rb +1 -1
  33. data/lib/ruby-next/language/rewriters/numeric_literals.rb +41 -0
  34. data/lib/ruby-next/language/rewriters/pattern_matching.rb +18 -15
  35. data/lib/ruby-next/language/rewriters/required_kwargs.rb +39 -0
  36. data/lib/ruby-next/language/rewriters/safe_navigation.rb +42 -29
  37. data/lib/ruby-next/language/rewriters/shorthand_hash.rb +1 -1
  38. data/lib/ruby-next/language/setup.rb +7 -4
  39. data/lib/ruby-next/language/unparser.rb +5 -0
  40. data/lib/ruby-next/language.rb +62 -44
  41. data/lib/ruby-next/rubocop.rb +9 -18
  42. data/lib/ruby-next/setup_self.rb +5 -3
  43. data/lib/ruby-next/version.rb +1 -1
  44. data/lib/ruby-next.rb +5 -38
  45. metadata +20 -18
  46. data/lib/.rbnext/2.3/ruby-next/language/rewriters/right_hand_assignment.rb +0 -117
  47. data/lib/ruby-next/language/rewriters/right_hand_assignment.rb +0 -117
@@ -20,7 +20,7 @@ module RubyNext
20
20
  module InstanceEval # :nodoc:
21
21
  refine Object do
22
22
  def instance_eval(*args, &block)
23
- return super(*args, &block) if block_given?
23
+ return super(*args, &block) if block
24
24
 
25
25
  source = args.shift
26
26
  new_source = ::RubyNext::Language::Runtime.transform(source, using: false)
@@ -33,7 +33,7 @@ module RubyNext
33
33
  module ClassEval
34
34
  refine Module do
35
35
  def module_eval(*args, &block)
36
- return super(*args, &block) if block_given?
36
+ return super(*args, &block) if block
37
37
 
38
38
  source = args.shift
39
39
  new_source = ::RubyNext::Language::Runtime.transform(source, using: false)
@@ -42,7 +42,7 @@ module RubyNext
42
42
  end
43
43
 
44
44
  def class_eval(*args, &block)
45
- return super(*args, &block) if block_given?
45
+ return super(*args, &block) if block
46
46
 
47
47
  source = args.shift
48
48
  new_source = ::RubyNext::Language::Runtime.transform(source, using: false)
@@ -4,8 +4,24 @@ require "parser/rubynext"
4
4
 
5
5
  module RubyNext
6
6
  module Language
7
+ module BuilderExt
8
+ def match_pattern(lhs, match_t, rhs)
9
+ n(:match_pattern, [lhs, rhs],
10
+ binary_op_map(lhs, match_t, rhs))
11
+ end
12
+
13
+ def match_pattern_p(lhs, match_t, rhs)
14
+ n(:match_pattern_p, [lhs, rhs],
15
+ binary_op_map(lhs, match_t, rhs))
16
+ end
17
+ end
18
+
7
19
  class Builder < ::Parser::Builders::Default
8
20
  modernize
21
+
22
+ unless method_defined?(:match_pattern_p)
23
+ include BuilderExt
24
+ end
9
25
  end
10
26
 
11
27
  class << self
@@ -5,22 +5,26 @@ module RubyNext
5
5
  module Rewriters
6
6
  class ArgsForward < Base
7
7
  NAME = "args-forward"
8
- SYNTAX_PROBE = "obj = Object.new; def obj.foo(...) super(1, ...); end"
9
- MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
8
+ SYNTAX_PROBE = "obj = Object.new; def obj.foo(...) super(...); end"
9
+ MIN_SUPPORTED_VERSION = Gem::Version.new("2.7.0")
10
10
 
11
11
  REST = :__rest__
12
12
  BLOCK = :__block__
13
13
 
14
- def on_forward_arg(node)
14
+ def on_args(node)
15
+ farg = node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forward_arg }
16
+ return unless farg
17
+
15
18
  context.track! self
16
19
 
17
20
  node = super(node)
18
21
 
19
- replace(node.loc.expression, "*#{REST}, &#{BLOCK}")
22
+ replace(farg.loc.expression, "*#{REST}, &#{BLOCK}")
20
23
 
21
24
  node.updated(
22
25
  :args,
23
26
  [
27
+ *node.children.slice(0, node.children.index(farg)),
24
28
  s(:restarg, REST),
25
29
  s(:blockarg, BLOCK)
26
30
  ]
@@ -28,14 +32,14 @@ module RubyNext
28
32
  end
29
33
 
30
34
  def on_send(node)
31
- fargs = node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forwarded_args }
35
+ fargs = extract_fargs(node)
32
36
  return super(node) unless fargs
33
37
 
34
38
  process_fargs(node, fargs)
35
39
  end
36
40
 
37
41
  def on_super(node)
38
- fargs = node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forwarded_args }
42
+ fargs = extract_fargs(node)
39
43
  return super(node) unless fargs
40
44
 
41
45
  process_fargs(node, fargs)
@@ -43,6 +47,10 @@ module RubyNext
43
47
 
44
48
  private
45
49
 
50
+ def extract_fargs(node)
51
+ node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forwarded_args }
52
+ end
53
+
46
54
  def process_fargs(node, fargs)
47
55
  replace(fargs.loc.expression, "*#{REST}, &#{BLOCK}")
48
56
 
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyNext
4
+ module Language
5
+ module Rewriters
6
+ class ArgsForwardLeading < ArgsForward
7
+ NAME = "args-forward-leading"
8
+ SYNTAX_PROBE = "obj = Object.new; def obj.foo(...) super(1, ...); end"
9
+ MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
10
+
11
+ attr_reader :leading_farg
12
+ alias leading_farg? leading_farg
13
+
14
+ def on_def(node)
15
+ @leading_farg = method_with_leading_arg(node)
16
+
17
+ super
18
+ end
19
+
20
+ def on_defs(node)
21
+ @leading_farg = method_with_leading_arg(node)
22
+
23
+ super
24
+ end
25
+
26
+ def on_args(node)
27
+ return super if leading_farg?
28
+
29
+ node
30
+ end
31
+
32
+ def on_send(node)
33
+ return super if leading_farg?
34
+
35
+ node
36
+ end
37
+
38
+ def on_super(node)
39
+ return super if leading_farg?
40
+
41
+ node
42
+ end
43
+
44
+ private
45
+
46
+ def send_with_leading_farg(node)
47
+ return false unless node.type == :send || node.type == :super
48
+
49
+ fargs = extract_fargs(node)
50
+
51
+ return false unless fargs
52
+
53
+ node.children.index(fargs) > (node.type == :send ? 2 : 0)
54
+ end
55
+
56
+ def method_with_leading_arg(node)
57
+ find_child(node) { |child| child.type == :forward_arg } &&
58
+ (
59
+ def_with_leading_farg(node) ||
60
+ find_child(node) { |child| send_with_leading_farg(child) }
61
+ )
62
+ end
63
+
64
+ def def_with_leading_farg(node)
65
+ args = node.type == :defs ? node.children[2] : node.children[1]
66
+ args = args.children
67
+
68
+ farg = args.detect { |child| child.type == :forward_arg }
69
+
70
+ args.index(farg) > 0
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -61,7 +61,7 @@ module RubyNext
61
61
  eval_mid = Kernel.respond_to?(:eval_without_ruby_next) ? :eval_without_ruby_next : :eval
62
62
  Kernel.send eval_mid, self::SYNTAX_PROBE, nil, __FILE__, __LINE__
63
63
  false
64
- rescue SyntaxError, NameError
64
+ rescue SyntaxError, StandardError
65
65
  true
66
66
  ensure
67
67
  $VERBOSE = save_verbose
@@ -94,6 +94,24 @@ module RubyNext
94
94
 
95
95
  private
96
96
 
97
+ # BFS with predicate block
98
+ def find_child(node)
99
+ queue = [node]
100
+
101
+ loop do
102
+ break if queue.empty?
103
+
104
+ child = queue.shift
105
+ next unless child.is_a?(::Parser::AST::Node)
106
+
107
+ return child if yield child
108
+
109
+ queue.push(*child.children)
110
+ end
111
+
112
+ nil
113
+ end
114
+
97
115
  def replace(range, ast)
98
116
  @source_rewriter&.replace(range, unparse(ast))
99
117
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ruby-next/language/rewriters/pattern_matching"
4
+
5
+ module RubyNext
6
+ module Language
7
+ module Rewriters
8
+ using RubyNext
9
+
10
+ # Separate pattern matching rewriter for Ruby 2.7 to
11
+ # transpile only `in` patterns
12
+ class InPattern < PatternMatching
13
+ NAME = "pattern-matching-in"
14
+ SYNTAX_PROBE = "1 in 2"
15
+ MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
16
+
17
+ # Make case-match no-op
18
+ def on_case_match(node)
19
+ node
20
+ end
21
+
22
+ def on_match_pattern_p(node)
23
+ context.track! self
24
+
25
+ @deconstructed_keys = {}
26
+ @predicates = Predicates::Noop.new
27
+
28
+ matchee =
29
+ s(:begin, s(:lvasgn, MATCHEE, node.children[0]))
30
+
31
+ pattern =
32
+ locals.with(
33
+ matchee: MATCHEE,
34
+ arr: MATCHEE_ARR,
35
+ hash: MATCHEE_HASH
36
+ ) do
37
+ send(
38
+ :"#{node.children[1].type}_clause",
39
+ node.children[1]
40
+ )
41
+ end
42
+
43
+ node.updated(
44
+ :and,
45
+ [
46
+ matchee,
47
+ pattern
48
+ ]
49
+ ).tap do |new_node|
50
+ replace(node.loc.expression, inline_blocks(unparse(new_node)))
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -6,7 +6,7 @@ module RubyNext
6
6
  class MethodReference < Base
7
7
  NAME = "method-reference"
8
8
  SYNTAX_PROBE = "Language.:transform"
9
- MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
9
+ MIN_SUPPORTED_VERSION = Gem::Version.new(RubyNext::NEXT_VERSION)
10
10
 
11
11
  def on_meth_ref(node)
12
12
  context.track! self
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyNext
4
+ module Language
5
+ module Rewriters
6
+ class NumericLiterals < Base
7
+ using RubyNext
8
+
9
+ NAME = "numeric-literals"
10
+ SYNTAX_PROBE = "2i + 1/2r"
11
+ MIN_SUPPORTED_VERSION = Gem::Version.new("2.1.0")
12
+
13
+ def on_rational(node)
14
+ context.track! self
15
+
16
+ val = node.children.first
17
+
18
+ parts = [s(:int, val.numerator)]
19
+
20
+ parts << s(:int, val.denominator) unless val.denominator == 1
21
+
22
+ s(:send, nil, :Rational, *parts).tap do |new_node|
23
+ replace(node.loc.expression, new_node)
24
+ end
25
+ end
26
+
27
+ def on_complex(node)
28
+ context.track! self
29
+
30
+ val = node.children.first
31
+
32
+ s(:send, nil, :Complex,
33
+ s(:int, val.real),
34
+ s(:int, val.imaginary)).tap do |new_node|
35
+ replace(node.loc.expression, new_node)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -13,12 +13,12 @@ module RubyNext
13
13
 
14
14
  # Useful to generate simple operation nodes
15
15
  # (e.g., 'a + b')
16
- def -(val)
17
- ::Parser::AST::Node.new(:send, [self, :-, val.to_ast_node])
16
+ def -(other)
17
+ ::Parser::AST::Node.new(:send, [self, :-, other.to_ast_node])
18
18
  end
19
19
 
20
- def +(val)
21
- ::Parser::AST::Node.new(:send, [self, :+, val.to_ast_node])
20
+ def +(other)
21
+ ::Parser::AST::Node.new(:send, [self, :+, other.to_ast_node])
22
22
  end
23
23
  end
24
24
 
@@ -218,9 +218,10 @@ module RubyNext
218
218
  predicate_clause(:respond_to_deconstruct_keys, node)
219
219
  end
220
220
 
221
- def hash_key(node, key)
222
- key = key.children.first if key.is_a?(::Parser::AST::Node)
223
- predicate_clause(:"hash_key_#{key}", node)
221
+ def hash_keys(node, keys)
222
+ keys = keys.map { |key| key.is_a?(::Parser::AST::Node) ? key.children.first : key }
223
+
224
+ predicate_clause(:"hash_keys_#{keys.join("_p_")}", node)
224
225
  end
225
226
  end
226
227
  end
@@ -266,7 +267,7 @@ module RubyNext
266
267
  )
267
268
  end
268
269
 
269
- def on_in_match(node)
270
+ def on_match_pattern(node)
270
271
  context.track! self
271
272
 
272
273
  @deconstructed_keys = {}
@@ -303,6 +304,8 @@ module RubyNext
303
304
  end
304
305
  end
305
306
 
307
+ alias on_in_match on_match_pattern
308
+
306
309
  private
307
310
 
308
311
  def rewrite_case_in!(node, matchee, new_node)
@@ -350,7 +353,7 @@ module RubyNext
350
353
 
351
354
  else_clause = (else_clause || no_matching_pattern).then do |node|
352
355
  next node unless node.type == :empty_else
353
- s(:empty)
356
+ nil
354
357
  end
355
358
 
356
359
  clauses << else_clause
@@ -883,14 +886,14 @@ module RubyNext
883
886
  end
884
887
 
885
888
  def having_hash_keys(keys, hash = s(:lvar, locals[:hash]))
886
- key = keys.shift
887
- node = predicates.hash_key(hash_has_key(key, hash), key)
889
+ keys.reduce(nil) do |acc, key|
890
+ pnode = hash_has_key(key, hash)
891
+ next pnode unless acc
888
892
 
889
- keys.reduce(node) do |res, key|
890
893
  s(:begin,
891
- s(:and,
892
- res,
893
- predicates.hash_key(hash_has_key(key, hash), key)))
894
+ s(:and, acc, pnode))
895
+ end.then do |node|
896
+ predicates.hash_keys(node, keys)
894
897
  end
895
898
  end
896
899
 
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyNext
4
+ module Language
5
+ module Rewriters
6
+ class RequiredKwargs < Base
7
+ using RubyNext
8
+
9
+ NAME = "required-kwargs"
10
+ SYNTAX_PROBE = "obj = Object.new; def obj.foo(x:, y: 1); end"
11
+ MIN_SUPPORTED_VERSION = Gem::Version.new("2.1.0")
12
+
13
+ def on_kwarg(node)
14
+ context.track! self
15
+
16
+ name = node.children[0]
17
+
18
+ new_node = node.updated(
19
+ :kwoptarg,
20
+ [name, raise_missing_keyword(name)]
21
+ )
22
+
23
+ replace(node.loc.expression, "#{name}: ::Kernel.raise(::ArgumentError, \"missing keyword: #{name}\")")
24
+
25
+ new_node
26
+ end
27
+
28
+ private
29
+
30
+ def raise_missing_keyword(name)
31
+ s(:send,
32
+ s(:const, s(:cbase), :Kernel), :raise,
33
+ s(:const, s(:cbase), :ArgumentError),
34
+ s(:str, "missing keyword: #{name}"))
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -8,6 +8,8 @@ module RubyNext
8
8
  SYNTAX_PROBE = "nil&.x&.nil?"
9
9
  MIN_SUPPORTED_VERSION = Gem::Version.new("2.3.0")
10
10
 
11
+ SAFE_LVAR = :__safe_lvar__
12
+
11
13
  def on_csend(node)
12
14
  node = super(node)
13
15
 
@@ -20,7 +22,7 @@ module RubyNext
20
22
  :and,
21
23
  [
22
24
  process(safe_navigation(receiver)),
23
- s(:send, decsendize(receiver), *args)
25
+ s(:send, safe_lvar, *args)
24
26
  ]
25
27
  ))
26
28
 
@@ -34,18 +36,15 @@ module RubyNext
34
36
 
35
37
  context.track!(self)
36
38
 
37
- new_node = s(:begin,
38
- super(node.updated(
39
- :and,
40
- [
41
- process(safe_navigation(node.children[0].children[0])),
42
- process(node.updated(nil, node.children.map(&method(:decsendize))))
43
- ]
44
- )))
39
+ super(decsendize(node))
40
+ end
45
41
 
46
- replace(node.loc.expression, new_node)
42
+ def on_numblock(node)
43
+ return super(node) unless node.children[0].type == :csend
47
44
 
48
- new_node
45
+ context.track!(self)
46
+
47
+ super(decsendize(node))
49
48
  end
50
49
 
51
50
  def on_op_asgn(node)
@@ -53,37 +52,51 @@ module RubyNext
53
52
 
54
53
  context.track!(self)
55
54
 
55
+ super(decsendize(node))
56
+ end
57
+
58
+ private
59
+
60
+ def decsendize(node)
61
+ csend, *children = node.children
62
+
63
+ receiver, *other = csend.children
64
+
65
+ new_csend = csend.updated(:send, [safe_lvar, *other])
66
+
56
67
  new_node = s(:begin,
57
- super(node.updated(
68
+ node.updated(
58
69
  :and,
59
70
  [
60
- process(safe_navigation(node.children[0].children[0])),
61
- process(node.updated(nil, node.children.map(&method(:decsendize))))
71
+ process(safe_navigation(receiver)),
72
+ process(node.updated(nil, [new_csend, *children]))
62
73
  ]
63
- )))
74
+ ))
64
75
 
65
76
  replace(node.loc.expression, new_node)
66
77
 
67
78
  new_node
68
79
  end
69
80
 
70
- private
71
-
72
- def decsendize(node)
73
- return node unless node.is_a?(::Parser::AST::Node) && node.type == :csend
74
-
75
- node.updated(:send, node.children.map(&method(:decsendize)))
76
- end
77
-
78
- # Transform: x&.y -> (!x.nil? && x.y) || nil
81
+ # Transform: x&.y -> ((_tmp_ = x) || true) && (!_tmp_.nil? || nil) && _tmp_.y
79
82
  # This allows us to handle `false&.to_s == "false"`
80
83
  def safe_navigation(node)
81
84
  s(:begin,
82
- s(:or,
83
- s(:send,
84
- s(:send, node, :nil?),
85
- :!),
86
- s(:nil)))
85
+ s(:and,
86
+ s(:begin,
87
+ s(:or,
88
+ s(:begin, s(:lvasgn, SAFE_LVAR, node)),
89
+ s(:true))),
90
+ s(:begin,
91
+ s(:or,
92
+ s(:send,
93
+ s(:send, safe_lvar, :nil?),
94
+ :!),
95
+ s(:nil)))))
96
+ end
97
+
98
+ def safe_lvar
99
+ s(:lvar, SAFE_LVAR)
87
100
  end
88
101
  end
89
102
  end
@@ -6,7 +6,7 @@ module RubyNext
6
6
  class ShorthandHash < Base
7
7
  NAME = "shorthand-hash"
8
8
  SYNTAX_PROBE = "data = {x}"
9
- MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
9
+ MIN_SUPPORTED_VERSION = Gem::Version.new(RubyNext::NEXT_VERSION)
10
10
 
11
11
  def on_ipair(node)
12
12
  context.track! self
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Make sure Core is loaded
4
4
  require "ruby-next"
5
+ require "pathname"
5
6
 
6
7
  module RubyNext
7
8
  module Language
@@ -29,7 +30,7 @@ module RubyNext
29
30
 
30
31
  def setup_gem_load_path(lib_dir = "lib", rbnext_dir: RUBY_NEXT_DIR, transpile: false)
31
32
  called_from = caller_locations(1, 1).first.path
32
- dirname = File.dirname(called_from)
33
+ dirname = File.realpath(File.dirname(called_from))
33
34
 
34
35
  loop do
35
36
  basename = File.basename(dirname)
@@ -48,11 +49,13 @@ module RubyNext
48
49
 
49
50
  GemTranspiler.maybe_transpile(File.dirname(dirname), lib_dir, next_dirname) if transpile
50
51
 
51
- current_index = $LOAD_PATH.index(dirname)
52
+ current_index = $LOAD_PATH.find_index do |load_path|
53
+ Pathname.new(load_path).realpath.to_s == dirname
54
+ end
52
55
 
53
56
  raise "Gem's lib is not in the $LOAD_PATH: #{dirname}" if current_index.nil?
54
57
 
55
- version = RubyNext.next_version
58
+ version = RubyNext.next_ruby_version
56
59
 
57
60
  loop do
58
61
  break unless version
@@ -64,7 +67,7 @@ module RubyNext
64
67
  current_index += 1
65
68
  end
66
69
 
67
- version = RubyNext.next_version(version)
70
+ version = RubyNext.next_ruby_version(version)
68
71
  end
69
72
  end
70
73
  end
@@ -6,3 +6,8 @@ require "parser/current"
6
6
  $VERBOSE = save_verbose
7
7
 
8
8
  require "unparser"
9
+
10
+ # For backward compatibility with older Unparser
11
+ if RubyNext::Language::Builder.respond_to?(:emit_kwargs=) && !defined?(Unparser::Emitter::Kwargs)
12
+ RubyNext::Language::Builder.emit_kwargs = false
13
+ end