synvert-core 0.63.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -1
  3. data/.gitignore +4 -0
  4. data/CHANGELOG.md +9 -1
  5. data/Guardfile +11 -2
  6. data/README.md +74 -34
  7. data/Rakefile +15 -1
  8. data/lib/synvert/core/array_ext.rb +41 -0
  9. data/lib/synvert/core/configuration.rb +12 -0
  10. data/lib/synvert/core/engine/erb.rb +9 -8
  11. data/lib/synvert/core/exceptions.rb +0 -4
  12. data/lib/synvert/core/node_ext.rb +232 -128
  13. data/lib/synvert/core/node_query/compiler/array.rb +34 -0
  14. data/lib/synvert/core/node_query/compiler/attribute.rb +51 -0
  15. data/lib/synvert/core/node_query/compiler/attribute_list.rb +24 -0
  16. data/lib/synvert/core/node_query/compiler/boolean.rb +23 -0
  17. data/lib/synvert/core/node_query/compiler/comparable.rb +79 -0
  18. data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +51 -0
  19. data/lib/synvert/core/node_query/compiler/expression.rb +88 -0
  20. data/lib/synvert/core/node_query/compiler/float.rb +23 -0
  21. data/lib/synvert/core/node_query/compiler/identifier.rb +41 -0
  22. data/lib/synvert/core/node_query/compiler/integer.rb +23 -0
  23. data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +7 -0
  24. data/lib/synvert/core/node_query/compiler/nil.rb +23 -0
  25. data/lib/synvert/core/node_query/compiler/parse_error.rb +7 -0
  26. data/lib/synvert/core/node_query/compiler/regexp.rb +37 -0
  27. data/lib/synvert/core/node_query/compiler/selector.rb +51 -0
  28. data/lib/synvert/core/node_query/compiler/string.rb +34 -0
  29. data/lib/synvert/core/node_query/compiler/symbol.rb +23 -0
  30. data/lib/synvert/core/node_query/compiler.rb +24 -0
  31. data/lib/synvert/core/node_query/lexer.rex +96 -0
  32. data/lib/synvert/core/node_query/lexer.rex.rb +293 -0
  33. data/lib/synvert/core/node_query/parser.racc.rb +518 -0
  34. data/lib/synvert/core/node_query/parser.y +84 -0
  35. data/lib/synvert/core/node_query.rb +36 -0
  36. data/lib/synvert/core/rewriter/action/append_action.rb +4 -3
  37. data/lib/synvert/core/rewriter/action/delete_action.rb +17 -8
  38. data/lib/synvert/core/rewriter/action/insert_action.rb +16 -7
  39. data/lib/synvert/core/rewriter/action/insert_after_action.rb +3 -2
  40. data/lib/synvert/core/rewriter/action/prepend_action.rb +3 -2
  41. data/lib/synvert/core/rewriter/action/remove_action.rb +16 -10
  42. data/lib/synvert/core/rewriter/action/replace_action.rb +15 -5
  43. data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +18 -11
  44. data/lib/synvert/core/rewriter/action/replace_with_action.rb +6 -5
  45. data/lib/synvert/core/rewriter/action/wrap_action.rb +16 -7
  46. data/lib/synvert/core/rewriter/action.rb +22 -10
  47. data/lib/synvert/core/rewriter/any_value.rb +1 -0
  48. data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +4 -0
  49. data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +4 -0
  50. data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +4 -0
  51. data/lib/synvert/core/rewriter/condition.rb +11 -3
  52. data/lib/synvert/core/rewriter/gem_spec.rb +6 -3
  53. data/lib/synvert/core/rewriter/helper.rb +7 -4
  54. data/lib/synvert/core/rewriter/instance.rb +217 -104
  55. data/lib/synvert/core/rewriter/ruby_version.rb +4 -4
  56. data/lib/synvert/core/rewriter/scope/goto_scope.rb +5 -6
  57. data/lib/synvert/core/rewriter/scope/query_scope.rb +36 -0
  58. data/lib/synvert/core/rewriter/scope/within_scope.rb +10 -5
  59. data/lib/synvert/core/rewriter/scope.rb +8 -0
  60. data/lib/synvert/core/rewriter/warning.rb +1 -1
  61. data/lib/synvert/core/rewriter.rb +91 -43
  62. data/lib/synvert/core/version.rb +1 -1
  63. data/lib/synvert/core.rb +22 -6
  64. data/spec/synvert/core/engine/erb_spec.rb +2 -2
  65. data/spec/synvert/core/node_ext_spec.rb +36 -12
  66. data/spec/synvert/core/node_query/lexer_spec.rb +525 -0
  67. data/spec/synvert/core/node_query/parser_spec.rb +270 -0
  68. data/spec/synvert/core/rewriter/action_spec.rb +0 -4
  69. data/spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb +1 -6
  70. data/spec/synvert/core/rewriter/gem_spec_spec.rb +1 -1
  71. data/spec/synvert/core/rewriter/helper_spec.rb +4 -1
  72. data/spec/synvert/core/rewriter/instance_spec.rb +31 -20
  73. data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +74 -0
  74. data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +12 -9
  75. data/spec/synvert/core/rewriter_spec.rb +4 -2
  76. data/synvert-core-ruby.gemspec +7 -2
  77. metadata +91 -4
