ruby-next-core 0.12.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c248b303a7e6990efd5d93e042c4043a61a553fddf880f44d9a2f7f40e66eabb
4
- data.tar.gz: 23aa24ec51098f2a73196c2ddb3c4ae1fdeece1b5232cb5832012466080f29e9
3
+ metadata.gz: 1e73900618b0d9da915699c40c610736e19919ac0d11bce7c7dc58e7d5ddb84b
4
+ data.tar.gz: b07917f44a763467f4bed145ae1224ba8aeb03eaba7924b2787c681df4b704f8
5
5
  SHA512:
6
- metadata.gz: 1b97768e53ff0e8841fbb7d045358728dcb2208ba79cdb0636b495de3112810b3d8f8deb1cbbe34a5fe52ef79c09044d4871db05caed04b211dfbbca8e6c4238
7
- data.tar.gz: 700ad59a1f0e094bf162dc2d2e30af843b4f95b9bfc3d104c58ea2f7d8a46c57537792c507dd0189e2c93850c0cccc4b0e8bb57e10eef22041ee0dac5b4b537c
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
- <a href="https://evilmartians.com/?utm_source=ruby-next">
25
- <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
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
- No new features since 3.0 release.
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
@@ -353,7 +353,7 @@ module RubyNext
353
353
 
354
354
  else_clause = (else_clause || no_matching_pattern).then do |node|
355
355
  next node unless node.type == :empty_else
356
- s(:empty)
356
+ nil
357
357
  end
358
358
 
359
359
  clauses << else_clause
@@ -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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ RubyNext::Core.patch Array, method: :intersect?, version: "3.1" do
4
+ <<-RUBY
5
+ def intersect?(other)
6
+ !(self & other).empty?
7
+ end
8
+ RUBY
9
+ end
@@ -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
- # Refine Array seprately, 'cause refining modules is vulnerable to prepend:
4
- # - https://bugs.ruby-lang.org/issues/13446
5
- RubyNext::Core.patch Enumerable, method: :tally, version: "2.7", refineable: [Enumerable, Array] do
6
- <<-RUBY
7
- def tally
8
- each_with_object({}) do |v, acc|
9
- acc[v] ||= 0
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
@@ -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 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
  ]
@@ -23,7 +23,7 @@ module RubyNext
23
23
  super
24
24
  end
25
25
 
26
- def on_forward_arg(node)
26
+ def on_args(node)
27
27
  return super if leading_farg?
28
28
 
29
29
  node
@@ -353,7 +353,7 @@ module RubyNext
353
353
 
354
354
  else_clause = (else_clause || no_matching_pattern).then do |node|
355
355
  next node unless node.type == :empty_else
356
- s(:empty)
356
+ nil
357
357
  end
358
358
 
359
359
  clauses << else_clause
@@ -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).cleanpath.to_s == dirname
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?
@@ -94,53 +94,29 @@ module RubyNext
94
94
  @runtime
95
95
  end
96
96
 
97
- def transform(*args, **kwargs)
98
- if mode == :rewrite
99
- rewrite(*args, **kwargs)
100
- else
101
- regenerate(*args, **kwargs)
102
- end
103
- rescue Unparser::UnknownNodeError
104
- if Gem::Version.new(::RubyNext.current_ruby_version) >= Gem::Version.new("3.0.0")
105
- RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since Unparser doesn't support 3.0+ AST yet.\n" \
106
- "See https://github.com/mbj/unparser/issues/168"
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
- Unparser.unparse(new_ast, comments)
120
- end.then do |source|
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
- Core.inject! source.dup
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
 
@@ -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.index(lib_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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyNext
4
- VERSION = "0.12.0"
4
+ VERSION = "0.13.0"
5
5
  end
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.12.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-01-12 00:00:00.000000000 Z
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.0.6
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: []