ruby-next-core 0.9.2 → 0.10.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 +22 -0
- data/README.md +14 -4
- data/lib/.rbnext/2.3/ruby-next/commands/core_ext.rb +167 -0
- data/lib/.rbnext/2.3/ruby-next/commands/nextify.rb +198 -0
- data/lib/.rbnext/2.3/ruby-next/language/eval.rb +66 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/base.rb +121 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/endless_range.rb +63 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/pattern_matching.rb +944 -0
- data/lib/.rbnext/2.3/ruby-next/utils.rb +65 -0
- data/lib/ruby-next.rb +8 -6
- data/lib/ruby-next/cli.rb +2 -2
- data/lib/ruby-next/commands/core_ext.rb +1 -1
- data/lib/ruby-next/core.rb +27 -21
- data/lib/ruby-next/core/array/deconstruct.rb +9 -9
- data/lib/ruby-next/core/array/difference_union_intersection.rb +12 -12
- data/lib/ruby-next/core/constants/no_matching_pattern_error.rb +3 -3
- data/lib/ruby-next/core/enumerable/filter.rb +8 -8
- data/lib/ruby-next/core/enumerable/filter_map.rb +25 -25
- data/lib/ruby-next/core/enumerable/tally.rb +7 -7
- data/lib/ruby-next/core/enumerator/produce.rb +12 -12
- data/lib/ruby-next/core/hash/deconstruct_keys.rb +9 -9
- data/lib/ruby-next/core/hash/except.rb +11 -0
- data/lib/ruby-next/core/hash/merge.rb +8 -8
- data/lib/ruby-next/core/kernel/then.rb +2 -2
- data/lib/ruby-next/core/proc/compose.rb +11 -11
- data/lib/ruby-next/core/string/split.rb +6 -6
- data/lib/ruby-next/core/struct/deconstruct.rb +2 -2
- data/lib/ruby-next/core/struct/deconstruct_keys.rb +17 -17
- data/lib/ruby-next/core/symbol/end_with.rb +4 -4
- data/lib/ruby-next/core/symbol/start_with.rb +4 -4
- data/lib/ruby-next/core/time/ceil.rb +6 -6
- data/lib/ruby-next/core/time/floor.rb +4 -4
- data/lib/ruby-next/core/unboundmethod/bind_call.rb +4 -4
- data/lib/ruby-next/core_ext.rb +1 -1
- data/lib/ruby-next/language.rb +12 -1
- data/lib/ruby-next/language/parser.rb +0 -3
- data/lib/ruby-next/language/proposed.rb +3 -0
- data/lib/ruby-next/language/rewriters/args_forward.rb +23 -20
- data/lib/ruby-next/language/rewriters/base.rb +1 -1
- data/lib/ruby-next/language/rewriters/endless_method.rb +25 -3
- data/lib/ruby-next/language/rewriters/find_pattern.rb +44 -0
- data/lib/ruby-next/language/rewriters/method_reference.rb +1 -1
- data/lib/ruby-next/language/rewriters/pattern_matching.rb +102 -12
- data/lib/ruby-next/language/rewriters/right_hand_assignment.rb +1 -1
- data/lib/ruby-next/language/rewriters/safe_navigation.rb +87 -0
- data/lib/ruby-next/language/rewriters/shorthand_hash.rb +47 -0
- data/lib/ruby-next/language/rewriters/squiggly_heredoc.rb +36 -0
- data/lib/ruby-next/language/unparser.rb +0 -14
- data/lib/ruby-next/logging.rb +1 -1
- data/lib/ruby-next/rubocop.rb +15 -9
- data/lib/ruby-next/setup_self.rb +22 -0
- data/lib/ruby-next/version.rb +1 -1
- data/lib/uby-next.rb +8 -4
- metadata +20 -7
@@ -1,21 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RubyNext::Core.patch Hash, method: :deconstruct_keys, version: "2.7" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
<<-RUBY
|
5
|
+
def deconstruct_keys(_)
|
6
|
+
self
|
7
|
+
end
|
8
8
|
RUBY
|
9
9
|
end
|
10
10
|
|
11
11
|
# We need to hack `respond_to?` in Ruby 2.5, since it's not working with refinements
|
12
12
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.6")
|
13
13
|
RubyNext::Core.patch refineable: Hash, name: "HashRespondToDeconstructKeys", method: :deconstruct_keys, version: "2.7" do
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
<<-RUBY
|
15
|
+
def respond_to?(mid, *)
|
16
|
+
return true if mid == :deconstruct_keys
|
17
|
+
super
|
18
|
+
end
|
19
19
|
RUBY
|
20
20
|
end
|
21
21
|
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RubyNext::Core.patch Hash, method: :merge, version: "2.6", supported: {}.method(:merge).arity < 0, core_ext: :prepend do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
<<-RUBY
|
5
|
+
def merge(*others)
|
6
|
+
return super if others.size == 1
|
7
|
+
return dup if others.size == 0
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
merge(others.shift).tap do |new_h|
|
10
|
+
others.each { |h| new_h.merge!(h) }
|
11
|
+
end
|
12
|
+
end
|
13
13
|
RUBY
|
14
14
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# - https://bugs.ruby-lang.org/issues/13446
|
5
5
|
# - Rails added `Kernel.prepend` in 6.1: https://github.com/rails/rails/commit/3124007bd674dcdc9c3b5c6b2964dfb7a1a0733c
|
6
6
|
RubyNext::Core.patch Kernel, method: :then, version: "2.6", refineable: Object do
|
7
|
-
|
8
|
-
|
7
|
+
<<-RUBY
|
8
|
+
alias then yield_self
|
9
9
|
RUBY
|
10
10
|
end
|
@@ -2,18 +2,18 @@
|
|
2
2
|
|
3
3
|
# rubocop:disable Style/LambdaCall
|
4
4
|
RubyNext::Core.patch Proc, name: "ProcCompose", method: :<<, version: "2.6" do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
<<-RUBY
|
6
|
+
def <<(other)
|
7
|
+
raise TypeError, "callable object is expected" unless other.respond_to?(:call)
|
8
|
+
this = self
|
9
|
+
proc { |*args, &block| this.(other.(*args, &block)) }
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def >>(other)
|
13
|
+
raise TypeError, "callable object is expected" unless other.respond_to?(:call)
|
14
|
+
this = self
|
15
|
+
proc { |*args, &block| other.(this.(*args, &block)) }
|
16
|
+
end
|
17
17
|
RUBY
|
18
18
|
end
|
19
19
|
# rubocop:enable Style/LambdaCall
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RubyNext::Core.patch String, method: :split, version: "2.6", supported: ("a b".split(" ", &proc {}) == "a b"), core_ext: :prepend do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
<<-RUBY
|
5
|
+
def split(*args, &block)
|
6
|
+
return super unless block_given?
|
7
|
+
super.each { |el| yield el }
|
8
|
+
self
|
9
|
+
end
|
10
10
|
RUBY
|
11
11
|
end
|
@@ -2,31 +2,31 @@
|
|
2
2
|
|
3
3
|
# Source: https://github.com/ruby/ruby/blob/b76a21aa45fff75909a66f8b20fc5856705f7862/struct.c#L953-L980
|
4
4
|
RubyNext::Core.patch Struct, method: :deconstruct_keys, version: "2.7" do
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
<<-'RUBY'
|
6
|
+
def deconstruct_keys(keys)
|
7
|
+
raise TypeError, "wrong argument type #{keys.class} (expected Array or nil)" if keys && !keys.is_a?(Array)
|
8
8
|
|
9
|
-
|
9
|
+
return to_h unless keys
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
keys.each_with_object({}) do |k, acc|
|
12
|
+
# if k is Symbol and not a member of a Struct return {}
|
13
|
+
next if (Symbol === k || String === k) && !members.include?(k.to_sym)
|
14
|
+
# if k is Integer check that index is not ouf of bounds
|
15
|
+
next if Integer === k && k > size - 1
|
16
|
+
acc[k] = self[k]
|
17
|
+
end
|
18
|
+
end
|
19
19
|
RUBY
|
20
20
|
end
|
21
21
|
|
22
22
|
# We need to hack `respond_to?` in Ruby 2.5, since it's not working with refinements
|
23
23
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.6")
|
24
24
|
RubyNext::Core.patch refineable: Struct, name: "StructRespondToDeconstruct", method: :deconstruct_keys, version: "2.7" do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
<<-RUBY
|
26
|
+
def respond_to?(mid, *)
|
27
|
+
return true if mid == :deconstruct_keys || mid == :deconstruct
|
28
|
+
super
|
29
|
+
end
|
30
30
|
RUBY
|
31
31
|
end
|
32
32
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RubyNext::Core.patch Symbol, method: :start_with?, version: "2.7" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
<<-RUBY
|
5
|
+
def start_with?(*prefixes)
|
6
|
+
to_s.start_with?(*prefixes)
|
7
|
+
end
|
8
8
|
RUBY
|
9
9
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RubyNext::Core.patch Time, method: :ceil, version: "2.7" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
<<-RUBY
|
5
|
+
def ceil(den = 0)
|
6
|
+
sceil = (subsec * 10**den).ceil.to_r / 10**den
|
7
|
+
change = sceil - subsec
|
8
|
+
self + change
|
9
|
+
end
|
10
10
|
RUBY
|
11
11
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RubyNext::Core.patch UnboundMethod, method: :bind_call, version: "2.7" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
<<-RUBY
|
5
|
+
def bind_call(receiver, *args, &block)
|
6
|
+
bind(receiver).call(*args, &block)
|
7
|
+
end
|
8
8
|
RUBY
|
9
9
|
end
|
data/lib/ruby-next/core_ext.rb
CHANGED
data/lib/ruby-next/language.rb
CHANGED
@@ -100,7 +100,7 @@ module RubyNext
|
|
100
100
|
else
|
101
101
|
regenerate(*args, **kwargs)
|
102
102
|
end
|
103
|
-
rescue Unparser::
|
103
|
+
rescue Unparser::UnknownNodeError
|
104
104
|
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0")
|
105
105
|
RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since Unparser doesn't support 2.7+ AST yet.\n" \
|
106
106
|
"See https://github.com/mbj/unparser/pull/142"
|
@@ -173,6 +173,12 @@ module RubyNext
|
|
173
173
|
|
174
174
|
require "ruby-next/language/rewriters/base"
|
175
175
|
|
176
|
+
require "ruby-next/language/rewriters/squiggly_heredoc"
|
177
|
+
rewriters << Rewriters::SquigglyHeredoc
|
178
|
+
|
179
|
+
require "ruby-next/language/rewriters/safe_navigation"
|
180
|
+
rewriters << Rewriters::SafeNavigation
|
181
|
+
|
176
182
|
require "ruby-next/language/rewriters/args_forward"
|
177
183
|
rewriters << Rewriters::ArgsForward
|
178
184
|
|
@@ -182,6 +188,11 @@ module RubyNext
|
|
182
188
|
require "ruby-next/language/rewriters/pattern_matching"
|
183
189
|
rewriters << Rewriters::PatternMatching
|
184
190
|
|
191
|
+
# Must be added after general pattern matching rewriter to become
|
192
|
+
# no-op in Ruby <2.7
|
193
|
+
require "ruby-next/language/rewriters/find_pattern"
|
194
|
+
rewriters << Rewriters::FindPattern
|
195
|
+
|
185
196
|
# Put endless range in the end, 'cause Parser fails to parse it in
|
186
197
|
# pattern matching
|
187
198
|
require "ruby-next/language/rewriters/endless_range"
|
@@ -4,3 +4,6 @@
|
|
4
4
|
|
5
5
|
require "ruby-next/language/rewriters/method_reference"
|
6
6
|
RubyNext::Language.rewriters << RubyNext::Language::Rewriters::MethodReference
|
7
|
+
|
8
|
+
require "ruby-next/language/rewriters/shorthand_hash"
|
9
|
+
RubyNext::Language.rewriters << RubyNext::Language::Rewriters::ShorthandHash
|
@@ -5,16 +5,18 @@ 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(...); end"
|
9
|
-
MIN_SUPPORTED_VERSION = Gem::Version.new("2.7.
|
8
|
+
SYNTAX_PROBE = "obj = Object.new; def obj.foo(...) super(1, ...); end"
|
9
|
+
MIN_SUPPORTED_VERSION = Gem::Version.new("2.7.2")
|
10
10
|
|
11
11
|
REST = :__rest__
|
12
12
|
BLOCK = :__block__
|
13
13
|
|
14
|
-
def
|
14
|
+
def on_forward_arg(node)
|
15
15
|
context.track! self
|
16
16
|
|
17
|
-
|
17
|
+
node = super(node)
|
18
|
+
|
19
|
+
replace(node.loc.expression, "*#{REST}, &#{BLOCK}")
|
18
20
|
|
19
21
|
node.updated(
|
20
22
|
:args,
|
@@ -26,34 +28,35 @@ module RubyNext
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def on_send(node)
|
29
|
-
|
31
|
+
fargs = node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forwarded_args }
|
32
|
+
return super(node) unless fargs
|
33
|
+
|
34
|
+
process_fargs(node, fargs)
|
35
|
+
end
|
36
|
+
|
37
|
+
def on_super(node)
|
38
|
+
fargs = node.children.find { |child| child.is_a?(::Parser::AST::Node) && child.type == :forwarded_args }
|
39
|
+
return super(node) unless fargs
|
40
|
+
|
41
|
+
process_fargs(node, fargs)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
30
45
|
|
31
|
-
|
46
|
+
def process_fargs(node, fargs)
|
47
|
+
replace(fargs.loc.expression, "*#{REST}, &#{BLOCK}")
|
32
48
|
|
33
49
|
process(
|
34
50
|
node.updated(
|
35
51
|
nil,
|
36
52
|
[
|
37
|
-
*node.children
|
53
|
+
*node.children.take(node.children.index(fargs)),
|
38
54
|
*forwarded_args
|
39
55
|
]
|
40
56
|
)
|
41
57
|
)
|
42
58
|
end
|
43
59
|
|
44
|
-
def on_super(node)
|
45
|
-
return super(node) unless node.children[0]&.type == :forwarded_args
|
46
|
-
|
47
|
-
replace(node.children[0].loc.expression, "*#{REST}, &#{BLOCK}")
|
48
|
-
|
49
|
-
node.updated(
|
50
|
-
nil,
|
51
|
-
forwarded_args
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
60
|
def forwarded_args
|
58
61
|
[
|
59
62
|
s(:splat, s(:lvar, REST)),
|
@@ -6,7 +6,14 @@ module RubyNext
|
|
6
6
|
class EndlessMethod < Base
|
7
7
|
NAME = "endless-method"
|
8
8
|
SYNTAX_PROBE = "obj = Object.new; def obj.foo() = 42"
|
9
|
-
MIN_SUPPORTED_VERSION = Gem::Version.new("
|
9
|
+
MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
|
10
|
+
|
11
|
+
unless Parser::Meta::NODE_TYPES.include?(:def_e)
|
12
|
+
def on_def(node)
|
13
|
+
return on_def_e(node) if node.loc.end.nil?
|
14
|
+
super(node)
|
15
|
+
end
|
16
|
+
end
|
10
17
|
|
11
18
|
def on_def_e(node)
|
12
19
|
context.track! self
|
@@ -14,24 +21,39 @@ module RubyNext
|
|
14
21
|
replace(node.loc.assignment, "; ")
|
15
22
|
insert_after(node.loc.expression, "; end")
|
16
23
|
|
24
|
+
new_loc = node.loc.dup
|
25
|
+
new_loc.instance_variable_set(:@end, node.loc.expression)
|
26
|
+
|
17
27
|
process(
|
18
28
|
node.updated(
|
19
29
|
:def,
|
20
|
-
node.children
|
30
|
+
node.children,
|
31
|
+
location: new_loc
|
21
32
|
)
|
22
33
|
)
|
23
34
|
end
|
24
35
|
|
36
|
+
unless Parser::Meta::NODE_TYPES.include?(:def_e)
|
37
|
+
def on_defs(node)
|
38
|
+
return on_defs_e(node) if node.loc.end.nil?
|
39
|
+
super(node)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
25
43
|
def on_defs_e(node)
|
26
44
|
context.track! self
|
27
45
|
|
28
46
|
replace(node.loc.assignment, "; ")
|
29
47
|
insert_after(node.loc.expression, "; end")
|
30
48
|
|
49
|
+
new_loc = node.loc.dup
|
50
|
+
new_loc.instance_variable_set(:@end, node.loc.expression)
|
51
|
+
|
31
52
|
process(
|
32
53
|
node.updated(
|
33
54
|
:defs,
|
34
|
-
node.children
|
55
|
+
node.children,
|
56
|
+
location: new_loc
|
35
57
|
)
|
36
58
|
)
|
37
59
|
end
|