@@ -5,18 +5,8 @@ require 'fileutils'
5
5
  module Synvert::Core
6
6
  # Rewriter is the top level namespace in a snippet.
7
7
  #
8
- # One Rewriter can contain one or many [Synvert::Core::Rewriter::Instance],
8
+ # One Rewriter checks if the depndency version matches, and it can contain one or many {Synvert::Core::Rewriter::Instance},
9
9
  # which define the behavior what files and what codes to detect and rewrite to what code.
10
- #
11
- # Synvert::Rewriter.new 'factory_girl_short_syntax', 'use FactoryGirl short syntax' do
12
- # if_gem 'factory_girl', '>= 2.0.0'
13
- #
14
- # within_files 'spec/**/*.rb' do
15
- # with_node type: 'send', receiver: 'FactoryGirl', message: 'create' do
16
- # replace_with "create({{arguments}})"
17
- # end
18
- # end
19
- # end
20
10
  class Rewriter
21
11
  autoload :Action, 'synvert/core/rewriter/action'
22
12
  autoload :AppendAction, 'synvert/core/rewriter/action/append_action'
@@ -35,6 +25,7 @@ module Synvert::Core
35
25
  autoload :Instance, 'synvert/core/rewriter/instance'
36
26
 
37
27
  autoload :Scope, 'synvert/core/rewriter/scope'
28
+ autoload :QueryScope, 'synvert/core/rewriter/scope/query_scope'
38
29
  autoload :WithinScope, 'synvert/core/rewriter/scope/within_scope'
39
30
  autoload :GotoScope, 'synvert/core/rewriter/scope/goto_scope'
40
31
 
@@ -53,7 +44,7 @@ module Synvert::Core
53
44
  class << self
54
45
  # Execute the temporary rewriter without group and name.
55
46
  #
56
- # @param block [Block] a block defines the behaviors of the rewriter.
47
+ # @yield defines the behaviors of the rewriter.
57
48
  def execute(&block)
58
49
  rewriter = Rewriter.new('', '', &block)
59
50
  rewriter.process
@@ -91,7 +82,7 @@ module Synvert::Core
91
82
  #
92
83
  # @param group [String] the rewriter group.
93
84
  # @param name [String] the rewriter name.
94
- # @param sandbox [Boolean] if run in sandbox mode, default is false.
85
+ # @param sandbox [Boolean] if run in sandbox mode.
95
86
  # @return [Synvert::Core::Rewriter] the registered rewriter.
96
87
  # @raise [Synvert::Core::RewriterNotFound] if the registered rewriter is not found.
97
88
  def call(group, name, sandbox = false)
@@ -141,13 +132,12 @@ module Synvert::Core
141
132
  # @return [Rewriter::GemSpec] the gem spec
142
133
  attr_reader :group, :name, :sub_snippets, :helpers, :warnings, :affected_files, :ruby_version, :gem_spec
143
134
 
144
- # Initialize a rewriter.
145
- # When a rewriter is initialized, it is also registered.
135
+ # Initialize a Rewriter.
136
+ # When a rewriter is initialized, it is already registered.
146
137
  #
147
138
  # @param group [String] group of the rewriter.
148
139
  # @param name [String] name of the rewriter.
