ruby-next-core 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +15 -3
- data/lib/.rbnext/2.1/ruby-next/core.rb +3 -0
- data/lib/.rbnext/2.1/ruby-next/language.rb +227 -0
- data/lib/.rbnext/2.3/ruby-next/language/rewriters/pattern_matching.rb +1 -1
- data/lib/.rbnext/2.7/ruby-next/core.rb +3 -0
- 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/enumerable/tally.rb +46 -7
- data/lib/ruby-next/core.rb +3 -0
- data/lib/ruby-next/language/rewriters/args_forward.rb +6 -2
- data/lib/ruby-next/language/rewriters/args_forward_leading.rb +1 -1
- data/lib/ruby-next/language/rewriters/pattern_matching.rb +1 -1
- data/lib/ruby-next/language/setup.rb +1 -1
- data/lib/ruby-next/language.rb +44 -43
- data/lib/ruby-next/setup_self.rb +3 -1
- data/lib/ruby-next/version.rb +1 -1
- metadata +11 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e73900618b0d9da915699c40c610736e19919ac0d11bce7c7dc58e7d5ddb84b
|
4
|
+
data.tar.gz: b07917f44a763467f4bed145ae1224ba8aeb03eaba7924b2787c681df4b704f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb7bc9bc3416a8b6df9e99f346fb15c2c0ae0a9d63bba739adaa6c604110eaa753a5d7b00d98443400e92d7233fba7b4fda2a43e866ce85ef04ed46cd7e89a4c
|
7
|
+
data.tar.gz: 0b6410607425aaa0afb66309fa07739e72e3b8cbf94addf85d501f136755159db968225b6d1752a1bda77911592252d48e2d2c5421dae5798d5741ef6ec33616
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.13.0 (2021-09-27)
|
6
|
+
|
7
|
+
- Added `Enumerable#tally` with the resulting hash. ([@skryukov][])
|
8
|
+
|
9
|
+
- Added `Array#intersect?`. ([@skryukov][])
|
10
|
+
|
5
11
|
## 0.12.0 (2021-01-12)
|
6
12
|
|
7
13
|
- Added required keyword arguments rewriter. ([@palkan][])
|
@@ -281,3 +287,4 @@ p a #=> 1
|
|
281
287
|
[@palkan]: https://github.com/palkan
|
282
288
|
[backports]: https://github.com/marcandre/backports
|
283
289
|
[@sl4vr]: https://github.com/sl4vr
|
290
|
+
[@skryukov]: https://github.com/skryukov
|
data/README.md
CHANGED
@@ -21,8 +21,20 @@ That's why Ruby Next implements the `master` features as fast as possible.
|
|
21
21
|
|
22
22
|
Read more about the motivation behind the Ruby Next in this post: [Ruby Next: Make all Rubies quack alike](https://evilmartians.com/chronicles/ruby-next-make-all-rubies-quack-alike).
|
23
23
|
|
24
|
-
<
|
25
|
-
<
|
24
|
+
<table style="border:none;">
|
25
|
+
<tr>
|
26
|
+
<td>
|
27
|
+
<a href="https://evilmartians.com/?utm_source=ruby-next">
|
28
|
+
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
|
29
|
+
</a>
|
30
|
+
</td>
|
31
|
+
<td>
|
32
|
+
<a href="http://www.digitalfukuoka.jp/topics/169">
|
33
|
+
<img src="http://www.digitalfukuoka.jp/javascripts/kcfinder/upload/images/excellence.jpg" width="200">
|
34
|
+
</a>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
</table>
|
26
38
|
|
27
39
|
## Posts
|
28
40
|
|
@@ -510,7 +522,7 @@ require "ruby-next/language/runtime"
|
|
510
522
|
|
511
523
|
### Supported edge features
|
512
524
|
|
513
|
-
|
525
|
+
`Array#intersect?` ([#15198](https://bugs.ruby-lang.org/issues/15198))
|
514
526
|
|
515
527
|
### Supported proposed features
|
516
528
|
|
@@ -181,6 +181,7 @@ unless defined?(NoMatchingPatternError)
|
|
181
181
|
end
|
182
182
|
|
183
183
|
require "ruby-next/core/constants/no_matching_pattern_error"
|
184
|
+
require "ruby-next/core/constants/frozen_error"
|
184
185
|
require "ruby-next/core/array/deconstruct"
|
185
186
|
require "ruby-next/core/hash/deconstruct_keys"
|
186
187
|
require "ruby-next/core/struct/deconstruct"
|
@@ -188,6 +189,8 @@ require "ruby-next/core/struct/deconstruct_keys"
|
|
188
189
|
|
189
190
|
require "ruby-next/core/hash/except"
|
190
191
|
|
192
|
+
require "ruby-next/core/array/intersect"
|
193
|
+
|
191
194
|
# Generate refinements
|
192
195
|
RubyNext.module_eval do
|
193
196
|
RubyNext::Core.patches.refined.each do |mod, patches|
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
gem "ruby-next-parser", ">= 2.8.0.3"
|
4
|
+
gem "unparser", ">= 0.4.7"
|
5
|
+
|
6
|
+
require "set"
|
7
|
+
|
8
|
+
require "ruby-next"
|
9
|
+
|
10
|
+
module RubyNext
|
11
|
+
# Language module contains tools to transpile newer Ruby syntax
|
12
|
+
# into an older one.
|
13
|
+
#
|
14
|
+
# It works the following way:
|
15
|
+
# - Takes a Ruby source code as input
|
16
|
+
# - Generates the AST using the edge parser (via the `parser` gem)
|
17
|
+
# - Pass this AST through the list of processors (one feature = one processor)
|
18
|
+
# - Each processor may modify the AST
|
19
|
+
# - Generates a transpiled source code from the transformed AST (via the `unparser` gem)
|
20
|
+
module Language
|
21
|
+
using RubyNext
|
22
|
+
|
23
|
+
require "ruby-next/language/parser"
|
24
|
+
require "ruby-next/language/unparser"
|
25
|
+
|
26
|
+
RewriterNotFoundError = Class.new(StandardError)
|
27
|
+
|
28
|
+
class TransformContext
|
29
|
+
attr_reader :versions, :use_ruby_next
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
# Minimum supported RubyNext version
|
33
|
+
@min_version = MIN_SUPPORTED_VERSION
|
34
|
+
@dirty = false
|
35
|
+
@versions = Set.new
|
36
|
+
@use_ruby_next = false
|
37
|
+
end
|
38
|
+
|
39
|
+
# Called by rewriter when it performs transfomrations
|
40
|
+
def track!(rewriter)
|
41
|
+
@dirty = true
|
42
|
+
versions << rewriter.class::MIN_SUPPORTED_VERSION
|
43
|
+
end
|
44
|
+
|
45
|
+
def use_ruby_next!
|
46
|
+
@use_ruby_next = true
|
47
|
+
end
|
48
|
+
|
49
|
+
alias use_ruby_next? use_ruby_next
|
50
|
+
|
51
|
+
def dirty?
|
52
|
+
@dirty == true
|
53
|
+
end
|
54
|
+
|
55
|
+
def min_version
|
56
|
+
versions.min
|
57
|
+
end
|
58
|
+
|
59
|
+
def sorted_versions
|
60
|
+
versions.to_a.sort
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class << self
|
65
|
+
attr_accessor :rewriters
|
66
|
+
attr_reader :watch_dirs
|
67
|
+
|
68
|
+
attr_accessor :strategy
|
69
|
+
|
70
|
+
MODES = %i[rewrite ast].freeze
|
71
|
+
|
72
|
+
attr_reader :mode
|
73
|
+
|
74
|
+
def mode=(val)
|
75
|
+
raise ArgumentError, "Unknown mode: #{val}. Available: #{MODES.join(",")}" unless MODES.include?(val)
|
76
|
+
@mode = val
|
77
|
+
end
|
78
|
+
|
79
|
+
def rewrite?
|
80
|
+
mode == :rewrite?
|
81
|
+
end
|
82
|
+
|
83
|
+
def ast?
|
84
|
+
mode == :ast
|
85
|
+
end
|
86
|
+
|
87
|
+
def runtime!
|
88
|
+
require "ruby-next/language/rewriters/runtime"
|
89
|
+
|
90
|
+
@runtime = true
|
91
|
+
end
|
92
|
+
|
93
|
+
def runtime?
|
94
|
+
@runtime
|
95
|
+
end
|
96
|
+
|
97
|
+
def transform(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
|
98
|
+
retried = 0
|
99
|
+
new_source = nil
|
100
|
+
begin
|
101
|
+
new_source =
|
102
|
+
if mode == :rewrite
|
103
|
+
rewrite(source, rewriters: rewriters, using: using, context: context)
|
104
|
+
else
|
105
|
+
regenerate(source, rewriters: rewriters, using: using, context: context)
|
106
|
+
end
|
107
|
+
rescue Unparser::UnknownNodeError => err
|
108
|
+
RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since the version of Unparser you use doesn't support some syntax yet: #{err.message}.\n" \
|
109
|
+
"Try upgrading the Unparser or set transpiling mode to \"rewrite\" in case you use some edge or experimental syntax."
|
110
|
+
self.mode = :rewrite
|
111
|
+
retried += 1
|
112
|
+
retry unless retried > 1
|
113
|
+
raise
|
114
|
+
end
|
115
|
+
|
116
|
+
return new_source unless RubyNext::Core.refine?
|
117
|
+
return new_source unless using && context.use_ruby_next?
|
118
|
+
|
119
|
+
Core.inject! new_source.dup
|
120
|
+
end
|
121
|
+
|
122
|
+
def transformable?(path)
|
123
|
+
watch_dirs.any? { |dir| path.start_with?(dir) }
|
124
|
+
end
|
125
|
+
|
126
|
+
# Rewriters required for the current version
|
127
|
+
def current_rewriters
|
128
|
+
@current_rewriters ||= rewriters.select(&:unsupported_syntax?)
|
129
|
+
end
|
130
|
+
|
131
|
+
# This method guarantees that rewriters will be returned in order they defined in Language module
|
132
|
+
def select_rewriters(*names)
|
133
|
+
rewriters_delta = names - rewriters.map { |rewriter| rewriter::NAME }
|
134
|
+
if rewriters_delta.any?
|
135
|
+
raise RewriterNotFoundError, "Rewriters not found: #{rewriters_delta.join(",")}"
|
136
|
+
end
|
137
|
+
|
138
|
+
rewriters.select { |rewriter| names.include?(rewriter::NAME) }
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def regenerate(source, rewriters: ::Kernel.raise(::ArgumentError, "missing keyword: rewriters"), using: ::Kernel.raise(::ArgumentError, "missing keyword: using"), context: ::Kernel.raise(::ArgumentError, "missing keyword: context"))
|
144
|
+
parse_with_comments(source).then do |(ast, comments)|
|
145
|
+
rewriters.inject(ast) do |tree, rewriter|
|
146
|
+
rewriter.new(context).process(tree)
|
147
|
+
end.then do |new_ast|
|
148
|
+
next source unless context.dirty?
|
149
|
+
|
150
|
+
Unparser.unparse(new_ast, comments)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def rewrite(source, rewriters: ::Kernel.raise(::ArgumentError, "missing keyword: rewriters"), using: ::Kernel.raise(::ArgumentError, "missing keyword: using"), context: ::Kernel.raise(::ArgumentError, "missing keyword: context"))
|
156
|
+
rewriters.inject(source) do |src, rewriter|
|
157
|
+
buffer = Parser::Source::Buffer.new("<dynamic>")
|
158
|
+
buffer.source = src
|
159
|
+
|
160
|
+
rewriter.new(context).rewrite(buffer, parse(src))
|
161
|
+
end.then do |new_source|
|
162
|
+
next source unless context.dirty?
|
163
|
+
|
164
|
+
new_source
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
attr_writer :watch_dirs
|
169
|
+
end
|
170
|
+
|
171
|
+
self.rewriters = []
|
172
|
+
self.watch_dirs = %w[app lib spec test].map { |path| File.join(Dir.pwd, path) }
|
173
|
+
self.mode = ENV.fetch("RUBY_NEXT_TRANSPILE_MODE", "rewrite").to_sym
|
174
|
+
|
175
|
+
require "ruby-next/language/rewriters/base"
|
176
|
+
|
177
|
+
require "ruby-next/language/rewriters/squiggly_heredoc"
|
178
|
+
rewriters << Rewriters::SquigglyHeredoc
|
179
|
+
|
180
|
+
require "ruby-next/language/rewriters/safe_navigation"
|
181
|
+
rewriters << Rewriters::SafeNavigation
|
182
|
+
|
183
|
+
require "ruby-next/language/rewriters/numeric_literals"
|
184
|
+
rewriters << Rewriters::NumericLiterals
|
185
|
+
|
186
|
+
require "ruby-next/language/rewriters/required_kwargs"
|
187
|
+
rewriters << Rewriters::RequiredKwargs
|
188
|
+
|
189
|
+
require "ruby-next/language/rewriters/args_forward"
|
190
|
+
rewriters << Rewriters::ArgsForward
|
191
|
+
|
192
|
+
# Must be added after general args forward rewriter to become
|
193
|
+
# no-op in Ruby <2.7
|
194
|
+
require "ruby-next/language/rewriters/args_forward_leading"
|
195
|
+
rewriters << Rewriters::ArgsForwardLeading
|
196
|
+
|
197
|
+
require "ruby-next/language/rewriters/numbered_params"
|
198
|
+
rewriters << Rewriters::NumberedParams
|
199
|
+
|
200
|
+
require "ruby-next/language/rewriters/pattern_matching"
|
201
|
+
rewriters << Rewriters::PatternMatching
|
202
|
+
|
203
|
+
# Must be added after general pattern matching rewriter to become
|
204
|
+
# no-op in Ruby <2.7
|
205
|
+
require "ruby-next/language/rewriters/find_pattern"
|
206
|
+
rewriters << Rewriters::FindPattern
|
207
|
+
|
208
|
+
require "ruby-next/language/rewriters/in_pattern"
|
209
|
+
rewriters << Rewriters::InPattern
|
210
|
+
|
211
|
+
# Put endless range in the end, 'cause Parser fails to parse it in
|
212
|
+
# pattern matching
|
213
|
+
require "ruby-next/language/rewriters/endless_range"
|
214
|
+
rewriters << Rewriters::EndlessRange
|
215
|
+
|
216
|
+
require "ruby-next/language/rewriters/endless_method"
|
217
|
+
RubyNext::Language.rewriters << RubyNext::Language::Rewriters::EndlessMethod
|
218
|
+
|
219
|
+
if ENV["RUBY_NEXT_EDGE"] == "1"
|
220
|
+
require "ruby-next/language/edge"
|
221
|
+
end
|
222
|
+
|
223
|
+
if ENV["RUBY_NEXT_PROPOSED"] == "1"
|
224
|
+
require "ruby-next/language/proposed"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -181,6 +181,7 @@ unless defined?(NoMatchingPatternError)
|
|
181
181
|
end
|
182
182
|
|
183
183
|
require "ruby-next/core/constants/no_matching_pattern_error"
|
184
|
+
require "ruby-next/core/constants/frozen_error"
|
184
185
|
require "ruby-next/core/array/deconstruct"
|
185
186
|
require "ruby-next/core/hash/deconstruct_keys"
|
186
187
|
require "ruby-next/core/struct/deconstruct"
|
@@ -188,6 +189,8 @@ require "ruby-next/core/struct/deconstruct_keys"
|
|
188
189
|
|
189
190
|
require "ruby-next/core/hash/except"
|
190
191
|
|
192
|
+
require "ruby-next/core/array/intersect"
|
193
|
+
|
191
194
|
# Generate refinements
|
192
195
|
RubyNext.module_eval do
|
193
196
|
RubyNext::Core.patches.refined.each do |mod, patches|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RubyNext::Core.patch Object,
|
4
|
+
name: "FrozenError",
|
5
|
+
method: nil,
|
6
|
+
refineable: [],
|
7
|
+
version: "2.5",
|
8
|
+
# avoid defining the constant twice, 'causae it's already included in core
|
9
|
+
# we only use the contents in `ruby-next core_ext`.
|
10
|
+
supported: true,
|
11
|
+
location: [__FILE__, __LINE__ + 2] do
|
12
|
+
<<-RUBY
|
13
|
+
FrozenError ||= RuntimeError
|
14
|
+
RUBY
|
15
|
+
end
|
@@ -1,12 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
# Ruby 3.1 adds an ability to pass a hash as accumulator.
|
4
|
+
#
|
5
|
+
# NOTE: We have separate patches for MRI 3.0+ and others due to the unsupported refinements vs modules behaviour.
|
6
|
+
if Enumerable.method_defined?(:tally) && ([].method(:tally).arity == 0) && !(defined?(JRUBY_VERSION) || defined?(TruffleRuby))
|
7
|
+
RubyNext::Core.patch name: "TallyWithHash", supported: false, native: nil, method: :tally, version: "3.1", refineable: [Enumerable] do
|
8
|
+
<<-'RUBY'
|
9
|
+
def tally(*attrs)
|
10
|
+
return super() if attrs.size.zero?
|
11
|
+
|
12
|
+
raise ArgumentError, "wrong number of arguments (given #{attrs.size}, expected 0..1)" if attrs.size > 1
|
13
|
+
|
14
|
+
hash = attrs.size.zero? ? {} : attrs[0].to_hash
|
15
|
+
raise FrozenError, "can't modify frozen #{hash.class}: #{hash}" if hash.frozen?
|
16
|
+
|
17
|
+
each_with_object(hash) do |v, acc|
|
18
|
+
acc[v] = 0 unless acc.key?(v)
|
19
|
+
acc[v] += 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
RUBY
|
23
|
+
end
|
24
|
+
else
|
25
|
+
RubyNext::Core.patch Enumerable, method: :tally, version: "3.1", refineable: [Enumerable, Array] do
|
26
|
+
<<-'RUBY'
|
27
|
+
def tally(acc = {})
|
28
|
+
hash = acc.to_hash
|
29
|
+
raise FrozenError, "can't modify frozen #{hash.class}: #{hash}" if hash.frozen?
|
30
|
+
|
31
|
+
each_with_object(hash) do |v, acc|
|
32
|
+
acc[v] = 0 unless acc.key?(v)
|
33
|
+
acc[v] += 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
RUBY
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# This patch is intended for core extensions only (since we can not use prepend here)
|
41
|
+
RubyNext::Core.patch Enumerable, name: "TallyWithHashCoreExt", version: "3.1", supported: Enumerable.method_defined?(:tally) && ([].method(:tally).arity != 0), method: :tally, refineable: [] do
|
42
|
+
<<-'RUBY'
|
43
|
+
def tally(acc = {})
|
44
|
+
hash = acc.to_hash
|
45
|
+
raise FrozenError, "can't modify frozen #{hash.class}: #{hash}" if hash.frozen?
|
46
|
+
|
47
|
+
each_with_object(hash) do |v, acc|
|
48
|
+
acc[v] = 0 unless acc.key?(v)
|
10
49
|
acc[v] += 1
|
11
50
|
end
|
12
51
|
end
|
data/lib/ruby-next/core.rb
CHANGED
@@ -181,6 +181,7 @@ unless defined?(NoMatchingPatternError)
|
|
181
181
|
end
|
182
182
|
|
183
183
|
require "ruby-next/core/constants/no_matching_pattern_error"
|
184
|
+
require "ruby-next/core/constants/frozen_error"
|
184
185
|
require "ruby-next/core/array/deconstruct"
|
185
186
|
require "ruby-next/core/hash/deconstruct_keys"
|
186
187
|
require "ruby-next/core/struct/deconstruct"
|
@@ -188,6 +189,8 @@ require "ruby-next/core/struct/deconstruct_keys"
|
|
188
189
|
|
189
190
|
require "ruby-next/core/hash/except"
|
190
191
|
|
192
|
+
require "ruby-next/core/array/intersect"
|
193
|
+
|
191
194
|
# Generate refinements
|
192
195
|
RubyNext.module_eval do
|
193
196
|
RubyNext::Core.patches.refined.each do |mod, patches|
|
@@ -11,16 +11,20 @@ module RubyNext
|
|
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
|
]
|
@@ -50,7 +50,7 @@ module RubyNext
|
|
50
50
|
GemTranspiler.maybe_transpile(File.dirname(dirname), lib_dir, next_dirname) if transpile
|
51
51
|
|
52
52
|
current_index = $LOAD_PATH.find_index do |load_path|
|
53
|
-
Pathname.new(load_path).
|
53
|
+
Pathname.new(load_path).realpath.to_s == dirname
|
54
54
|
end
|
55
55
|
|
56
56
|
raise "Gem's lib is not in the $LOAD_PATH: #{dirname}" if current_index.nil?
|
data/lib/ruby-next/language.rb
CHANGED
@@ -94,53 +94,29 @@ module RubyNext
|
|
94
94
|
@runtime
|
95
95
|
end
|
96
96
|
|
97
|
-
def transform(
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
97
|
+
def transform(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
|
98
|
+
retried = 0
|
99
|
+
new_source = nil
|
100
|
+
begin
|
101
|
+
new_source =
|
102
|
+
if mode == :rewrite
|
103
|
+
rewrite(source, rewriters: rewriters, using: using, context: context)
|
104
|
+
else
|
105
|
+
regenerate(source, rewriters: rewriters, using: using, context: context)
|
106
|
+
end
|
107
|
+
rescue Unparser::UnknownNodeError => err
|
108
|
+
RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since the version of Unparser you use doesn't support some syntax yet: #{err.message}.\n" \
|
109
|
+
"Try upgrading the Unparser or set transpiling mode to \"rewrite\" in case you use some edge or experimental syntax."
|
107
110
|
self.mode = :rewrite
|
111
|
+
retried += 1
|
112
|
+
retry unless retried > 1
|
113
|
+
raise
|
108
114
|
end
|
109
|
-
rewrite(*args, **kwargs)
|
110
|
-
end
|
111
|
-
|
112
|
-
def regenerate(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
|
113
|
-
parse_with_comments(source).then do |(ast, comments)|
|
114
|
-
rewriters.inject(ast) do |tree, rewriter|
|
115
|
-
rewriter.new(context).process(tree)
|
116
|
-
end.then do |new_ast|
|
117
|
-
next source unless context.dirty?
|
118
115
|
|
119
|
-
|
120
|
-
|
121
|
-
next source unless RubyNext::Core.refine?
|
122
|
-
next source unless using && context.use_ruby_next?
|
116
|
+
return new_source unless RubyNext::Core.refine?
|
117
|
+
return new_source unless using && context.use_ruby_next?
|
123
118
|
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def rewrite(source, rewriters: self.rewriters, using: RubyNext::Core.refine?, context: TransformContext.new)
|
130
|
-
rewriters.inject(source) do |src, rewriter|
|
131
|
-
buffer = Parser::Source::Buffer.new("<dynamic>")
|
132
|
-
buffer.source = src
|
133
|
-
|
134
|
-
rewriter.new(context).rewrite(buffer, parse(src))
|
135
|
-
end.then do |new_source|
|
136
|
-
next source unless context.dirty?
|
137
|
-
new_source
|
138
|
-
end.then do |source|
|
139
|
-
next source unless RubyNext::Core.refine?
|
140
|
-
next source unless using && context.use_ruby_next?
|
141
|
-
|
142
|
-
Core.inject! source.dup
|
143
|
-
end
|
119
|
+
Core.inject! new_source.dup
|
144
120
|
end
|
145
121
|
|
146
122
|
def transformable?(path)
|
@@ -164,6 +140,31 @@ module RubyNext
|
|
164
140
|
|
165
141
|
private
|
166
142
|
|
143
|
+
def regenerate(source, rewriters:, using:, context:)
|
144
|
+
parse_with_comments(source).then do |(ast, comments)|
|
145
|
+
rewriters.inject(ast) do |tree, rewriter|
|
146
|
+
rewriter.new(context).process(tree)
|
147
|
+
end.then do |new_ast|
|
148
|
+
next source unless context.dirty?
|
149
|
+
|
150
|
+
Unparser.unparse(new_ast, comments)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def rewrite(source, rewriters:, using:, context:)
|
156
|
+
rewriters.inject(source) do |src, rewriter|
|
157
|
+
buffer = Parser::Source::Buffer.new("<dynamic>")
|
158
|
+
buffer.source = src
|
159
|
+
|
160
|
+
rewriter.new(context).rewrite(buffer, parse(src))
|
161
|
+
end.then do |new_source|
|
162
|
+
next source unless context.dirty?
|
163
|
+
|
164
|
+
new_source
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
167
168
|
attr_writer :watch_dirs
|
168
169
|
end
|
169
170
|
|
data/lib/ruby-next/setup_self.rb
CHANGED
@@ -6,7 +6,9 @@
|
|
6
6
|
version = RubyNext.next_ruby_version
|
7
7
|
next_dirname = File.join(__dir__, "..", ".rbnext")
|
8
8
|
lib_path = File.realpath(File.join(__dir__, ".."))
|
9
|
-
current_index = $LOAD_PATH.
|
9
|
+
current_index = $LOAD_PATH.find_index do |load_path|
|
10
|
+
File.exist?(load_path) && File.realpath(load_path) == lib_path
|
11
|
+
end
|
10
12
|
|
11
13
|
loop do
|
12
14
|
break unless version
|
data/lib/ruby-next/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-next-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Dementyev
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-next-parser
|
@@ -28,20 +28,14 @@ dependencies:
|
|
28
28
|
name: unparser
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 0.5.6
|
34
|
-
- - "<"
|
31
|
+
- - "~>"
|
35
32
|
- !ruby/object:Gem::Version
|
36
33
|
version: 0.6.0
|
37
34
|
type: :development
|
38
35
|
prerelease: false
|
39
36
|
version_requirements: !ruby/object:Gem::Requirement
|
40
37
|
requirements:
|
41
|
-
- - "
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: 0.5.6
|
44
|
-
- - "<"
|
38
|
+
- - "~>"
|
45
39
|
- !ruby/object:Gem::Version
|
46
40
|
version: 0.6.0
|
47
41
|
description: "\n Ruby Next Core is a zero deps version of Ruby Next meant to be
|
@@ -63,6 +57,7 @@ files:
|
|
63
57
|
- bin/ruby-next
|
64
58
|
- bin/transform
|
65
59
|
- lib/.rbnext/2.1/ruby-next/core.rb
|
60
|
+
- lib/.rbnext/2.1/ruby-next/language.rb
|
66
61
|
- lib/.rbnext/2.3/ruby-next/commands/core_ext.rb
|
67
62
|
- lib/.rbnext/2.3/ruby-next/commands/nextify.rb
|
68
63
|
- lib/.rbnext/2.3/ruby-next/language/eval.rb
|
@@ -80,6 +75,8 @@ files:
|
|
80
75
|
- lib/ruby-next/core.rb
|
81
76
|
- lib/ruby-next/core/array/deconstruct.rb
|
82
77
|
- lib/ruby-next/core/array/difference_union_intersection.rb
|
78
|
+
- lib/ruby-next/core/array/intersect.rb
|
79
|
+
- lib/ruby-next/core/constants/frozen_error.rb
|
83
80
|
- lib/ruby-next/core/constants/no_matching_pattern_error.rb
|
84
81
|
- lib/ruby-next/core/enumerable/filter.rb
|
85
82
|
- lib/ruby-next/core/enumerable/filter_map.rb
|
@@ -141,7 +138,7 @@ metadata:
|
|
141
138
|
documentation_uri: http://github.com/ruby-next/ruby-next/blob/master/README.md
|
142
139
|
homepage_uri: http://github.com/ruby-next/ruby-next
|
143
140
|
source_code_uri: http://github.com/ruby-next/ruby-next
|
144
|
-
post_install_message:
|
141
|
+
post_install_message:
|
145
142
|
rdoc_options: []
|
146
143
|
require_paths:
|
147
144
|
- lib
|
@@ -156,8 +153,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
153
|
- !ruby/object:Gem::Version
|
157
154
|
version: '0'
|
158
155
|
requirements: []
|
159
|
-
rubygems_version: 3.
|
160
|
-
signing_key:
|
156
|
+
rubygems_version: 3.2.15
|
157
|
+
signing_key:
|
161
158
|
specification_version: 4
|
162
159
|
summary: Ruby Next core functionality
|
163
160
|
test_files: []
|