ruby-next-core 0.10.5 → 0.13.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +41 -0
- data/README.md +25 -16
- data/lib/.rbnext/2.1/ruby-next/core.rb +206 -0
- data/lib/.rbnext/2.1/ruby-next/language.rb +227 -0
- data/lib/.rbnext/2.3/ruby-next/commands/nextify.rb +2 -2
- data/lib/.rbnext/2.3/ruby-next/language/eval.rb +4 -4
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/base.rb +23 -5
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/endless_range.rb +1 -1
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/pattern_matching.rb +20 -17
- data/lib/.rbnext/2.3/ruby-next/utils.rb +1 -1
- data/lib/.rbnext/2.7/ruby-next/core.rb +206 -0
- data/lib/ruby-next/commands/nextify.rb +1 -1
- data/lib/ruby-next/config.rb +50 -0
- data/lib/ruby-next/core/array/deconstruct.rb +1 -1
- data/lib/ruby-next/core/array/intersect.rb +9 -0
- data/lib/ruby-next/core/constants/frozen_error.rb +15 -0
- data/lib/ruby-next/core/constants/no_matching_pattern_error.rb +1 -1
- data/lib/ruby-next/core/enumerable/tally.rb +46 -7
- data/lib/ruby-next/core/hash/deconstruct_keys.rb +1 -1
- data/lib/ruby-next/core/struct/deconstruct_keys.rb +3 -3
- data/lib/ruby-next/core.rb +8 -4
- data/lib/ruby-next/core_ext.rb +3 -1
- data/lib/ruby-next/language/bootsnap.rb +1 -1
- data/lib/ruby-next/language/edge.rb +0 -6
- data/lib/ruby-next/language/eval.rb +3 -3
- data/lib/ruby-next/language/parser.rb +16 -0
- data/lib/ruby-next/language/rewriters/args_forward.rb +14 -6
- data/lib/ruby-next/language/rewriters/args_forward_leading.rb +75 -0
- data/lib/ruby-next/language/rewriters/base.rb +19 -1
- data/lib/ruby-next/language/rewriters/in_pattern.rb +56 -0
- data/lib/ruby-next/language/rewriters/method_reference.rb +1 -1
- data/lib/ruby-next/language/rewriters/numeric_literals.rb +41 -0
- data/lib/ruby-next/language/rewriters/pattern_matching.rb +18 -15
- data/lib/ruby-next/language/rewriters/required_kwargs.rb +39 -0
- data/lib/ruby-next/language/rewriters/safe_navigation.rb +42 -29
- data/lib/ruby-next/language/rewriters/shorthand_hash.rb +1 -1
- data/lib/ruby-next/language/setup.rb +7 -4
- data/lib/ruby-next/language/unparser.rb +5 -0
- data/lib/ruby-next/language.rb +62 -44
- data/lib/ruby-next/rubocop.rb +9 -18
- data/lib/ruby-next/setup_self.rb +5 -3
- data/lib/ruby-next/version.rb +1 -1
- data/lib/ruby-next.rb +5 -38
- metadata +20 -18
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/right_hand_assignment.rb +0 -117
- 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
|
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
|
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
|
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(
|
9
|
-
MIN_SUPPORTED_VERSION = Gem::Version.new("
|
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
|
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(
|
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
|
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
|
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,
|
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(
|
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 -(
|
17
|
-
::Parser::AST::Node.new(:send, [self, :-,
|
16
|
+
def -(other)
|
17
|
+
::Parser::AST::Node.new(:send, [self, :-, other.to_ast_node])
|
18
18
|
end
|
19
19
|
|
20
|
-
def +(
|
21
|
-
::Parser::AST::Node.new(:send, [self, :+,
|
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
|
222
|
-
|
223
|
-
|
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
|
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
|
-
|
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
|
-
|
887
|
-
|
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
|
-
|
893
|
-
|
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,
|
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
|
-
|
38
|
-
|
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
|
-
|
42
|
+
def on_numblock(node)
|
43
|
+
return super(node) unless node.children[0].type == :csend
|
47
44
|
|
48
|
-
|
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
|
-
|
68
|
+
node.updated(
|
58
69
|
:and,
|
59
70
|
[
|
60
|
-
process(safe_navigation(
|
61
|
-
process(node.updated(nil,
|
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
|
-
|
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(:
|
83
|
-
s(:
|
84
|
-
s(:
|
85
|
-
|
86
|
-
|
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(
|
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.
|
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.
|
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.
|
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
|