149
- # @param block [Block] a block defines the behaviors of the rewriter, block code won't be called when initialization.
150
- # @return [Synvert::Core::Rewriter]
140
+ # @yield defines the behaviors of the rewriter, block code won't be called when initialization.
151
141
  def initialize(group, name, &block)
152
142
  @group = group
153
143
  @name = name
@@ -198,9 +188,12 @@ module Synvert::Core
198
188
  # DSL #
199
189
  #######
200
190
 
201
- # Parse description dsl, it sets description of the rewrite.
191
+ # Parse +description+ dsl, it sets description of the rewrite.
202
192
  # Or get description.
203
- #
193
+ # @example
194
+ # Synvert::Rewriter.new 'rspec', 'use_new_syntax' do
195
+ # description 'It converts rspec code to new syntax, it calls all rspec sub snippets.'
196
+ # end
204
197
  # @param description [String] rewriter description.
205
198
  # @return rewriter description.
206
199
  def description(description = nil)
@@ -211,24 +204,34 @@ module Synvert::Core
211
204
  end
212
205
  end
213
206
 
214
- # Parse if_ruby dsl, it checks if ruby version if greater than or equal to the specified ruby version.
215
- #
216
- # @param version, [String] specified ruby version.
207
+ # Parse +if_ruby+ dsl, it checks if ruby version is greater than or equal to the specified ruby version.
208
+ # @example
209
+ # Synvert::Rewriter.new 'ruby', 'new_safe_navigation_operator' do
210
+ # if_ruby '2.3.0'
211
+ # end
212
+ # @param version [String] specified ruby version.
217
213
  def if_ruby(version)
218
214
  @ruby_version = Rewriter::RubyVersion.new(version)
219
215
  end
220
216
 
221
- # Parse if_gem dsl, it compares version of the specified gem.
222
- #
217
+ # Parse +if_gem+ dsl, it compares version of the specified gem.
218
+ # @example
219
+ # Synvert::Rewriter.new 'rails', 'upgrade_5_2_to_6_0' do
220
+ # if_gem 'rails', '>= 6.0'
221
+ # end
223
222
  # @param name [String] gem name.
224
223
  # @param version [String] equal, less than or greater than specified version, e.g. '>= 2.0.0',
225
224
  def if_gem(name, version)
226
225
  @gem_spec = Rewriter::GemSpec.new(name, version)
227
226
  end
228
227
 
229
- # Parse within_files dsl, it finds specified files.
230
- # It creates a [Synvert::Core::Rewriter::Instance] to rewrite code.
231
- #
228
+ # Parse +within_files+ dsl, it finds specified files.
229
+ # It creates a {Synvert::Core::Rewriter::Instance} to rewrite code.
230
+ # @example
231
+ # Synvert::Rewriter.new 'rspec', 'be_close_to_be_within' do
232
+ # within_files '**/*.rb' do
233
+ # end
234
+ # end
232
235
  # @param file_patterns [String|Array<String>] string pattern or list of string pattern to find files, e.g. ['spec/**/*_spec.rb']
233
236
  # @param block [Block] the block to rewrite code in the matching files.
234
237
  def within_files(file_patterns, &block)
@@ -240,11 +243,18 @@ module Synvert::Core
240
243
  Rewriter::Instance.new(self, Array(file_patterns), &block).process
241
244
  end
242
245
 
243
- # Parse within_file dsl, it finds a specifiled file.
246
+ # Parse +within_file+ dsl, it finds a specifiled file.
244
247
  alias within_file within_files
245
248
 
246
- # Parses add_file dsl, it adds a new file.
247
- #
249
+ # Parses +add_file+ dsl, it adds a new file.
250
+ # @example
251
+ # Synvert::Rewriter.new 'rails', 'add_application_record' do
252
+ # add_file 'app/models/application_record.rb', <<~EOS
253
+ # class ApplicationRecord < ActiveRecord::Base
254
+ # self.abstract_class = true
255
+ # end
256
+ # EOS
257
+ # end
248
258
  # @param filename [String] file name of newly created file.
249
259
  # @param content [String] file body of newly created file.
250
260
  def add_file(filename, content)
@@ -257,13 +267,14 @@ module Synvert::Core
257
267
  end
258
268
 
259
269
  FileUtils.mkdir_p File.dirname(filepath)
