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
@@ -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(RUBY_VERSION) >= Gem::Version.new("2.7.0")
105
- RubyNext.warn "Ruby Next fallbacks to \"rewrite\" transpiling mode since Unparser doesn't support 2.7+ AST yet.\n" \
106
- "See https://github.com/mbj/unparser/pull/142"
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
-
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?
123
-
124
- Core.inject! source.dup
125
- end
126
- end
127
- end
128
115
 
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
116
+ return new_source unless RubyNext::Core.refine?
117
+ return new_source unless using && context.use_ruby_next?
133
118
 
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,12 +140,37 @@ 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
 
170
171
  self.rewriters = []
171
172
  self.watch_dirs = %w[app lib spec test].map { |path| File.join(Dir.pwd, path) }
172
- self.mode = ENV.fetch("RUBY_NEXT_TRANSPILE_MODE", "ast").to_sym
173
+ self.mode = ENV.fetch("RUBY_NEXT_TRANSPILE_MODE", "rewrite").to_sym
173
174
 
174
175
  require "ruby-next/language/rewriters/base"
175
176
 
@@ -179,9 +180,20 @@ module RubyNext
179
180
  require "ruby-next/language/rewriters/safe_navigation"
180
181
  rewriters << Rewriters::SafeNavigation
181
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
+
182
189
  require "ruby-next/language/rewriters/args_forward"
183
190
  rewriters << Rewriters::ArgsForward
184
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
+
185
197
  require "ruby-next/language/rewriters/numbered_params"
186
198
  rewriters << Rewriters::NumberedParams
187
199
 
@@ -193,11 +205,17 @@ module RubyNext
193
205
  require "ruby-next/language/rewriters/find_pattern"
194
206
  rewriters << Rewriters::FindPattern
195
207
 
208
+ require "ruby-next/language/rewriters/in_pattern"
209
+ rewriters << Rewriters::InPattern
210
+
196
211
  # Put endless range in the end, 'cause Parser fails to parse it in
197
212
  # pattern matching
198
213
  require "ruby-next/language/rewriters/endless_range"
199
214
  rewriters << Rewriters::EndlessRange
200
215
 
216
+ require "ruby-next/language/rewriters/endless_method"
217
+ RubyNext::Language.rewriters << RubyNext::Language::Rewriters::EndlessMethod
218
+
201
219
  if ENV["RUBY_NEXT_EDGE"] == "1"
202
220
  require "ruby-next/language/edge"
203
221
  end
@@ -4,6 +4,7 @@
4
4
  # edge features and fix some bugs with 2.7+ syntax
5
5
 
6
6
  require "parser/ruby-next/version"
7
+ require "ruby-next/language/parser"
7
8
 
8
9
  module RuboCop
9
10
  # Transform Ruby Next parser version to a float, e.g.: "2.8.0.1" => 2.801
@@ -37,7 +38,6 @@ module RuboCop
37
38
  def parser_class(version)
38
39
  return super unless version == RUBY_NEXT_VERSION
39
40
 
40
- require "parser/rubynext"
41
41
  Parser::RubyNext
42
42
  end
43
43
  end
@@ -52,7 +52,7 @@ module RuboCop
52
52
  module AST
53
53
  module Traversal
54
54
  # Fixed in https://github.com/rubocop-hq/rubocop/pull/7786
55
- %i[case_match in_pattern find_pattern].each do |type|
55
+ %i[case_match in_pattern find_pattern match_pattern match_pattern_p].each do |type|
56
56
  next if method_defined?(:"on_#{type}")
57
57
  module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
58
58
  def on_#{type}(node)
@@ -62,6 +62,10 @@ end
62
62
  RUBY
63
63
  end
64
64
  end
65
+
66
+ unless Builder.method_defined?(:match_pattern_p)
67
+ Builder.include RubyNext::Language::BuilderExt
68
+ end
65
69
  end
66
70
  end
67
71
  # rubocop:enable Layout/HeredocIndentation
@@ -102,27 +106,14 @@ module RuboCop
102
106
  send(:"on_#{body_node.type}", body_node)
103
107
  end
104
108
  end
105
-
106
- unless method_defined?(:on_rasgn)
107
- def on_rasgn(node)
108
- val_node, asgn_node = *node
109
- send(:"on_#{asgn_node.type}", asgn_node)
110
- send(:"on_#{val_node.type}", val_node)
111
- end
112
-
113
- def on_mrasgn(node)
114
- lhs, rhs = *node
115
- send(:"on_#{lhs.type}", lhs)
116
- send(:"on_#{rhs.type}", rhs)
117
- end
118
- end
119
109
  end
