rubocop-rails 2.17.4 → 2.19.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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +22 -2
- data/config/default.yml +54 -29
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +1 -1
- data/lib/rubocop/cop/mixin/index_method.rb +3 -3
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +10 -2
- data/lib/rubocop/cop/rails/action_controller_test_case.rb +1 -1
- data/lib/rubocop/cop/rails/action_order.rb +5 -6
- data/lib/rubocop/cop/rails/active_record_aliases.rb +2 -0
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +6 -3
- data/lib/rubocop/cop/rails/add_column_index.rb +2 -2
- data/lib/rubocop/cop/rails/application_job.rb +1 -1
- data/lib/rubocop/cop/rails/arel_star.rb +1 -1
- data/lib/rubocop/cop/rails/assert_not.rb +1 -1
- data/lib/rubocop/cop/rails/belongs_to.rb +1 -4
- data/lib/rubocop/cop/rails/blank.rb +5 -5
- data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -4
- data/lib/rubocop/cop/rails/compact_blank.rb +2 -2
- data/lib/rubocop/cop/rails/content_tag.rb +1 -1
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +16 -3
- data/lib/rubocop/cop/rails/delegate.rb +17 -3
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +1 -1
- data/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb +1 -1
- data/lib/rubocop/cop/rails/duration_arithmetic.rb +1 -1
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +1 -1
- data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +1 -1
- data/lib/rubocop/cop/rails/enum_hash.rb +1 -1
- data/lib/rubocop/cop/rails/environment_comparison.rb +1 -1
- data/lib/rubocop/cop/rails/file_path.rb +31 -15
- data/lib/rubocop/cop/rails/find_by_id.rb +2 -2
- data/lib/rubocop/cop/rails/find_each.rb +6 -2
- data/lib/rubocop/cop/rails/freeze_time.rb +3 -0
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +2 -2
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +18 -2
- data/lib/rubocop/cop/rails/http_status.rb +1 -1
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -2
- data/lib/rubocop/cop/rails/inverse_of.rb +0 -3
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -7
- data/lib/rubocop/cop/rails/link_to_blank.rb +1 -1
- data/lib/rubocop/cop/rails/mailer_name.rb +1 -1
- data/lib/rubocop/cop/rails/negate_include.rb +1 -1
- data/lib/rubocop/cop/rails/not_null_column.rb +9 -6
- data/lib/rubocop/cop/rails/output.rb +3 -2
- data/lib/rubocop/cop/rails/output_safety.rb +5 -1
- data/lib/rubocop/cop/rails/pluck.rb +13 -1
- data/lib/rubocop/cop/rails/pluck_id.rb +1 -1
- data/lib/rubocop/cop/rails/presence.rb +3 -3
- data/lib/rubocop/cop/rails/present.rb +5 -5
- data/lib/rubocop/cop/rails/rake_environment.rb +1 -1
- data/lib/rubocop/cop/rails/read_write_attribute.rb +1 -1
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +3 -3
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -1
- data/lib/rubocop/cop/rails/reflection_class_name.rb +17 -1
- data/lib/rubocop/cop/rails/relative_date_constant.rb +2 -2
- data/lib/rubocop/cop/rails/response_parsed_body.rb +57 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +4 -29
- data/lib/rubocop/cop/rails/root_join_chain.rb +1 -1
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +1 -1
- data/lib/rubocop/cop/rails/safe_navigation.rb +1 -1
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +8 -1
- data/lib/rubocop/cop/rails/three_state_boolean_column.rb +71 -0
- data/lib/rubocop/cop/rails/time_zone.rb +2 -2
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +0 -2
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -1
- data/lib/rubocop/cop/rails/unused_ignored_columns.rb +6 -1
- data/lib/rubocop/cop/rails/validation.rb +1 -1
- data/lib/rubocop/cop/rails/where_equals.rb +1 -1
- data/lib/rubocop/cop/rails/where_exists.rb +1 -1
- data/lib/rubocop/cop/rails/where_missing.rb +3 -3
- data/lib/rubocop/cop/rails/where_not.rb +1 -1
- data/lib/rubocop/cop/rails/where_not_with_multiple_conditions.rb +2 -2
- data/lib/rubocop/cop/rails_cops.rb +2 -0
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop/rails.rb +1 -1
- data/lib/rubocop-rails.rb +1 -0
- metadata +6 -4
@@ -78,7 +78,7 @@ module RuboCop
|
|
78
78
|
def on_send(node)
|
79
79
|
duration_arithmetic_argument?(node) do |*operation|
|
80
80
|
add_offense(node) do |corrector|
|
81
|
-
corrector.replace(node
|
81
|
+
corrector.replace(node, corrected_source(*operation))
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
@@ -99,7 +99,7 @@ module RuboCop
|
|
99
99
|
|
100
100
|
def autocorrect_argument_keywords(corrector, node, keywords)
|
101
101
|
keywords.each.with_index do |keyword, idx|
|
102
|
-
corrector.insert_before(node.arguments[idx]
|
102
|
+
corrector.insert_before(node.arguments[idx], keyword)
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
@@ -3,34 +3,43 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
# Identifies usages of file path joining process
|
7
|
-
#
|
8
|
-
# joining paths.
|
6
|
+
# Identifies usages of file path joining process to use `Rails.root.join` clause.
|
7
|
+
# It is used to add uniformity when joining paths.
|
9
8
|
#
|
10
9
|
# @example EnforcedStyle: slashes (default)
|
11
10
|
# # bad
|
12
11
|
# Rails.root.join('app', 'models', 'goober')
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# Rails.root.join('app/models/goober')
|
15
|
+
#
|
16
|
+
# # bad
|
13
17
|
# File.join(Rails.root, 'app/models/goober')
|
14
18
|
# "#{Rails.root}/app/models/goober"
|
15
19
|
#
|
16
20
|
# # good
|
17
|
-
# Rails.root.join('app/models/goober')
|
21
|
+
# Rails.root.join('app/models/goober').to_s
|
18
22
|
#
|
19
23
|
# @example EnforcedStyle: arguments
|
20
24
|
# # bad
|
21
25
|
# Rails.root.join('app/models/goober')
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# Rails.root.join('app', 'models', 'goober')
|
29
|
+
#
|
30
|
+
# # bad
|
22
31
|
# File.join(Rails.root, 'app/models/goober')
|
23
32
|
# "#{Rails.root}/app/models/goober"
|
24
33
|
#
|
25
34
|
# # good
|
26
|
-
# Rails.root.join('app', 'models', 'goober')
|
35
|
+
# Rails.root.join('app', 'models', 'goober').to_s
|
27
36
|
#
|
28
37
|
class FilePath < Base
|
29
38
|
include ConfigurableEnforcedStyle
|
30
39
|
include RangeHelp
|
31
40
|
|
32
|
-
MSG_SLASHES = 'Prefer `Rails.root.join(\'path/to\')`.'
|
33
|
-
MSG_ARGUMENTS = 'Prefer `Rails.root.join(\'path\', \'to\')`.'
|
41
|
+
MSG_SLASHES = 'Prefer `Rails.root.join(\'path/to\')%<to_s>s`.'
|
42
|
+
MSG_ARGUMENTS = 'Prefer `Rails.root.join(\'path\', \'to\')%<to_s>s`.'
|
34
43
|
RESTRICT_ON_SEND = %i[join].freeze
|
35
44
|
|
36
45
|
def_node_matcher :file_join_nodes?, <<~PATTERN
|
@@ -53,7 +62,7 @@ module RuboCop
|
|
53
62
|
return unless last_child_source.start_with?('.') || last_child_source.include?(File::SEPARATOR)
|
54
63
|
return if last_child_source.start_with?(':')
|
55
64
|
|
56
|
-
register_offense(node)
|
65
|
+
register_offense(node, require_to_s: true)
|
57
66
|
end
|
58
67
|
|
59
68
|
def on_send(node)
|
@@ -68,7 +77,7 @@ module RuboCop
|
|
68
77
|
return unless file_join_nodes?(node)
|
69
78
|
return unless node.arguments.any? { |e| rails_root_nodes?(e) }
|
70
79
|
|
71
|
-
register_offense(node)
|
80
|
+
register_offense(node, require_to_s: true)
|
72
81
|
end
|
73
82
|
|
74
83
|
def check_for_rails_root_join_with_string_arguments(node)
|
@@ -78,7 +87,7 @@ module RuboCop
|
|
78
87
|
return unless node.arguments.size > 1
|
79
88
|
return unless node.arguments.all?(&:str_type?)
|
80
89
|
|
81
|
-
register_offense(node)
|
90
|
+
register_offense(node, require_to_s: false)
|
82
91
|
end
|
83
92
|
|
84
93
|
def check_for_rails_root_join_with_slash_separated_path(node)
|
@@ -87,21 +96,28 @@ module RuboCop
|
|
87
96
|
return unless rails_root_join_nodes?(node)
|
88
97
|
return unless node.arguments.any? { |arg| string_with_slash?(arg) }
|
89
98
|
|
90
|
-
register_offense(node)
|
99
|
+
register_offense(node, require_to_s: false)
|
91
100
|
end
|
92
101
|
|
93
102
|
def string_with_slash?(node)
|
94
103
|
node.str_type? && node.source.include?('/')
|
95
104
|
end
|
96
105
|
|
97
|
-
def register_offense(node)
|
106
|
+
def register_offense(node, require_to_s:)
|
98
107
|
line_range = node.loc.column...node.loc.last_column
|
99
108
|
source_range = source_range(processed_source.buffer, node.first_line, line_range)
|
100
|
-
|
109
|
+
require_to_s = false if node.dstr_type?
|
110
|
+
|
111
|
+
message = build_message(require_to_s)
|
112
|
+
|
113
|
+
add_offense(source_range, message: message)
|
101
114
|
end
|
102
115
|
|
103
|
-
def
|
104
|
-
|
116
|
+
def build_message(require_to_s)
|
117
|
+
message_template = style == :arguments ? MSG_ARGUMENTS : MSG_SLASHES
|
118
|
+
to_s = require_to_s ? '.to_s' : ''
|
119
|
+
|
120
|
+
format(message_template, to_s: to_s)
|
105
121
|
end
|
106
122
|
end
|
107
123
|
end
|
@@ -65,11 +65,11 @@ module RuboCop
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def where_take_offense_range(node, where)
|
68
|
-
range_between(where.loc.selector.begin_pos, node.
|
68
|
+
range_between(where.loc.selector.begin_pos, node.source_range.end_pos)
|
69
69
|
end
|
70
70
|
|
71
71
|
def find_by_offense_range(node)
|
72
|
-
range_between(node.loc.selector.begin_pos, node.
|
72
|
+
range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
|
73
73
|
end
|
74
74
|
|
75
75
|
def build_good_method(id_value)
|
@@ -3,8 +3,12 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
# Identifies usages of `all.each` and
|
7
|
-
#
|
6
|
+
# Identifies usages of `all.each` and change them to use `all.find_each` instead.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# This cop is unsafe if the receiver object is not an Active Record object.
|
10
|
+
# Also, `all.each` returns an `Array` instance and `all.find_each` returns nil,
|
11
|
+
# so the return values are different.
|
8
12
|
#
|
9
13
|
# @example
|
10
14
|
# # bad
|
@@ -41,11 +41,11 @@ module RuboCop
|
|
41
41
|
PATTERN
|
42
42
|
|
43
43
|
def_node_matcher :association_without_options?, <<~PATTERN
|
44
|
-
(send
|
44
|
+
(send _ {:has_many :has_one} _)
|
45
45
|
PATTERN
|
46
46
|
|
47
47
|
def_node_matcher :association_with_options?, <<~PATTERN
|
48
|
-
(send
|
48
|
+
(send _ {:has_many :has_one} ... (hash $...))
|
49
49
|
PATTERN
|
50
50
|
|
51
51
|
def_node_matcher :dependent_option?, <<~PATTERN
|
@@ -10,6 +10,9 @@ module RuboCop
|
|
10
10
|
# Rails/HttpPositionalArguments cop or set your TargetRailsVersion in your
|
11
11
|
# .rubocop.yml file to 4.2.
|
12
12
|
#
|
13
|
+
# NOTE: It does not detect any cases where `include Rack::Test::Methods` is used
|
14
|
+
# which makes the http methods incompatible behavior.
|
15
|
+
#
|
13
16
|
# @example
|
14
17
|
# # bad
|
15
18
|
# get :new, { user_id: 1}
|
@@ -37,8 +40,15 @@ module RuboCop
|
|
37
40
|
(hash (kwsplat _))
|
38
41
|
PATTERN
|
39
42
|
|
43
|
+
def_node_matcher :include_rack_test_methods?, <<~PATTERN
|
44
|
+
(send nil? :include
|
45
|
+
(const
|
46
|
+
(const
|
47
|
+
(const {nil? cbase} :Rack) :Test) :Methods))
|
48
|
+
PATTERN
|
49
|
+
|
40
50
|
def on_send(node)
|
41
|
-
return if in_routing_block?(node)
|
51
|
+
return if in_routing_block?(node) || use_rack_test_methods?
|
42
52
|
|
43
53
|
http_request?(node) do |data|
|
44
54
|
return unless needs_conversion?(data)
|
@@ -56,7 +66,7 @@ module RuboCop
|
|
56
66
|
# that represents the path/action on the Rails controller
|
57
67
|
# the data is the http parameters and environment sent in
|
58
68
|
# the Rails 5 http call
|
59
|
-
corrector.replace(node
|
69
|
+
corrector.replace(node, correction(node))
|
60
70
|
end
|
61
71
|
end
|
62
72
|
end
|
@@ -67,6 +77,12 @@ module RuboCop
|
|
67
77
|
!!node.each_ancestor(:block).detect { |block| ROUTING_METHODS.include?(block.method_name) }
|
68
78
|
end
|
69
79
|
|
80
|
+
def use_rack_test_methods?
|
81
|
+
processed_source.ast.each_descendant(:send).any? do |node|
|
82
|
+
include_rack_test_methods?(node)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
70
86
|
def needs_conversion?(data)
|
71
87
|
return true unless data.hash_type?
|
72
88
|
return false if kwsplat_hash?(data)
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
66
66
|
return unless checker.offensive?
|
67
67
|
|
68
68
|
add_offense(checker.node, message: checker.message) do |corrector|
|
69
|
-
corrector.replace(checker.node
|
69
|
+
corrector.replace(checker.node, checker.preferred_style)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -35,8 +35,6 @@ module RuboCop
|
|
35
35
|
# skip_before_action :login_required,
|
36
36
|
# if: -> { trusted_origin? && action_name != "admin" }
|
37
37
|
# end
|
38
|
-
#
|
39
|
-
# @see https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options
|
40
38
|
class IgnoredSkipActionFilterOption < Base
|
41
39
|
MSG = <<~MSG.chomp.freeze
|
42
40
|
`%<ignore>s` option will be ignored when `%<prefer>s` and `%<ignore>s` are used together.
|
@@ -137,9 +137,6 @@ module RuboCop
|
|
137
137
|
# class Blog < ApplicationRecord
|
138
138
|
# has_many :posts, -> { order(published_at: :desc) }
|
139
139
|
# end
|
140
|
-
#
|
141
|
-
# @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
|
142
|
-
# @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
|
143
140
|
class InverseOf < Base
|
144
141
|
SPECIFY_MSG = 'Specify an `:inverse_of` option.'
|
145
142
|
NIL_MSG = 'You specified `inverse_of: nil`, you probably meant to use `inverse_of: false`.'
|
@@ -144,19 +144,29 @@ module RuboCop
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def aliased_action_methods(node, defined_methods)
|
147
|
-
alias_methods = node
|
148
|
-
|
149
|
-
hash_of_alias_methods = alias_methods.each_with_object({}) do |alias_method, result|
|
150
|
-
result[alias_method.last_argument.value] = alias_method.first_argument.value
|
151
|
-
end
|
152
|
-
|
147
|
+
alias_methods = alias_methods(node)
|
153
148
|
defined_methods.each_with_object([]) do |defined_method, aliased_method|
|
154
|
-
if (new_method_name =
|
149
|
+
if (new_method_name = alias_methods[defined_method])
|
155
150
|
aliased_method << new_method_name
|
156
151
|
end
|
157
152
|
end
|
158
153
|
end
|
159
154
|
|
155
|
+
def alias_methods(node)
|
156
|
+
result = {}
|
157
|
+
node.each_child_node(:send, :alias) do |child_node|
|
158
|
+
case child_node.type
|
159
|
+
when :send
|
160
|
+
if child_node.method?(:alias_method)
|
161
|
+
result[child_node.last_argument.value] = child_node.first_argument.value
|
162
|
+
end
|
163
|
+
when :alias
|
164
|
+
result[child_node.old_identifier.value] = child_node.new_identifier.value
|
165
|
+
end
|
166
|
+
end
|
167
|
+
result
|
168
|
+
end
|
169
|
+
|
160
170
|
# @param node [RuboCop::AST::Node]
|
161
171
|
# @return [Array<Symbol>]
|
162
172
|
def array_values(node) # rubocop:disable Metrics/MethodLength
|
@@ -68,7 +68,7 @@ module RuboCop
|
|
68
68
|
|
69
69
|
def append_to_rel(rel_node, corrector)
|
70
70
|
existing_rel = rel_node.children.last.value
|
71
|
-
str_range = rel_node.children.last.
|
71
|
+
str_range = rel_node.children.last.source_range.adjust(begin_pos: 1, end_pos: -1)
|
72
72
|
corrector.replace(str_range, "#{existing_rel} noopener")
|
73
73
|
end
|
74
74
|
|
@@ -21,7 +21,7 @@ module RuboCop
|
|
21
21
|
RESTRICT_ON_SEND = %i[add_column add_reference].freeze
|
22
22
|
|
23
23
|
def_node_matcher :add_not_null_column?, <<~PATTERN
|
24
|
-
(send nil? :add_column _ _ _ (hash $...))
|
24
|
+
(send nil? :add_column _ _ $_ (hash $...))
|
25
25
|
PATTERN
|
26
26
|
|
27
27
|
def_node_matcher :add_not_null_reference?, <<~PATTERN
|
@@ -44,17 +44,20 @@ module RuboCop
|
|
44
44
|
private
|
45
45
|
|
46
46
|
def check_add_column(node)
|
47
|
-
|
48
|
-
|
47
|
+
add_not_null_column?(node) do |type, pairs|
|
48
|
+
return if type.value == :virtual || type.value == 'virtual'
|
49
|
+
|
50
|
+
check_pairs(pairs)
|
51
|
+
end
|
49
52
|
end
|
50
53
|
|
51
54
|
def check_add_reference(node)
|
52
|
-
|
53
|
-
|
55
|
+
add_not_null_reference?(node) do |pairs|
|
56
|
+
check_pairs(pairs)
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
def check_pairs(pairs)
|
57
|
-
return unless pairs
|
58
61
|
return if pairs.any? { |pair| default_option?(pair) }
|
59
62
|
|
60
63
|
null_false = pairs.find { |pair| null_false?(pair) }
|
@@ -39,7 +39,8 @@ module RuboCop
|
|
39
39
|
PATTERN
|
40
40
|
|
41
41
|
def on_send(node)
|
42
|
-
return
|
42
|
+
return if node.parent&.call_type?
|
43
|
+
return unless output?(node) || io_output?(node)
|
43
44
|
|
44
45
|
range = offense_range(node)
|
45
46
|
|
@@ -56,7 +57,7 @@ module RuboCop
|
|
56
57
|
|
57
58
|
def offense_range(node)
|
58
59
|
if node.receiver
|
59
|
-
range_between(node.
|
60
|
+
range_between(node.source_range.begin_pos, node.loc.selector.end_pos)
|
60
61
|
else
|
61
62
|
node.loc.selector
|
62
63
|
end
|
@@ -66,8 +66,12 @@ module RuboCop
|
|
66
66
|
MSG = 'Tagging a string as html safe may be a security risk.'
|
67
67
|
RESTRICT_ON_SEND = %i[html_safe raw safe_concat].freeze
|
68
68
|
|
69
|
+
def_node_search :i18n_method?, <<~PATTERN
|
70
|
+
(send {nil? (const {nil? cbase} :I18n)} {:t :translate :l :localize} ...)
|
71
|
+
PATTERN
|
72
|
+
|
69
73
|
def on_send(node)
|
70
|
-
return if non_interpolated_string?(node)
|
74
|
+
return if non_interpolated_string?(node) || i18n_method?(node)
|
71
75
|
|
72
76
|
return unless looks_like_rails_html_safe?(node) ||
|
73
77
|
looks_like_rails_raw?(node) ||
|
@@ -9,6 +9,18 @@ module RuboCop
|
|
9
9
|
# element in an enumerable. When called on an Active Record relation, it
|
10
10
|
# results in a more efficient query that only selects the necessary key.
|
11
11
|
#
|
12
|
+
# @safety
|
13
|
+
# This cop is unsafe because model can use column aliases.
|
14
|
+
#
|
15
|
+
# [source,ruby]
|
16
|
+
# ----
|
17
|
+
# # Original code
|
18
|
+
# User.select('name AS nickname').map { |user| user[:nickname] } # => array of nicknames
|
19
|
+
#
|
20
|
+
# # After autocorrection
|
21
|
+
# User.select('name AS nickname').pluck(:nickname) # => raises ActiveRecord::StatementInvalid
|
22
|
+
# ----
|
23
|
+
#
|
12
24
|
# @example
|
13
25
|
# # bad
|
14
26
|
# Post.published.map { |post| post[:title] }
|
@@ -31,7 +43,7 @@ module RuboCop
|
|
31
43
|
|
32
44
|
def on_block(node)
|
33
45
|
pluck_candidate?(node) do |argument, key|
|
34
|
-
next
|
46
|
+
next if key.regexp_type? || !use_one_block_argument?(argument)
|
35
47
|
|
36
48
|
match = if node.block_type?
|
37
49
|
block_argument = argument.children.first.source
|
@@ -93,7 +93,7 @@ module RuboCop
|
|
93
93
|
|
94
94
|
def register_offense(node, receiver, other)
|
95
95
|
add_offense(node, message: message(node, receiver, other)) do |corrector|
|
96
|
-
corrector.replace(node
|
96
|
+
corrector.replace(node, replacement(receiver, other, node.left_sibling))
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
@@ -112,10 +112,10 @@ module RuboCop
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def current(node)
|
115
|
-
if node.source.include?("\n")
|
115
|
+
if !node.ternary? && node.source.include?("\n")
|
116
116
|
"#{node.loc.keyword.with(end_pos: node.condition.loc.selector.end_pos).source} ... end"
|
117
117
|
else
|
118
|
-
node.source
|
118
|
+
node.source.gsub(/\n\s*/, ' ')
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# Interaction with `Style/UnlessElse`:
|
10
10
|
# The configuration of `NotBlank` will not produce an offense in the
|
11
|
-
# context of `unless else` if `Style/UnlessElse` is
|
11
|
+
# context of `unless else` if `Style/UnlessElse` is enabled. This is
|
12
12
|
# to prevent interference between the autocorrection of the two cops.
|
13
13
|
#
|
14
14
|
# @example NotNilAndNotEmpty: true (default)
|
@@ -128,10 +128,10 @@ module RuboCop
|
|
128
128
|
|
129
129
|
if method_call
|
130
130
|
corrector.replace(node.loc.keyword, 'if')
|
131
|
-
range = method_call.
|
131
|
+
range = method_call.source_range
|
132
132
|
else
|
133
133
|
variable1, _variable2 = exists_and_not_empty?(node) || not_blank?(node)
|
134
|
-
range = node.
|
134
|
+
range = node.source_range
|
135
135
|
end
|
136
136
|
|
137
137
|
corrector.replace(range, replacement(variable1))
|
@@ -141,9 +141,9 @@ module RuboCop
|
|
141
141
|
|
142
142
|
def unless_condition(node, method_call)
|
143
143
|
if node.modifier_form?
|
144
|
-
node.loc.keyword.join(node.
|
144
|
+
node.loc.keyword.join(node.source_range.end)
|
145
145
|
else
|
146
|
-
node.
|
146
|
+
node.source_range.begin.join(method_call.source_range)
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
@@ -62,7 +62,7 @@ module RuboCop
|
|
62
62
|
elsif prv_sib
|
63
63
|
corrector.remove(range_between(node_end(prv_sib), node_end(allow_nil)))
|
64
64
|
else
|
65
|
-
corrector.remove(allow_nil
|
65
|
+
corrector.remove(allow_nil)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
@@ -87,11 +87,11 @@ module RuboCop
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def node_beg(node)
|
90
|
-
node.
|
90
|
+
node.source_range.begin_pos
|
91
91
|
end
|
92
92
|
|
93
93
|
def node_end(node)
|
94
|
-
node.
|
94
|
+
node.source_range.end_pos
|
95
95
|
end
|
96
96
|
end
|
97
97
|
end
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
40
40
|
def on_send(node)
|
41
41
|
association_with_foreign_key(node) do |type, name, options, foreign_key_pair, foreign_key|
|
42
42
|
if redundant?(node, type, name, options, foreign_key)
|
43
|
-
add_offense(foreign_key_pair.
|
43
|
+
add_offense(foreign_key_pair.source_range) do |corrector|
|
44
44
|
range = range_with_surrounding_space(foreign_key_pair.source_range, side: :left)
|
45
45
|
range = range_with_surrounding_comma(range, :left)
|
46
46
|
|
@@ -89,7 +89,7 @@ module RuboCop
|
|
89
89
|
private
|
90
90
|
|
91
91
|
def autocorrect(corrector, send_node, node)
|
92
|
-
corrector.remove(send_node.receiver
|
92
|
+
corrector.remove(send_node.receiver)
|
93
93
|
corrector.remove(send_node.loc.dot)
|
94
94
|
corrector.remove(block_argument_range(send_node)) unless node.numblock_type?
|
95
95
|
end
|
@@ -18,6 +18,8 @@ module RuboCop
|
|
18
18
|
# # good
|
19
19
|
# has_many :accounts, class_name: 'Account'
|
20
20
|
class ReflectionClassName < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
21
23
|
MSG = 'Use a string value for `class_name`.'
|
22
24
|
RESTRICT_ON_SEND = %i[has_many has_one belongs_to].freeze
|
23
25
|
ALLOWED_REFLECTION_CLASS_TYPES = %i[dstr str sym].freeze
|
@@ -32,12 +34,18 @@ module RuboCop
|
|
32
34
|
(pair (sym :class_name) #reflection_class_value?)
|
33
35
|
PATTERN
|
34
36
|
|
37
|
+
def_node_matcher :const_or_string, <<~PATTERN
|
38
|
+
{$(const nil? _) (send $(const nil? _) :name) (send $(const nil? _) :to_s)}
|
39
|
+
PATTERN
|
40
|
+
|
35
41
|
def on_send(node)
|
36
42
|
association_with_reflection(node) do |reflection_class_name|
|
37
43
|
return if reflection_class_name.value.send_type? && reflection_class_name.value.receiver.nil?
|
38
44
|
return if reflection_class_name.value.lvar_type? && str_assigned?(reflection_class_name)
|
39
45
|
|
40
|
-
add_offense(reflection_class_name.
|
46
|
+
add_offense(reflection_class_name.source_range) do |corrector|
|
47
|
+
autocorrect(corrector, reflection_class_name)
|
48
|
+
end
|
41
49
|
end
|
42
50
|
end
|
43
51
|
|
@@ -64,6 +72,14 @@ module RuboCop
|
|
64
72
|
!ALLOWED_REFLECTION_CLASS_TYPES.include?(class_value.type)
|
65
73
|
end
|
66
74
|
end
|
75
|
+
|
76
|
+
def autocorrect(corrector, class_config)
|
77
|
+
class_value = class_config.value
|
78
|
+
replacement = const_or_string(class_value)
|
79
|
+
return unless replacement.present?
|
80
|
+
|
81
|
+
corrector.replace(class_value, replacement.source.inspect)
|
82
|
+
end
|
67
83
|
end
|
68
84
|
end
|
69
85
|
end
|
@@ -78,7 +78,7 @@ module RuboCop
|
|
78
78
|
indent = ' ' * node.loc.column
|
79
79
|
new_code = ["def self.#{const_name.downcase}", "#{indent}#{value.source}", 'end'].join("\n#{indent}")
|
80
80
|
|
81
|
-
corrector.replace(node
|
81
|
+
corrector.replace(node, new_code)
|
82
82
|
end
|
83
83
|
|
84
84
|
def message(method_name)
|
@@ -86,7 +86,7 @@ module RuboCop
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def offense_range(name, value)
|
89
|
-
range_between(name.
|
89
|
+
range_between(name.source_range.begin_pos, value.source_range.end_pos)
|
90
90
|
end
|
91
91
|
|
92
92
|
def nested_relative_date(node, &callback)
|