260
- File.open filepath, 'w' do |file|
261
- file.write content
262
- end
270
+ File.write(filepath, content)
263
271
  end
264
272
 
265
- # Parses remove_file dsl, it removes a file.
266
- #
273
+ # Parses +remove_file+ dsl, it removes a file.
274
+ # @example
275
+ # Synvert::Rewriter.new 'rails', 'upgrade_4_0_to_4_1' do
276
+ # remove_file 'config/initializers/secret_token.rb'
277
+ # end
267
278
  # @param filename [String] file name.
268
279
  def remove_file(filename)
269
280
  return if @sandbox
@@ -272,26 +283,59 @@ module Synvert::Core
272
283
  File.delete(file_path) if File.exist?(file_path)
273
284
  end
274
285
 
275
- # Parse add_snippet dsl, it calls anther rewriter.
276
- #
286
+ # Parse +add_snippet+ dsl, it calls anther rewriter.
287
+ # @example
288
+ # Synvert::Rewriter.new 'minitest', 'better_syntax' do
289
+ # add_snippet 'minitest', 'assert_empty'
290
+ # add_snippet 'minitest', 'assert_equal_arguments_order'
291
+ # add_snippet 'minitest', 'assert_includes'
292
+ # add_snippet 'minitest', 'assert_instance_of'
293
+ # add_snippet 'minitest', 'assert_kind_of'
294
+ # add_snippet 'minitest', 'assert_match'
295
+ # add_snippet 'minitest', 'assert_nil'
296
+ # add_snippet 'minitest', 'assert_operator'
297
+ # add_snippet 'minitest', 'assert_path_exists'
298
+ # add_snippet 'minitest', 'assert_predicate'
299
+ # add_snippet 'minitest', 'assert_respond_to'
300
+ # add_snippet 'minitest', 'assert_silent'
301
+ # add_snippet 'minitest', 'assert_truthy'
302
+ # end
277
303
  # @param group [String] group of another rewriter.
278
304
  # @param name [String] name of another rewriter.
279
305
  def add_snippet(group, name)
280
306
  @sub_snippets << self.class.call(group.to_s, name.to_s, @sandbox)
281
307
  end
282
308
 
283
- # Parse helper_method dsl, it defines helper method for [Synvert::Core::Rewriter::Instance].
284
- #
309
+ # Parse +helper_method+ dsl, it defines helper method for {Synvert::Core::Rewriter::Instance}.
310
+ # @example
311
+ # Synvert::Rewriter.new 'rails', 'convert_active_record_dirty_5_0_to_5_1' do
312
+ # helper_method :find_callbacks_and_convert do |callback_names, callback_changes|
313
+ # # do anything, method find_callbacks_and_convert can be reused later.
314
+ # end
315
+ # within_files Synvert::RAILS_MODEL_FILES + Synvert::RAILS_OBSERVER_FILES do
316
+ # find_callbacks_and_convert(before_callback_names, before_callback_changes)
317
+ # find_callbacks_and_convert(after_callback_names, after_callback_changes)
318
+ # end
319
+ # end
285
320
  # @param name [String] helper method name.
286
- # @param block [Block] helper method block.
321
+ # @yield helper method block.
287
322
  def helper_method(name, &block)
288
323
  @helpers << { name: name, block: block }
289
324
  end
290
325
 
291
- # Parse todo dsl, it sets todo of the rewriter.
326
+ # Parse +todo+ dsl, it sets todo of the rewriter.
292
327
  # Or get todo.
293
- #
294
- # @param todo_list [String] rewriter todo.
328
+ # @example
329
+ # Synvert::Rewriter.new 'rails', 'upgrade_3_2_to_4_0' do
330
+ # todo <<~EOS
331
+ # 1. Rails 4.0 no longer supports loading plugins from vendor/plugins. You must replace any plugins by extracting them to gems and adding them to your Gemfile. If you choose not to make them gems, you can move them into, say, lib/my_plugin/* and add an appropriate initializer in config/initializers/my_plugin.rb.
332
+ # 2. Make the following changes to your Gemfile.
333
+ # gem 'sass-rails', '~> 4.0.0'
334
+ # gem 'coffee-rails', '~> 4.0.0'
335
+ # gem 'uglifier', '>= 1.3.0'
336
+ # EOS
337
+ # end
338
+ # @param todo [String] rewriter todo.
295
339
  # @return [String] rewriter todo.
