rubocop 0.70.0 → 0.72.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -10
  3. data/config/default.yml +50 -491
  4. data/lib/rubocop.rb +5 -53
  5. data/lib/rubocop/ast/builder.rb +2 -0
  6. data/lib/rubocop/ast/node.rb +1 -1
  7. data/lib/rubocop/ast/node/float_node.rb +12 -0
  8. data/lib/rubocop/ast/node/int_node.rb +12 -0
  9. data/lib/rubocop/ast/node/mixin/numeric_node.rb +21 -0
  10. data/lib/rubocop/ast/node/resbody_node.rb +1 -6
  11. data/lib/rubocop/cached_data.rb +1 -1
  12. data/lib/rubocop/config.rb +35 -6
  13. data/lib/rubocop/config_loader.rb +2 -2
  14. data/lib/rubocop/config_loader_resolver.rb +0 -6
  15. data/lib/rubocop/cop/cop.rb +0 -4
  16. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +55 -0
  17. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  18. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +3 -1
  19. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -0
  20. data/lib/rubocop/cop/layout/indent_first_argument.rb +6 -2
  21. data/lib/rubocop/cop/layout/indent_first_parameter.rb +7 -3
  22. data/lib/rubocop/cop/layout/indent_heredoc.rb +0 -1
  23. data/lib/rubocop/cop/layout/indentation_consistency.rb +13 -12
  24. data/lib/rubocop/cop/layout/indentation_width.rb +8 -4
  25. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +2 -0
  26. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  27. data/lib/rubocop/cop/mixin/hash_alignment.rb +4 -0
  28. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +20 -22
  29. data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
  30. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -1
  31. data/lib/rubocop/cop/style/float_division.rb +94 -0
  32. data/lib/rubocop/cop/style/format_string.rb +7 -3
  33. data/lib/rubocop/cop/style/if_inside_else.rb +42 -0
  34. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -1
  35. data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
  36. data/lib/rubocop/cop/style/ternary_parentheses.rb +12 -2
  37. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -0
  38. data/lib/rubocop/cop/style/word_array.rb +2 -2
  39. data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -1
  40. data/lib/rubocop/node_pattern.rb +84 -5
  41. data/lib/rubocop/options.rb +0 -2
  42. data/lib/rubocop/processed_source.rb +5 -1
  43. data/lib/rubocop/rspec/cop_helper.rb +0 -1
  44. data/lib/rubocop/rspec/shared_contexts.rb +0 -17
  45. data/lib/rubocop/rspec/support.rb +0 -1
  46. data/lib/rubocop/runner.rb +6 -7
  47. data/lib/rubocop/version.rb +1 -1
  48. data/lib/rubocop/yaml_duplication_checker.rb +8 -2
  49. metadata +7 -69
  50. data/lib/rubocop/cop/mixin/target_rails_version.rb +0 -16
  51. data/lib/rubocop/cop/rails/action_filter.rb +0 -117
  52. data/lib/rubocop/cop/rails/active_record_aliases.rb +0 -48
  53. data/lib/rubocop/cop/rails/active_record_override.rb +0 -82
  54. data/lib/rubocop/cop/rails/active_support_aliases.rb +0 -69
  55. data/lib/rubocop/cop/rails/application_job.rb +0 -40
  56. data/lib/rubocop/cop/rails/application_record.rb +0 -40
  57. data/lib/rubocop/cop/rails/assert_not.rb +0 -44
  58. data/lib/rubocop/cop/rails/belongs_to.rb +0 -102
  59. data/lib/rubocop/cop/rails/blank.rb +0 -164
  60. data/lib/rubocop/cop/rails/bulk_change_table.rb +0 -289
  61. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +0 -91
  62. data/lib/rubocop/cop/rails/date.rb +0 -161
  63. data/lib/rubocop/cop/rails/delegate.rb +0 -132
  64. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +0 -37
  65. data/lib/rubocop/cop/rails/dynamic_find_by.rb +0 -91
  66. data/lib/rubocop/cop/rails/enum_uniqueness.rb +0 -45
  67. data/lib/rubocop/cop/rails/environment_comparison.rb +0 -68
  68. data/lib/rubocop/cop/rails/exit.rb +0 -67
  69. data/lib/rubocop/cop/rails/file_path.rb +0 -108
  70. data/lib/rubocop/cop/rails/find_by.rb +0 -55
  71. data/lib/rubocop/cop/rails/find_each.rb +0 -51
  72. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +0 -25
  73. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +0 -106
  74. data/lib/rubocop/cop/rails/http_positional_arguments.rb +0 -117
  75. data/lib/rubocop/cop/rails/http_status.rb +0 -179
  76. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -94
  77. data/lib/rubocop/cop/rails/inverse_of.rb +0 -246
  78. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +0 -175
  79. data/lib/rubocop/cop/rails/link_to_blank.rb +0 -98
  80. data/lib/rubocop/cop/rails/not_null_column.rb +0 -67
  81. data/lib/rubocop/cop/rails/output.rb +0 -49
  82. data/lib/rubocop/cop/rails/output_safety.rb +0 -99
  83. data/lib/rubocop/cop/rails/pluralization_grammar.rb +0 -107
  84. data/lib/rubocop/cop/rails/presence.rb +0 -124
  85. data/lib/rubocop/cop/rails/present.rb +0 -153
  86. data/lib/rubocop/cop/rails/read_write_attribute.rb +0 -74
  87. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +0 -111
  88. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +0 -136
  89. data/lib/rubocop/cop/rails/reflection_class_name.rb +0 -37
  90. data/lib/rubocop/cop/rails/refute_methods.rb +0 -76
  91. data/lib/rubocop/cop/rails/relative_date_constant.rb +0 -93
  92. data/lib/rubocop/cop/rails/request_referer.rb +0 -56
  93. data/lib/rubocop/cop/rails/reversible_migration.rb +0 -286
  94. data/lib/rubocop/cop/rails/safe_navigation.rb +0 -87
  95. data/lib/rubocop/cop/rails/save_bang.rb +0 -316
  96. data/lib/rubocop/cop/rails/scope_args.rb +0 -29
  97. data/lib/rubocop/cop/rails/skips_model_validations.rb +0 -87
  98. data/lib/rubocop/cop/rails/time_zone.rb +0 -238
  99. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +0 -105
  100. data/lib/rubocop/cop/rails/unknown_env.rb +0 -63
  101. data/lib/rubocop/cop/rails/validation.rb +0 -109
  102. data/lib/rubocop/rspec/shared_examples.rb +0 -59
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop checks for calls to `link_to` that contain a
7
- # `target: '_blank'` but no `rel: 'noopener'`. This can be a security
8
- # risk as the loaded page will have control over the previous page
9
- # and could change its location for phishing purposes.
10
- #
11
- # The option `rel: 'noreferrer'` also blocks this behavior
12
- # and removes the http-referrer header.
13
- #
14
- # @example
15
- # # bad
16
- # link_to 'Click here', url, target: '_blank'
17
- #
18
- # # good
19
- # link_to 'Click here', url, target: '_blank', rel: 'noopener'
20
- #
21
- # # good
22
- # link_to 'Click here', url, target: '_blank', rel: 'noreferrer'
23
- class LinkToBlank < Cop
24
- MSG = 'Specify a `:rel` option containing noopener.'
25
-
26
- def_node_matcher :blank_target?, <<-PATTERN
27
- (pair {(sym :target) (str "target")} {(str "_blank") (sym :_blank)})
28
- PATTERN
29
-
30
- def_node_matcher :includes_noopener?, <<-PATTERN
31
- (pair {(sym :rel) (str "rel")} ({str sym} #contains_noopener?))
32
- PATTERN
33
-
34
- def_node_matcher :rel_node?, <<-PATTERN
35
- (pair {(sym :rel) (str "rel")} (str _))
36
- PATTERN
37
-
38
- def on_send(node)
39
- return unless node.method?(:link_to)
40
-
41
- option_nodes = node.each_child_node(:hash)
42
-
43
- option_nodes.map(&:children).each do |options|
44
- blank = options.find { |o| blank_target?(o) }
45
- if blank && options.none? { |o| includes_noopener?(o) }
46
- add_offense(blank)
47
- end
48
- end
49
- end
50
-
51
- def autocorrect(node)
52
- lambda do |corrector|
53
- send_node = node.parent.parent
54
-
55
- option_nodes = send_node.each_child_node(:hash)
56
- rel_node = nil
57
- option_nodes.map(&:children).each do |options|
58
- rel_node ||= options.find { |o| rel_node?(o) }
59
- end
60
-
61
- if rel_node
62
- append_to_rel(rel_node, corrector)
63
- else
64
- add_rel(send_node, node, corrector)
65
- end
66
- end
67
- end
68
-
69
- private
70
-
71
- def append_to_rel(rel_node, corrector)
72
- existing_rel = rel_node.children.last.value
73
- str_range = rel_node.children.last.loc.expression.adjust(
74
- begin_pos: 1,
75
- end_pos: -1
76
- )
77
- corrector.replace(str_range, "#{existing_rel} noopener")
78
- end
79
-
80
- def add_rel(send_node, offence_node, corrector)
81
- opening_quote = offence_node.children.last.source[0]
82
- closing_quote = opening_quote == ':' ? '' : opening_quote
83
- new_rel_exp = ", rel: #{opening_quote}noopener#{closing_quote}"
84
- range = send_node.arguments.last.source_range
85
-
86
- corrector.insert_after(range, new_rel_exp)
87
- end
88
-
89
- def contains_noopener?(value)
90
- return false unless value
91
-
92
- rel_array = value.to_s.split(' ')
93
- rel_array.include?('noopener') || rel_array.include?('noreferrer')
94
- end
95
- end
96
- end
97
- end
98
- end
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop checks for add_column call with NOT NULL constraint
7
- # in migration file.
8
- #
9
- # @example
10
- # # bad
11
- # add_column :users, :name, :string, null: false
12
- # add_reference :products, :category, null: false
13
- #
14
- # # good
15
- # add_column :users, :name, :string, null: true
16
- # add_column :users, :name, :string, null: false, default: ''
17
- # add_reference :products, :category
18
- # add_reference :products, :category, null: false, default: 1
19
- class NotNullColumn < Cop
20
- MSG = 'Do not add a NOT NULL column without a default value.'
21
-
22
- def_node_matcher :add_not_null_column?, <<-PATTERN
23
- (send nil? :add_column _ _ _ (hash $...))
24
- PATTERN
25
-
26
- def_node_matcher :add_not_null_reference?, <<-PATTERN
27
- (send nil? :add_reference _ _ (hash $...))
28
- PATTERN
29
-
30
- def_node_matcher :null_false?, <<-PATTERN
31
- (pair (sym :null) (false))
32
- PATTERN
33
-
34
- def_node_matcher :default_option?, <<-PATTERN
35
- (pair (sym :default) !nil)
36
- PATTERN
37
-
38
- def on_send(node)
39
- check_add_column(node)
40
- check_add_reference(node)
41
- end
42
-
43
- private
44
-
45
- def check_add_column(node)
46
- pairs = add_not_null_column?(node)
47
- check_pairs(pairs)
48
- end
49
-
50
- def check_add_reference(node)
51
- pairs = add_not_null_reference?(node)
52
- check_pairs(pairs)
53
- end
54
-
55
- def check_pairs(pairs)
56
- return unless pairs
57
- return if pairs.any? { |pair| default_option?(pair) }
58
-
59
- null_false = pairs.find { |pair| null_false?(pair) }
60
- return unless null_false
61
-
62
- add_offense(null_false)
63
- end
64
- end
65
- end
66
- end
67
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop checks for the use of output calls like puts and print
7
- #
8
- # @example
9
- # # bad
10
- # puts 'A debug message'
11
- # pp 'A debug message'
12
- # print 'A debug message'
13
- #
14
- # # good
15
- # Rails.logger.debug 'A debug message'
16
- class Output < Cop
17
- MSG = 'Do not write to stdout. ' \
18
- "Use Rails's logger if you want to log."
19
-
20
- def_node_matcher :output?, <<-PATTERN
21
- (send nil? {:ap :p :pp :pretty_print :print :puts} ...)
22
- PATTERN
23
-
24
- def_node_matcher :io_output?, <<-PATTERN
25
- (send
26
- {
27
- (gvar #match_gvar?)
28
- {(const nil? :STDOUT) (const nil? :STDERR)}
29
- }
30
- {:binwrite :syswrite :write :write_nonblock}
31
- ...)
32
- PATTERN
33
-
34
- def on_send(node)
35
- return unless (output?(node) || io_output?(node)) &&
36
- node.arguments?
37
-
38
- add_offense(node, location: :selector)
39
- end
40
-
41
- private
42
-
43
- def match_gvar?(sym)
44
- %i[$stdout $stderr].include?(sym)
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,99 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop checks for the use of output safety calls like `html_safe`,
7
- # `raw`, and `safe_concat`. These methods do not escape content. They
8
- # simply return a SafeBuffer containing the content as is. Instead,
9
- # use `safe_join` to join content and escape it and concat to
10
- # concatenate content and escape it, ensuring its safety.
11
- #
12
- # @example
13
- # user_content = "<b>hi</b>"
14
- #
15
- # # bad
16
- # "<p>#{user_content}</p>".html_safe
17
- # # => ActiveSupport::SafeBuffer "<p><b>hi</b></p>"
18
- #
19
- # # good
20
- # content_tag(:p, user_content)
21
- # # => ActiveSupport::SafeBuffer "<p>&lt;b&gt;hi&lt;/b&gt;</p>"
22
- #
23
- # # bad
24
- # out = ""
25
- # out << "<li>#{user_content}</li>"
26
- # out << "<li>#{user_content}</li>"
27
- # out.html_safe
28
- # # => ActiveSupport::SafeBuffer "<li><b>hi</b></li><li><b>hi</b></li>"
29
- #
30
- # # good
31
- # out = []
32
- # out << content_tag(:li, user_content)
33
- # out << content_tag(:li, user_content)
34
- # safe_join(out)
35
- # # => ActiveSupport::SafeBuffer
36
- # # "<li>&lt;b&gt;hi&lt;/b&gt;</li><li>&lt;b&gt;hi&lt;/b&gt;</li>"
37
- #
38
- # # bad
39
- # out = "<h1>trusted content</h1>".html_safe
40
- # out.safe_concat(user_content)
41
- # # => ActiveSupport::SafeBuffer "<h1>trusted_content</h1><b>hi</b>"
42
- #
43
- # # good
44
- # out = "<h1>trusted content</h1>".html_safe
45
- # out.concat(user_content)
46
- # # => ActiveSupport::SafeBuffer
47
- # # "<h1>trusted_content</h1>&lt;b&gt;hi&lt;/b&gt;"
48
- #
49
- # # safe, though maybe not good style
50
- # out = "trusted content"
51
- # result = out.concat(user_content)
52
- # # => String "trusted content<b>hi</b>"
53
- # # because when rendered in ERB the String will be escaped:
54
- # # <%= result %>
55
- # # => trusted content&lt;b&gt;hi&lt;/b&gt;
56
- #
57
- # # bad
58
- # (user_content + " " + content_tag(:span, user_content)).html_safe
59
- # # => ActiveSupport::SafeBuffer "<b>hi</b> <span><b>hi</b></span>"
60
- #
61
- # # good
62
- # safe_join([user_content, " ", content_tag(:span, user_content)])
63
- # # => ActiveSupport::SafeBuffer
64
- # # "&lt;b&gt;hi&lt;/b&gt; <span>&lt;b&gt;hi&lt;/b&gt;</span>"
65
- class OutputSafety < Cop
66
- MSG = 'Tagging a string as html safe may be a security risk.'
67
-
68
- def on_send(node)
69
- return if non_interpolated_string?(node)
70
-
71
- return unless looks_like_rails_html_safe?(node) ||
72
- looks_like_rails_raw?(node) ||
73
- looks_like_rails_safe_concat?(node)
74
-
75
- add_offense(node, location: :selector)
76
- end
77
- alias on_csend on_send
78
-
79
- private
80
-
81
- def non_interpolated_string?(node)
82
- node.receiver&.str_type? && !node.receiver.dstr_type?
83
- end
84
-
85
- def looks_like_rails_html_safe?(node)
86
- node.receiver && node.method?(:html_safe) && !node.arguments?
87
- end
88
-
89
- def looks_like_rails_raw?(node)
90
- node.command?(:raw) && node.arguments.one?
91
- end
92
-
93
- def looks_like_rails_safe_concat?(node)
94
- node.method?(:safe_concat) && node.arguments.one?
95
- end
96
- end
97
- end
98
- end
99
- end
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop checks for correct grammar when using ActiveSupport's
7
- # core extensions to the numeric classes.
8
- #
9
- # @example
10
- # # bad
11
- # 3.day.ago
12
- # 1.months.ago
13
- #
14
- # # good
15
- # 3.days.ago
16
- # 1.month.ago
17
- class PluralizationGrammar < Cop
18
- SINGULAR_DURATION_METHODS = { second: :seconds,
19
- minute: :minutes,
20
- hour: :hours,
21
- day: :days,
22
- week: :weeks,
23
- fortnight: :fortnights,
24
- month: :months,
25
- year: :years }.freeze
26
-
27
- PLURAL_DURATION_METHODS = SINGULAR_DURATION_METHODS.invert.freeze
28
-
29
- MSG = 'Prefer `%<number>s.%<correct>s`.'
30
-
31
- def on_send(node)
32
- return unless duration_method?(node.method_name)
33
- return unless literal_number?(node.receiver)
34
-
35
- return unless offense?(node)
36
-
37
- add_offense(node)
38
- end
39
-
40
- def autocorrect(node)
41
- lambda do |corrector|
42
- method_name = node.loc.selector.source
43
-
44
- corrector.replace(node.loc.selector, correct_method(method_name))
45
- end
46
- end
47
-
48
- private
49
-
50
- def message(node)
51
- number, = *node.receiver
52
-
53
- format(MSG, number: number,
54
- correct: correct_method(node.method_name.to_s))
55
- end
56
-
57
- def correct_method(method_name)
58
- if plural_method?(method_name)
59
- singularize(method_name)
60
- else
61
- pluralize(method_name)
62
- end
63
- end
64
-
65
- def offense?(node)
66
- number, = *node.receiver
67
-
68
- singular_receiver?(number) && plural_method?(node.method_name) ||
69
- plural_receiver?(number) && singular_method?(node.method_name)
70
- end
71
-
72
- def plural_method?(method_name)
73
- method_name.to_s.end_with?('s')
74
- end
75
-
76
- def singular_method?(method_name)
77
- !plural_method?(method_name)
78
- end
79
-
80
- def singular_receiver?(number)
81
- number.abs == 1
82
- end
83
-
84
- def plural_receiver?(number)
85
- !singular_receiver?(number)
86
- end
87
-
88
- def literal_number?(node)
89
- node && (node.int_type? || node.float_type?)
90
- end
91
-
92
- def pluralize(method_name)
93
- SINGULAR_DURATION_METHODS.fetch(method_name.to_sym).to_s
94
- end
95
-
96
- def singularize(method_name)
97
- PLURAL_DURATION_METHODS.fetch(method_name.to_sym).to_s
98
- end
99
-
100
- def duration_method?(method_name)
101
- SINGULAR_DURATION_METHODS.key?(method_name) ||
102
- PLURAL_DURATION_METHODS.key?(method_name)
103
- end
104
- end
105
- end
106
- end
107
- end
@@ -1,124 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Rails
6
- # This cop checks code that can be written more easily using
7
- # `Object#presence` defined by Active Support.
8
- #
9
- # @example
10
- # # bad
11
- # a.present? ? a : nil
12
- #
13
- # # bad
14
- # !a.present? ? nil : a
15
- #
16
- # # bad
17
- # a.blank? ? nil : a
18
- #
19
- # # bad
20
- # !a.blank? ? a : nil
21
- #
22
- # # good
23
- # a.presence
24
- #
25
- # @example
26
- # # bad
27
- # a.present? ? a : b
28
- #
29
- # # bad
30
- # !a.present? ? b : a
31
- #
32
- # # bad
33
- # a.blank? ? b : a
34
- #
35
- # # bad
36
- # !a.blank? ? a : b
37
- #
38
- # # good
39
- # a.presence || b
40
- class Presence < Cop
41
- MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
42
-
43
- def_node_matcher :redundant_receiver_and_other, <<-PATTERN
44
- {
45
- (if
46
- (send $_recv :present?)
47
- _recv
48
- $!begin
49
- )
50
- (if
51
- (send $_recv :blank?)
52
- $!begin
53
- _recv
54
- )
55
- }
56
- PATTERN
57
-
58
- def_node_matcher :redundant_negative_receiver_and_other, <<-PATTERN
59
- {
60
- (if
61
- (send (send $_recv :present?) :!)
62
- $!begin
63
- _recv
64
- )
65
- (if
66
- (send (send $_recv :blank?) :!)
67
- _recv
68
- $!begin
69
- )
70
- }
71
- PATTERN
72
-
73
- def on_if(node)
74
- return if ignore_if_node?(node)
75
-
76
- redundant_receiver_and_other(node) do |receiver, other|
77
- unless ignore_other_node?(other) || receiver.nil?
78
- add_offense(node, message: message(node, receiver, other))
79
- end
80
- end
81
-
82
- redundant_negative_receiver_and_other(node) do |receiver, other|
83
- unless ignore_other_node?(other) || receiver.nil?
84
- add_offense(node, message: message(node, receiver, other))
85
- end
86
- end
87
- end
88
-
89
- def autocorrect(node)
90
- lambda do |corrector|
91
- redundant_receiver_and_other(node) do |receiver, other|
92
- corrector.replace(node.source_range, replacement(receiver, other))
93
- end
94
-
95
- redundant_negative_receiver_and_other(node) do |receiver, other|
96
- corrector.replace(node.source_range, replacement(receiver, other))
97
- end
98
- end
99
- end
100
-
101
- private
102
-
103
- def ignore_if_node?(node)
104
- node.elsif?
105
- end
106
-
107
- def ignore_other_node?(node)
108
- node && (node.if_type? || node.rescue_type? || node.while_type?)
109
- end
110
-
111
- def message(node, receiver, other)
112
- format(MSG,
113
- prefer: replacement(receiver, other),
114
- current: node.source)
115
- end
116
-
117
- def replacement(receiver, other)
118
- or_source = other.nil? || other.nil_type? ? '' : " || #{other.source}"
119
- "#{receiver.source}.presence" + or_source
120
- end
121
- end
122
- end
123
- end
124
- end