120
110
 
121
111
  module Layout
122
112
  require "rubocop/cop/layout/assignment_indentation"
123
- AssignmentIndentation.prepend(Module.new do
124
- POTENTIAL_RIGHT_TYPES = %i[ivasgn lvasgn cvasgn gvasgn casgn masgn].freeze
125
113
 
114
+ POTENTIAL_RIGHT_TYPES = %i[ivasgn lvasgn cvasgn gvasgn casgn masgn].freeze
115
+
116
+ AssignmentIndentation.prepend(Module.new do
126
117
  def check_assignment(node, *)
127
118
  return if rightward?(node)
128
119
  super
@@ -3,10 +3,12 @@
3
3
  # This file setup LOAD_PATH to load Ruby Next own transpiled paths
4
4
  # (we cannot use language/setup here, 'cause it requires Core to be loaded)
5
5
 
6
- version = RubyNext.next_version
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
@@ -18,5 +20,5 @@ loop do
18
20
  current_index += 1
19
21
  end
20
22
 
21
- version = RubyNext.next_version(version)
23
+ version = RubyNext.next_ruby_version(version)
22
24
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyNext
4
- VERSION = "0.10.5"
4
+ VERSION = "0.13.0"
5
5
  end
data/lib/ruby-next.rb CHANGED
@@ -1,41 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "ruby-next/version"
4
-
5
- module RubyNext
6
- # Mininum Ruby version supported by RubyNext
7
- MIN_SUPPORTED_VERSION = Gem::Version.new("2.2.0")
8
-
9
- # Where to store transpiled files (relative from the project LOAD_PATH, usually `lib/`)
10
- RUBY_NEXT_DIR = ".rbnext"
11
-
12
- # Defines last minor version for every major version
13
- LAST_MINOR_VERSIONS = {
14
- 2 => 8, # 2.8 is required for backward compatibility: some gems already uses it
15
- 3 => 0
16
- }.freeze
17
-
18
- LATEST_VERSION = [3, 0].freeze
19
-
20
- class << self
21
- def next_version(version = RUBY_VERSION)
22
- major, minor = Gem::Version.new(version).segments.map(&:to_i)
23
-
24
- return if major >= LATEST_VERSION.first && minor >= LATEST_VERSION.last
25
-
26
- nxt =
27
- if LAST_MINOR_VERSIONS[major] == minor
28
- "#{major + 1}.0.0"
29
- else
30
- "#{major}.#{minor + 1}.0"
31
- end
32
-
33
- Gem::Version.new(nxt)
34
- end
35
- end
36
-
37
- require "ruby-next/setup_self"
38
- require "ruby-next/core"
39
- require "ruby-next/core_ext" if RubyNext::Core.core_ext?
40
- require "ruby-next/logging"
41
- end
4
+ require "ruby-next/config"
5
+ require "ruby-next/setup_self"
6
+ require "ruby-next/core"
7
+ require "ruby-next/core_ext" if RubyNext::Core.core_ext?
8
+ require "ruby-next/logging"
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.10.5
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: 2020-10-13 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
@@ -16,32 +16,26 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 3.0.0.1
19
+ version: 3.0.0.3
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 3.0.0.1
26
+ version: 3.0.0.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: unparser
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 0.4.8
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.4.8
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
@@ -62,22 +56,27 @@ files:
62
56
  - bin/reparse
63
57
  - bin/ruby-next
64
58
  - bin/transform
59
+ - lib/.rbnext/2.1/ruby-next/core.rb
60
+ - lib/.rbnext/2.1/ruby-next/language.rb
65
61
  - lib/.rbnext/2.3/ruby-next/commands/core_ext.rb
66
62
  - lib/.rbnext/2.3/ruby-next/commands/nextify.rb
67
63
  - lib/.rbnext/2.3/ruby-next/language/eval.rb
68
64
  - lib/.rbnext/2.3/ruby-next/language/rewriters/base.rb
69
65
  - lib/.rbnext/2.3/ruby-next/language/rewriters/endless_range.rb
70
66
  - lib/.rbnext/2.3/ruby-next/language/rewriters/pattern_matching.rb
71
- - lib/.rbnext/2.3/ruby-next/language/rewriters/right_hand_assignment.rb
72
67
  - lib/.rbnext/2.3/ruby-next/utils.rb
68
+ - lib/.rbnext/2.7/ruby-next/core.rb
73
69
  - lib/ruby-next.rb
74
70
  - lib/ruby-next/cli.rb
75
71
  - lib/ruby-next/commands/base.rb
76
72
  - lib/ruby-next/commands/core_ext.rb
77
73
  - lib/ruby-next/commands/nextify.rb
74
+ - lib/ruby-next/config.rb
78
75
  - lib/ruby-next/core.rb
79
76
  - lib/ruby-next/core/array/deconstruct.rb
80
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
81
80
  - lib/ruby-next/core/constants/no_matching_pattern_error.rb
82
81
  - lib/ruby-next/core/enumerable/filter.rb
83
82
  - lib/ruby-next/core/enumerable/filter_map.rb
@@ -105,14 +104,17 @@ files:
105
104
  - lib/ruby-next/language/parser.rb
106
105
  - lib/ruby-next/language/proposed.rb
107
106
  - lib/ruby-next/language/rewriters/args_forward.rb
107
+ - lib/ruby-next/language/rewriters/args_forward_leading.rb
108
108
  - lib/ruby-next/language/rewriters/base.rb
109
109
  - lib/ruby-next/language/rewriters/endless_method.rb
110
110
  - lib/ruby-next/language/rewriters/endless_range.rb
111
111
  - lib/ruby-next/language/rewriters/find_pattern.rb
112
+ - lib/ruby-next/language/rewriters/in_pattern.rb
112
113
  - lib/ruby-next/language/rewriters/method_reference.rb
113
114
  - lib/ruby-next/language/rewriters/numbered_params.rb
115
+ - lib/ruby-next/language/rewriters/numeric_literals.rb
114
116
  - lib/ruby-next/language/rewriters/pattern_matching.rb
115
- - lib/ruby-next/language/rewriters/right_hand_assignment.rb
117
+ - lib/ruby-next/language/rewriters/required_kwargs.rb
116
118
  - lib/ruby-next/language/rewriters/runtime.rb
117
119
  - lib/ruby-next/language/rewriters/runtime/dir.rb
118
120
  - lib/ruby-next/language/rewriters/safe_navigation.rb
@@ -136,7 +138,7 @@ metadata:
136
138
  documentation_uri: http://github.com/ruby-next/ruby-next/blob/master/README.md
137
139
  homepage_uri: http://github.com/ruby-next/ruby-next
138
140
  source_code_uri: http://github.com/ruby-next/ruby-next
139
- post_install_message:
141
+ post_install_message:
140
142
  rdoc_options: []
141
143
  require_paths:
142
144
  - lib
@@ -151,8 +153,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
153
  - !ruby/object:Gem::Version
152
154
  version: '0'
153
155
  requirements: []
154
- rubygems_version: 3.0.6
155
- signing_key:
156
+ rubygems_version: 3.2.15
157
+ signing_key:
156
158
  specification_version: 4
157
159
  summary: Ruby Next core functionality
158
160
  test_files: []
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyNext
4
- module Language
5
- module Rewriters
6
- class RightHandAssignment < Base
7
- NAME = "right-hand-assignment"
8
- SYNTAX_PROBE = "1 + 2 => a"
9
- MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
10
-
11
- def on_rasgn(node)
12
- context.track! self
13
-
14
- node = super(node)
15
-
16
- val_node, asgn_node = *node
17
-
18
- remove(val_node.loc.expression.end.join(asgn_node.loc.expression))
19
- insert_before(val_node.loc.expression, "#{asgn_node.loc.expression.source} = ")
20
-
21
- asgn_node.updated(
22
- nil,
23
- asgn_node.children + [val_node]
24
- )
25
- end
26
-
27
- def on_vasgn(node)
28
- return super(node) unless rightward?(node)
29
-
30
- context.track! self
31
-
32
- name, val_node = *node
33
-
34
- remove(val_node.loc.expression.end.join(node.loc.name))
35
- insert_before(val_node.loc.expression, "#{name} = ")
36
-
37
- super(node)
38
- end
39
-
40
- def on_casgn(node)
41
- return super(node) unless rightward?(node)
42
-
43
- context.track! self
44
-
45
- scope_node, name, val_node = *node
46
-
47
- if scope_node
48
- scope = scope_node.type == :cbase ? scope_node.loc.expression.source : "#{scope_node.loc.expression.source}::"
49
- name = "#{scope}#{name}"
50
- end
51
-
52
- remove(val_node.loc.expression.end.join(node.loc.name))
53
- insert_before(val_node.loc.expression, "#{name} = ")
54
-
55
- super(node)
56
- end
57
-
58
- def on_mrasgn(node)
59
- context.track! self
60
-
61
- node = super(node)
62
-
63
- lhs, rhs = *node
64
-
65
- replace(lhs.loc.expression.end.join(rhs.loc.expression), ")")
66
- insert_before(lhs.loc.expression, "#{rhs.loc.expression.source} = (")
67
-
68
- node.updated(
69
- :masgn,
70
- [rhs, lhs]
71
- )
72
- end
73
-
74
- def on_masgn(node)
75
- return super(node) unless rightward?(node)
76
-
77
- context.track! self
78
-
79
- rhs, lhs = *node
80
-
81
- replace(lhs.loc.expression.end.join(rhs.loc.expression), ")")
82
- insert_before(lhs.loc.expression, "#{rhs.loc.expression.source} = (")
83
-
84
- node = super(node)
85
-
86
- lhs, rhs = *node
87
-
88
- node.updated(
89
- nil,
90
- [
91
- lhs,
92
- s(:begin, rhs)
93
- ]
94
- )
95
- end
96
-
97
- private
98
-
99
- def rightward?(node)
100
- # Location could be empty for node built by rewriters
101
- return false unless ((!node.loc.nil? || nil) && node.loc.operator)
102
-
103
- assignee_loc =
104
- if node.type == :masgn
105
- node.children[0].loc.expression
106
- else
107
- node.loc.name
108
- end
109
-
110
- return false unless assignee_loc
111
-
112
- assignee_loc.begin_pos > node.loc.operator.end_pos
113
- end
114
- end
115
- end
116
- end
117
- end
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyNext
4
- module Language
5
- module Rewriters
6
- class RightHandAssignment < Base
7
- NAME = "right-hand-assignment"
8
- SYNTAX_PROBE = "1 + 2 => a"
9
- MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")
10
-
11
- def on_rasgn(node)
12
- context.track! self
13
-
14
- node = super(node)
15
-
16
- val_node, asgn_node = *node
17
-
18
- remove(val_node.loc.expression.end.join(asgn_node.loc.expression))
19
- insert_before(val_node.loc.expression, "#{asgn_node.loc.expression.source} = ")
20
-
21
- asgn_node.updated(
22
- nil,
23
- asgn_node.children + [val_node]
24
- )
25
- end
26
-
27
- def on_vasgn(node)
28
- return super(node) unless rightward?(node)
29
-
30
- context.track! self
31
-
32
- name, val_node = *node
33
-
34
- remove(val_node.loc.expression.end.join(node.loc.name))
35
- insert_before(val_node.loc.expression, "#{name} = ")
36
-
37
- super(node)
38
- end
39
-
40
- def on_casgn(node)
41
- return super(node) unless rightward?(node)
42
-
43
- context.track! self
44
-
45
- scope_node, name, val_node = *node
46
-
47
- if scope_node
48
- scope = scope_node.type == :cbase ? scope_node.loc.expression.source : "#{scope_node.loc.expression.source}::"
49
- name = "#{scope}#{name}"
50
- end
51
-
52
- remove(val_node.loc.expression.end.join(node.loc.name))
53
- insert_before(val_node.loc.expression, "#{name} = ")
54
-
55
- super(node)
56
- end
57
-
58
- def on_mrasgn(node)
59
- context.track! self
60
-
61
- node = super(node)
62
-
63
- lhs, rhs = *node
64
-
65
- replace(lhs.loc.expression.end.join(rhs.loc.expression), ")")
66
- insert_before(lhs.loc.expression, "#{rhs.loc.expression.source} = (")
67
-
68
- node.updated(
69
- :masgn,
70
- [rhs, lhs]
71
- )
72
- end
73
-
74
- def on_masgn(node)
75
- return super(node) unless rightward?(node)
76
-
77
- context.track! self
78
-
79
- rhs, lhs = *node
80
-
81
- replace(lhs.loc.expression.end.join(rhs.loc.expression), ")")
82
- insert_before(lhs.loc.expression, "#{rhs.loc.expression.source} = (")
83
-
84
- node = super(node)
85
-
86
- lhs, rhs = *node
87
-
88
- node.updated(
89
- nil,
90
- [
91
- lhs,
92
- s(:begin, rhs)
93
- ]
94
- )
95
- end
96
-
97
- private
98
-
99
- def rightward?(node)
100
- # Location could be empty for node built by rewriters
101
- return false unless node.loc&.operator
102
-
103
- assignee_loc =
104
- if node.type == :masgn
105
- node.children[0].loc.expression
106
- else
107
- node.loc.name
108
- end
109
-
110
- return false unless assignee_loc
111
-
112
- assignee_loc.begin_pos > node.loc.operator.end_pos
113
- end
114
- end
115
- end
116
- end
117
- end