296
340
  def todo(todo = nil)
297
341
  if todo
@@ -302,6 +346,10 @@ module Synvert::Core
302
346
  end
303
347
 
304
348
  # Rerun the snippet until no change.
349
+ # @example
350
+ # Synvert::Rewriter.new 'ruby', 'nested_class_definition' do
351
+ # redo_until_no_change
352
+ # end
305
353
  def redo_until_no_change
306
354
  @redo_until_no_change = true
307
355
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '0.63.1'
5
+ VERSION = '1.0.2'
6
6
  end
7
7
  end
data/lib/synvert/core.rb CHANGED
@@ -10,6 +10,7 @@ require 'active_support/core_ext/object'
10
10
  require 'active_support/core_ext/array'
11
11
  require 'erubis'
12
12
  require 'set'
13
+ require 'synvert/core/array_ext'
13
14
  require 'synvert/core/node_ext'
14
15
 
15
16
  module Synvert
@@ -18,8 +19,8 @@ module Synvert
18
19
  autoload :Rewriter, 'synvert/core/rewriter'
19
20
  autoload :Engine, 'synvert/core/engine'
20
21
  autoload :RewriterNotFound, 'synvert/core/exceptions'
21
- autoload :GemfileLockNotFound, 'synvert/core/exceptions'
22
22
  autoload :MethodNotSupported, 'synvert/core/exceptions'
23
+ autoload :NodeQuery, 'synvert/core/node_query'
23
24
  end
24
25
  end
25
26
 
@@ -38,17 +39,32 @@ module Synvert
38
39
  RAILS_MAILER_FILES = %w[app/mailers/**/*.rb engines/*/app/mailers/**/*.rb]
39
40
  RAILS_MIGRATION_FILES = %w[db/migrate/**/*.rb engines/*/db/migrate/**/*.rb]
40
41
  RAILS_MODEL_FILES = %w[app/models/**/*.rb engines/*/app/models/**/*.rb]
41
- RAILS_ROUTE_FILES = %w[config/routes.rb config/routes/**/*.rb engines/*/config/routes.rb engines/*/config/routes/**/*.rb]
42
+ RAILS_ROUTE_FILES = %w[
43
+ config/routes.rb
44
+ config/routes/**/*.rb
45
+ engines/*/config/routes.rb
46
+ engines/*/config/routes/**/*.rb
47
+ ]
42
48
  RAILS_VIEW_FILES = %w[app/views/**/*.html.{erb,haml,slim}]
43
49
 
44
50
  RAILS_CONTROLLER_TEST_FILES = %w[
45
- test/functional/**/*.rb test/controllers/**/*.rb engines/*/test/functional/**/*.rb engines/*/test/controllers/**/*.rb
46
- spec/functional/**/*.rb spec/controllers/**/*.rb engines/*/spec/functional/**/*.rb engines/*/spec/controllers/**/*.rb
51
+ test/functional/**/*.rb
52
+ test/controllers/**/*.rb
53
+ engines/*/test/functional/**/*.rb
54
+ engines/*/test/controllers/**/*.rb
55
+ spec/functional/**/*.rb
56
+ spec/controllers/**/*.rb
57
+ engines/*/spec/functional/**/*.rb
58
+ engines/*/spec/controllers/**/*.rb
47
59
  ]
48
60
  RAILS_INTEGRATION_TEST_FILES = %w[test/integration/**/*.rb spec/integration/**/*.rb]
49
61
  RAILS_MODEL_TEST_FILES = %w[
50
- test/unit/**/*.rb engines/*/test/unit/**/*.rb test/models/**/*.rb engines/*/test/models/**/*.rb
51
- spec/models/**/*.rb engines/*/spec/models/**/*.rb
62
+ test/unit/**/*.rb
63
+ engines/*/test/unit/**/*.rb
64
+ test/models/**/*.rb
65
+ engines/*/test/models/**/*.rb
66
+ spec/models/**/*.rb
67
+ engines/*/spec/models/**/*.rb
52
68
  ]
53
69
 
54
70
  RAILS_FACTORY_FILES = %w[test/factories/**/*.rb spec/factories/**/*.rb]
@@ -13,13 +13,13 @@ module Synvert::Core
13
13
  }
14
14
  </style>
15
15
  <%end%>
16
-
16
+
17
17
  <%
18
18
  foo = 'bar'
19
19
  post = Post.find(:first)
20
20
  bar = 'foo'
21
21
  %>
22
-
22
+
23
23
  <% if User.current &&
24
24
  User.current.admin %>
25
25
  <%= rounded_content("page") do %>
@@ -3,6 +3,25 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Parser::AST::Node do
6
+ describe '#parent' do
7
+ it 'gets parent node' do
8
+ node = parse('FactoryBot.create(:user)')
9
+ child_node = node.children.first
10
+ expect(child_node.parent).to eq node
11
+ end
12
+ end
13
+
14
+ describe '#siblings' do
15
+ it 'gets sibling nodes' do
16
+ node = parse(<<~EOS)
17
+ def foobar; end
18
+ def foo; end
19
+ def bar; end
20
+ EOS
21
+ expect(node.children.first.siblings).to eq [node.children.second, node.children.last]
22
+ end
23
+ end
24
+
6
25
  describe '#name' do
7
26
  it 'gets for class node' do
8
27
  node = parse('class Synvert; end')
@@ -129,17 +148,17 @@ describe Parser::AST::Node do
129
148
  describe '#arguments' do
130
149
  it 'gets for def node' do
131
150
  node = parse('def test(foo, bar); foo + bar; end')
132
- expect(node.arguments.type).to eq :args
151
+ expect(node.arguments.map(&:type)).to eq [:arg, :arg]
133
152
  end
134
153
 
135
154
  it 'gets for defs node' do
136
155
  node = parse('def self.test(foo, bar); foo + bar; end')
137
- expect(node.arguments.type).to eq :args
156
+ expect(node.arguments.map(&:type)).to eq [:arg, :arg]
138
157
  end
139
158
 
140
159
  it 'gets for block node' do
141
160
  node = parse('RSpec.configure do |config|; end')
142
- expect(node.arguments.type).to eq :args
161
+ expect(node.arguments.map(&:type)).to eq [:arg]
143
162
  end
144
163
 
145
164
  it 'gets for send node' do
@@ -388,6 +407,11 @@ describe Parser::AST::Node do
388
407
  expect(node.to_value).to be_falsey
389
408
  end
390
409
 
410
+ it 'gets for nil' do
411
+ node = parse('nil')
412
+ expect(node.to_value).to be_nil
413
+ end
414
+
391
415
  it 'gets for irange' do
392
416
  node = parse('(1..10)')
393
417
  expect(node.to_value).to eq(1..10)
@@ -404,13 +428,6 @@ describe Parser::AST::Node do
404
428
  end
405
429
  end
406
430
 
407
- describe '#to_s' do
408
- it 'gets for mlhs node' do
409
- node = parse('var.each { |(param1, param2)| }')
410
- expect(node.arguments.first.to_s).to eq '(param1, param2)'
411
- end
412
- end
413
-
414
431
  describe '#filename' do
415
432
  it 'gets file name' do
416
433
  source = 'foobar'
@@ -541,7 +558,14 @@ describe Parser::AST::Node do
541
558
  it 'matches arguments with nested hash' do
542
559
  source = '{ user_id: user.id }'
543
560
  node = parse(source)
544
- expect(node).to be_match(type: 'hash', user_id_value: { type: 'send', receiver: { type: 'send', message: 'user' }, message: 'id' })
561
+ expect(node).to be_match(
562
+ type: 'hash',
563
+ user_id_value: {
564
+ type: 'send',
565
+ receiver: { type: 'send', message: 'user' },
566
+ message: 'id'
567
+ }
568
+ )
545
569
  end
546
570
 
547
571
  it 'matches arguments contain' do
@@ -869,7 +893,7 @@ describe Parser::AST::Node do
869
893
  expect(range.to_range).to eq(16...27)
870
894
  end
871
895
 
872
- it "checks array' value" do
896
+ it "checks array's value" do
873
897
  node = parse('factory :admin, class: User do; end')
874
898
  range = node.child_node_range('caller.arguments.second.class_value')
875
899
  expect(range.to_range).to eq(23...27)