rubocop 1.43.0 → 1.45.1
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/README.md +1 -1
- data/config/default.yml +64 -29
- data/lib/rubocop/cli.rb +54 -8
- data/lib/rubocop/config_loader.rb +12 -15
- data/lib/rubocop/config_loader_resolver.rb +3 -4
- data/lib/rubocop/cop/base.rb +27 -9
- data/lib/rubocop/cop/commissioner.rb +8 -2
- data/lib/rubocop/cop/cop.rb +23 -3
- data/lib/rubocop/cop/corrector.rb +10 -2
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +1 -6
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/block_end_newline.rb +7 -1
- data/lib/rubocop/cop/layout/class_structure.rb +2 -16
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +6 -9
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -13
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +4 -4
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +5 -4
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
- data/lib/rubocop/cop/lint/debugger.rb +8 -27
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
- data/lib/rubocop/cop/lint/else_layout.rb +2 -6
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +15 -17
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -5
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +11 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +7 -4
- data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -3
- data/lib/rubocop/cop/lint/useless_rescue.rb +15 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +9 -1
- data/lib/rubocop/cop/lint/void.rb +19 -10
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +2 -5
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_methods.rb +3 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +5 -3
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +51 -25
- data/lib/rubocop/cop/mixin/line_length_help.rb +3 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -3
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +4 -0
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +1 -1
- data/lib/rubocop/cop/registry.rb +12 -7
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -11
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +8 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +3 -10
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +0 -6
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/documentation_method.rb +6 -0
- data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +114 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +11 -5
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/min_max_comparison.rb +11 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
- data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +18 -3
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -5
- data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
- data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
- data/lib/rubocop/cop/style/operator_method_call.rb +2 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +3 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +16 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -10
- data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
- data/lib/rubocop/cop/style/require_order.rb +2 -9
- data/lib/rubocop/cop/style/self_assignment.rb +2 -2
- data/lib/rubocop/cop/style/semicolon.rb +24 -2
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +12 -5
- data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
- data/lib/rubocop/cop/team.rb +19 -14
- data/lib/rubocop/cop/variable_force/scope.rb +3 -3
- data/lib/rubocop/cop/variable_force/variable_table.rb +3 -1
- data/lib/rubocop/cop/variable_force.rb +1 -1
- data/lib/rubocop/formatter.rb +0 -1
- data/lib/rubocop/options.rb +22 -1
- data/lib/rubocop/rspec/expect_offense.rb +6 -4
- data/lib/rubocop/runner.rb +40 -4
- data/lib/rubocop/server/cache.rb +10 -3
- data/lib/rubocop/server/cli.rb +37 -18
- data/lib/rubocop/server/client_command/exec.rb +1 -1
- data/lib/rubocop/server/client_command/start.rb +6 -1
- data/lib/rubocop/server/core.rb +23 -8
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +4 -0
- metadata +11 -27
@@ -62,10 +62,12 @@ module RuboCop
|
|
62
62
|
# Returns the end line of a node, which might be a comment and not part of the AST
|
63
63
|
# End line is considered either the line at which another node starts, or
|
64
64
|
# the line at which the parent node ends.
|
65
|
-
# rubocop:disable Metrics/AbcSize
|
65
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
66
66
|
def find_end_line(node)
|
67
|
-
if node.if_type? && node.
|
67
|
+
if node.if_type? && node.else?
|
68
68
|
node.loc.else.line
|
69
|
+
elsif node.if_type? && node.ternary?
|
70
|
+
node.else_branch.loc.line
|
69
71
|
elsif (next_sibling = node.right_sibling)
|
70
72
|
next_sibling.loc.line
|
71
73
|
elsif (parent = node.parent)
|
@@ -74,7 +76,7 @@ module RuboCop
|
|
74
76
|
node.loc.end.line
|
75
77
|
end
|
76
78
|
end
|
77
|
-
# rubocop:enable Metrics/AbcSize
|
79
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
78
80
|
end
|
79
81
|
end
|
80
82
|
end
|
@@ -46,21 +46,22 @@ module RuboCop
|
|
46
46
|
|
47
47
|
private
|
48
48
|
|
49
|
-
# rubocop:disable Metrics/AbcSize
|
50
|
-
def register_offense(node, message, replacement)
|
49
|
+
def register_offense(node, message, replacement) # rubocop:disable Metrics/AbcSize
|
51
50
|
add_offense(node.value, message: message) do |corrector|
|
52
51
|
if (def_node = def_node_that_require_parentheses(node))
|
53
|
-
|
52
|
+
last_argument = def_node.last_argument
|
53
|
+
if last_argument.nil? || !last_argument.hash_type?
|
54
|
+
next corrector.replace(node, replacement)
|
55
|
+
end
|
56
|
+
|
57
|
+
white_spaces = range_between(def_node.selector.end_pos,
|
54
58
|
def_node.first_argument.source_range.begin_pos)
|
55
59
|
corrector.replace(white_spaces, '(')
|
56
|
-
|
57
|
-
last_argument = def_node.arguments.last
|
58
60
|
corrector.insert_after(last_argument, ')') if node == last_argument.pairs.last
|
59
61
|
end
|
60
62
|
corrector.replace(node, replacement)
|
61
63
|
end
|
62
64
|
end
|
63
|
-
# rubocop:enable Metrics/AbcSize
|
64
65
|
|
65
66
|
def ignore_mixed_hash_shorthand_syntax?(hash_node)
|
66
67
|
target_ruby_version <= 3.0 || enforced_shorthand_syntax != 'consistent' ||
|
@@ -87,31 +88,37 @@ module RuboCop
|
|
87
88
|
end
|
88
89
|
|
89
90
|
def require_hash_value_for_around_hash_literal?(node)
|
90
|
-
return false unless (
|
91
|
+
return false unless (method_dispatch_node = find_ancestor_method_dispatch_node(node))
|
91
92
|
|
92
|
-
!node.parent.braces? &&
|
93
|
-
|
93
|
+
!node.parent.braces? &&
|
94
|
+
!use_element_of_hash_literal_as_receiver?(method_dispatch_node, node.parent) &&
|
95
|
+
use_modifier_form_without_parenthesized_method_call?(method_dispatch_node)
|
94
96
|
end
|
95
97
|
|
98
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
96
99
|
def def_node_that_require_parentheses(node)
|
97
100
|
last_pair = node.parent.pairs.last
|
98
101
|
return unless last_pair.key.source == last_pair.value.source
|
99
|
-
return unless (
|
100
|
-
return
|
102
|
+
return unless (dispatch_node = find_ancestor_method_dispatch_node(node))
|
103
|
+
return if node.respond_to?(:parenthesized?) && !node.parenthesized?
|
104
|
+
return unless last_expression?(dispatch_node) || method_dispatch_as_argument?(dispatch_node)
|
101
105
|
|
102
|
-
def_node = node.each_ancestor(:send, :csend).first
|
106
|
+
def_node = node.each_ancestor(:send, :csend, :super, :yield).first
|
103
107
|
|
104
|
-
def_node unless def_node && def_node.arguments.empty?
|
108
|
+
DefNode.new(def_node) unless def_node && def_node.arguments.empty?
|
105
109
|
end
|
110
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
106
111
|
|
107
|
-
def
|
108
|
-
ancestor = node.parent.parent
|
112
|
+
def find_ancestor_method_dispatch_node(node)
|
113
|
+
return unless (ancestor = node.parent.parent)
|
114
|
+
return unless ancestor.call_type? || ancestor.super_type? || ancestor.yield_type?
|
115
|
+
return if brackets?(ancestor)
|
109
116
|
|
110
|
-
ancestor
|
117
|
+
ancestor
|
111
118
|
end
|
112
119
|
|
113
|
-
def brackets?(
|
114
|
-
|
120
|
+
def brackets?(method_dispatch_node)
|
121
|
+
method_dispatch_node.method?(:[]) || method_dispatch_node.method?(:[]=)
|
115
122
|
end
|
116
123
|
|
117
124
|
def use_element_of_hash_literal_as_receiver?(ancestor, parent)
|
@@ -125,15 +132,16 @@ module RuboCop
|
|
125
132
|
ancestor.ancestors.any? { |node| node.respond_to?(:modifier_form?) && node.modifier_form? }
|
126
133
|
end
|
127
134
|
|
128
|
-
def
|
129
|
-
|
135
|
+
def last_expression?(ancestor)
|
136
|
+
ancestor.right_sibling ||
|
137
|
+
ancestor.each_ancestor.find { |node| node.assignment? || node.send_type? }&.right_sibling
|
138
|
+
end
|
130
139
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end&.right_sibling
|
140
|
+
def method_dispatch_as_argument?(method_dispatch_node)
|
141
|
+
parent = method_dispatch_node.parent
|
142
|
+
return false unless parent
|
135
143
|
|
136
|
-
|
144
|
+
parent.call_type? || parent.super_type? || parent.yield_type?
|
137
145
|
end
|
138
146
|
|
139
147
|
def breakdown_value_types_of_hash(hash_node)
|
@@ -189,6 +197,24 @@ module RuboCop
|
|
189
197
|
register_offense(pair_node, OMIT_HASH_VALUE_MSG, replacement)
|
190
198
|
end
|
191
199
|
end
|
200
|
+
|
201
|
+
DefNode = Struct.new(:node) do
|
202
|
+
def selector
|
203
|
+
if node.loc.respond_to?(:selector)
|
204
|
+
node.loc.selector
|
205
|
+
else
|
206
|
+
node.loc.keyword
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def first_argument
|
211
|
+
node.first_argument
|
212
|
+
end
|
213
|
+
|
214
|
+
def last_argument
|
215
|
+
node.last_argument
|
216
|
+
end
|
217
|
+
end
|
192
218
|
end
|
193
219
|
end
|
194
220
|
# rubocop:enable Metrics/ModuleLength
|
@@ -4,6 +4,8 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
# Help methods for determining if a line is too long.
|
6
6
|
module LineLengthHelp
|
7
|
+
include Alignment
|
8
|
+
|
7
9
|
private
|
8
10
|
|
9
11
|
def ignore_cop_directives?
|
@@ -85,7 +87,7 @@ module RuboCop
|
|
85
87
|
|
86
88
|
def tab_indentation_width
|
87
89
|
config.for_cop('Layout/IndentationStyle')['IndentationWidth'] ||
|
88
|
-
|
90
|
+
configured_indentation_width
|
89
91
|
end
|
90
92
|
|
91
93
|
def uri_regexp
|
@@ -107,9 +107,9 @@ module RuboCop
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
def empty_brackets?(left_bracket_token, right_bracket_token)
|
111
|
-
left_index =
|
112
|
-
right_index =
|
110
|
+
def empty_brackets?(left_bracket_token, right_bracket_token, tokens: processed_source.tokens)
|
111
|
+
left_index = tokens.index(left_bracket_token)
|
112
|
+
right_index = tokens.index(right_bracket_token)
|
113
113
|
right_index && left_index == right_index - 1
|
114
114
|
end
|
115
115
|
|
@@ -132,7 +132,7 @@ module RuboCop
|
|
132
132
|
|
133
133
|
def avoid_comma(kind, comma_begin_pos, extra_info)
|
134
134
|
range = range_between(comma_begin_pos, comma_begin_pos + 1)
|
135
|
-
article =
|
135
|
+
article = kind.include?('array') ? 'an' : 'a'
|
136
136
|
msg = format(
|
137
137
|
MSG,
|
138
138
|
command: 'Avoid',
|
data/lib/rubocop/cop/registry.rb
CHANGED
@@ -41,6 +41,11 @@ module RuboCop
|
|
41
41
|
@global = new
|
42
42
|
end
|
43
43
|
|
44
|
+
def self.qualified_cop?(name)
|
45
|
+
badge = Badge.parse(name)
|
46
|
+
global.qualify_badge(badge).first == badge
|
47
|
+
end
|
48
|
+
|
44
49
|
attr_reader :options
|
45
50
|
|
46
51
|
def initialize(cops = [], options = {})
|
@@ -158,6 +163,13 @@ module RuboCop
|
|
158
163
|
'RedundantCopDisableDirective'
|
159
164
|
end
|
160
165
|
|
166
|
+
def qualify_badge(badge)
|
167
|
+
clear_enrollment_queue
|
168
|
+
@departments
|
169
|
+
.map { |department, _| badge.with_department(department) }
|
170
|
+
.select { |potential_badge| registered?(potential_badge) }
|
171
|
+
end
|
172
|
+
|
161
173
|
# @return [Hash{String => Array<Class>}]
|
162
174
|
def to_h
|
163
175
|
clear_enrollment_queue
|
@@ -282,13 +294,6 @@ module RuboCop
|
|
282
294
|
self.class.new(cops)
|
283
295
|
end
|
284
296
|
|
285
|
-
def qualify_badge(badge)
|
286
|
-
clear_enrollment_queue
|
287
|
-
@departments
|
288
|
-
.map { |department, _| badge.with_department(department) }
|
289
|
-
.select { |potential_badge| registered?(potential_badge) }
|
290
|
-
end
|
291
|
-
|
292
297
|
def resolve_badge(given_badge, real_badge, source_path)
|
293
298
|
unless given_badge.match?(real_badge)
|
294
299
|
path = PathUtil.smart_path(source_path)
|
@@ -115,9 +115,7 @@ module RuboCop
|
|
115
115
|
def_node = find_corresponding_def_node(node)
|
116
116
|
return unless def_node
|
117
117
|
|
118
|
-
|
119
|
-
remove_node(corrector, node)
|
120
|
-
insert_def(corrector, node, def_node.source)
|
118
|
+
replace_def(corrector, node, def_node)
|
121
119
|
when :inline
|
122
120
|
remove_node(corrector, node)
|
123
121
|
select_grouped_def_nodes(node).each do |grouped_def_node|
|
@@ -131,7 +129,8 @@ module RuboCop
|
|
131
129
|
end
|
132
130
|
|
133
131
|
def offense?(node)
|
134
|
-
(group_style? && access_modifier_is_inlined?(node)
|
132
|
+
(group_style? && access_modifier_is_inlined?(node) &&
|
133
|
+
!right_siblings_same_inline_method?(node)) ||
|
135
134
|
(inline_style? && access_modifier_is_not_inlined?(node))
|
136
135
|
end
|
137
136
|
|
@@ -151,6 +150,12 @@ module RuboCop
|
|
151
150
|
!access_modifier_is_inlined?(node)
|
152
151
|
end
|
153
152
|
|
153
|
+
def right_siblings_same_inline_method?(node)
|
154
|
+
node.right_siblings.any? do |sibling|
|
155
|
+
sibling.send_type? && sibling.method?(node.method_name) && !sibling.arguments.empty?
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
154
159
|
def message(range)
|
155
160
|
access_modifier = range.source
|
156
161
|
|
@@ -173,7 +178,9 @@ module RuboCop
|
|
173
178
|
end
|
174
179
|
|
175
180
|
def find_argument_less_modifier_node(node)
|
176
|
-
node.parent
|
181
|
+
return unless (parent = node.parent)
|
182
|
+
|
183
|
+
parent.each_child_node(:send).find do |child|
|
177
184
|
child.method?(node.method_name) && child.arguments.empty?
|
178
185
|
end
|
179
186
|
end
|
@@ -184,17 +191,21 @@ module RuboCop
|
|
184
191
|
end.select(&:def_type?)
|
185
192
|
end
|
186
193
|
|
187
|
-
def
|
188
|
-
source =
|
194
|
+
def replace_def(corrector, node, def_node)
|
195
|
+
source = def_source(node, def_node)
|
189
196
|
argument_less_modifier_node = find_argument_less_modifier_node(node)
|
190
197
|
if argument_less_modifier_node
|
191
198
|
corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
|
199
|
+
elsif (ancestor = node.each_ancestor(:block, :class, :module).first)
|
200
|
+
|
201
|
+
corrector.insert_before(ancestor.loc.end, "#{node.method_name}\n\n#{source}\n")
|
192
202
|
else
|
193
|
-
corrector.
|
194
|
-
|
195
|
-
"#{node.method_name}\n\n#{source}\n"
|
196
|
-
)
|
203
|
+
corrector.replace(node, "#{node.method_name}\n\n#{source}")
|
204
|
+
return
|
197
205
|
end
|
206
|
+
|
207
|
+
remove_node(corrector, def_node)
|
208
|
+
remove_node(corrector, node)
|
198
209
|
end
|
199
210
|
|
200
211
|
def insert_inline_modifier(corrector, node, modifier_name)
|
@@ -204,6 +215,10 @@ module RuboCop
|
|
204
215
|
def remove_node(corrector, node)
|
205
216
|
corrector.remove(range_with_comments_and_lines(node))
|
206
217
|
end
|
218
|
+
|
219
|
+
def def_source(node, def_node)
|
220
|
+
[*processed_source.ast_with_comments[node].map(&:text), def_node.source].join("\n")
|
221
|
+
end
|
207
222
|
end
|
208
223
|
end
|
209
224
|
end
|
@@ -84,6 +84,7 @@ module RuboCop
|
|
84
84
|
def on_def(node)
|
85
85
|
return unless node.body
|
86
86
|
return unless (rest_args_name, args = use_rest_arguments?(node.arguments))
|
87
|
+
return if args.any?(&:default?)
|
87
88
|
|
88
89
|
node.each_descendant(:send) do |send_node|
|
89
90
|
kwargs_name, block_name = extract_argument_names_from(args)
|
@@ -299,8 +299,8 @@ module RuboCop
|
|
299
299
|
|
300
300
|
def move_comment_before_block(corrector, comment, block_node, closing_brace)
|
301
301
|
range = block_node.chained? ? end_of_chain(block_node.parent).source_range : closing_brace
|
302
|
-
|
303
|
-
corrector
|
302
|
+
corrector.remove(range_with_surrounding_space(comment.loc.expression, side: :right))
|
303
|
+
remove_trailing_whitespace(corrector, range, comment)
|
304
304
|
corrector.insert_after(range, "\n")
|
305
305
|
|
306
306
|
corrector.insert_before(block_node, "#{comment.text}\n")
|
@@ -313,6 +313,12 @@ module RuboCop
|
|
313
313
|
end_of_chain(node.parent)
|
314
314
|
end
|
315
315
|
|
316
|
+
def remove_trailing_whitespace(corrector, range, comment)
|
317
|
+
range_of_trailing = range.end.join(comment.loc.expression.begin)
|
318
|
+
|
319
|
+
corrector.remove(range_of_trailing) if range_of_trailing.source.match?(/\A\s+\z/)
|
320
|
+
end
|
321
|
+
|
316
322
|
def with_block?(node)
|
317
323
|
node.respond_to?(:block_node) && node.block_node
|
318
324
|
end
|
@@ -31,6 +31,7 @@ module RuboCop
|
|
31
31
|
#
|
32
32
|
# The compact style is only forced for classes/modules with one child.
|
33
33
|
class ClassAndModuleChildren < Base
|
34
|
+
include Alignment
|
34
35
|
include ConfigurableEnforcedStyle
|
35
36
|
include RangeHelp
|
36
37
|
extend AutoCorrector
|
@@ -59,7 +60,7 @@ module RuboCop
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def nest_definition(corrector, node)
|
62
|
-
padding = (
|
63
|
+
padding = indentation(node) + leading_spaces(node)
|
63
64
|
padding_for_trailing_end = padding.sub(' ' * node.loc.end.column, '')
|
64
65
|
|
65
66
|
replace_namespace_keyword(corrector, node)
|
@@ -124,10 +125,6 @@ module RuboCop
|
|
124
125
|
corrector.remove(range)
|
125
126
|
end
|
126
127
|
|
127
|
-
def configured_indentation_width
|
128
|
-
config.for_badge(Layout::IndentationWidth.badge).fetch('Width', 2)
|
129
|
-
end
|
130
|
-
|
131
128
|
def unindent(corrector, node)
|
132
129
|
return if node.body.children.last.nil?
|
133
130
|
|
@@ -141,10 +138,6 @@ module RuboCop
|
|
141
138
|
node.source_range.source_line[/\A\s*/]
|
142
139
|
end
|
143
140
|
|
144
|
-
def indent_width
|
145
|
-
@config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
146
|
-
end
|
147
|
-
|
148
141
|
def check_style(node, body)
|
149
142
|
return if node.identifier.children[0]&.cbase_type?
|
150
143
|
|
@@ -185,7 +178,7 @@ module RuboCop
|
|
185
178
|
end
|
186
179
|
|
187
180
|
def compact_node_name?(node)
|
188
|
-
|
181
|
+
node.identifier.source.include?('::')
|
189
182
|
end
|
190
183
|
end
|
191
184
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Enforces the use of `Comparable#clamp` instead of comparison by minimum and maximum.
|
7
|
+
#
|
8
|
+
# This cop supports autocorrection for `if/elsif/else` bad style only.
|
9
|
+
# Because `ArgumentError` occurs if the minimum and maximum of `clamp` arguments are reversed.
|
10
|
+
# When these are variables, it is not possible to determine which is the minimum and maximum:
|
11
|
+
#
|
12
|
+
# [source,ruby]
|
13
|
+
# ----
|
14
|
+
# [1, [2, 3].max].min # => 1
|
15
|
+
# 1.clamp(3, 1) # => min argument must be smaller than max argument (ArgumentError)
|
16
|
+
# ----
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# [[x, low].max, high].min
|
22
|
+
#
|
23
|
+
# # bad
|
24
|
+
# if x < low
|
25
|
+
# low
|
26
|
+
# elsif high < x
|
27
|
+
# high
|
28
|
+
# else
|
29
|
+
# x
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # good
|
33
|
+
# x.clamp(low, high)
|
34
|
+
#
|
35
|
+
class ComparableClamp < Base
|
36
|
+
include Alignment
|
37
|
+
extend AutoCorrector
|
38
|
+
extend TargetRubyVersion
|
39
|
+
|
40
|
+
minimum_target_ruby_version 2.4
|
41
|
+
|
42
|
+
MSG = 'Use `%<prefer>s` instead of `if/elsif/else`.'
|
43
|
+
MSG_MIN_MAX = 'Use `Comparable#clamp` instead.'
|
44
|
+
RESTRICT_ON_SEND = %i[min max].freeze
|
45
|
+
|
46
|
+
# @!method if_elsif_else_condition?(node)
|
47
|
+
def_node_matcher :if_elsif_else_condition?, <<~PATTERN
|
48
|
+
{
|
49
|
+
(if (send _x :< _min) _min (if (send _max :< _x) _max _x))
|
50
|
+
(if (send _min :> _x) _min (if (send _max :< _x) _max _x))
|
51
|
+
(if (send _x :< _min) _min (if (send _x :> _max) _max _x))
|
52
|
+
(if (send _min :> _x) _min (if (send _x :> _max) _max _x))
|
53
|
+
(if (send _max :< _x) _max (if (send _x :< _min) _min _x))
|
54
|
+
(if (send _x :> _max) _max (if (send _x :< _min) _min _x))
|
55
|
+
(if (send _max :< _x) _max (if (send _min :> _x) _min _x))
|
56
|
+
(if (send _x :> _max) _max (if (send _min :> _x) _min _x))
|
57
|
+
}
|
58
|
+
PATTERN
|
59
|
+
|
60
|
+
# @!method array_min_max?(node)
|
61
|
+
def_node_matcher :array_min_max?, <<~PATTERN
|
62
|
+
{
|
63
|
+
(send
|
64
|
+
(array
|
65
|
+
(send (array _ _) :max) _) :min)
|
66
|
+
(send
|
67
|
+
(array
|
68
|
+
_ (send (array _ _) :max)) :min)
|
69
|
+
(send
|
70
|
+
(array
|
71
|
+
(send (array _ _) :min) _) :max)
|
72
|
+
(send
|
73
|
+
(array
|
74
|
+
_ (send (array _ _) :min)) :max)
|
75
|
+
}
|
76
|
+
PATTERN
|
77
|
+
|
78
|
+
def on_if(node)
|
79
|
+
return unless if_elsif_else_condition?(node)
|
80
|
+
|
81
|
+
if_body, elsif_body, else_body = *node.branches
|
82
|
+
|
83
|
+
else_body_source = else_body.source
|
84
|
+
|
85
|
+
if min_condition?(node.condition, else_body_source)
|
86
|
+
min = if_body.source
|
87
|
+
max = elsif_body.source
|
88
|
+
else
|
89
|
+
min = elsif_body.source
|
90
|
+
max = if_body.source
|
91
|
+
end
|
92
|
+
|
93
|
+
prefer = "#{else_body_source}.clamp(#{min}, #{max})"
|
94
|
+
|
95
|
+
add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
|
96
|
+
autocorrect(corrector, node, prefer)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def on_send(node)
|
101
|
+
return unless array_min_max?(node)
|
102
|
+
|
103
|
+
add_offense(node, message: MSG_MIN_MAX)
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def autocorrect(corrector, node, prefer)
|
109
|
+
if node.elsif?
|
110
|
+
corrector.insert_before(node, "else\n")
|
111
|
+
corrector.replace(node, "#{indentation(node)}#{prefer}")
|
112
|
+
else
|
113
|
+
corrector.replace(node, prefer)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def min_condition?(if_condition, else_body)
|
118
|
+
lhs, op, rhs = *if_condition
|
119
|
+
|
120
|
+
(lhs.source == else_body && op == :<) || (rhs.source == else_body && op == :>)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -218,11 +218,9 @@ module RuboCop
|
|
218
218
|
VARIABLE_ASSIGNMENT_TYPES = %i[casgn cvasgn gvasgn ivasgn lvasgn].freeze
|
219
219
|
ASSIGNMENT_TYPES = VARIABLE_ASSIGNMENT_TYPES + %i[and_asgn or_asgn op_asgn masgn].freeze
|
220
220
|
LINE_LENGTH = 'Layout/LineLength'
|
221
|
-
INDENTATION_WIDTH = 'Layout/IndentationWidth'
|
222
221
|
ENABLED = 'Enabled'
|
223
222
|
MAX = 'Max'
|
224
223
|
SINGLE_LINE_CONDITIONS_ONLY = 'SingleLineConditionsOnly'
|
225
|
-
WIDTH = 'Width'
|
226
224
|
|
227
225
|
# The shovel operator `<<` does not have its own type. It is a `send`
|
228
226
|
# type.
|
@@ -428,10 +426,6 @@ module RuboCop
|
|
428
426
|
config.for_cop(LINE_LENGTH)[MAX]
|
429
427
|
end
|
430
428
|
|
431
|
-
def indentation_width
|
432
|
-
config.for_cop(INDENTATION_WIDTH)[WIDTH] || 2
|
433
|
-
end
|
434
|
-
|
435
429
|
def single_line_conditions_only?
|
436
430
|
cop_config[SINGLE_LINE_CONDITIONS_ONLY]
|
437
431
|
end
|
@@ -7,6 +7,10 @@ module RuboCop
|
|
7
7
|
# It can optionally be configured to also require documentation for
|
8
8
|
# non-public methods.
|
9
9
|
#
|
10
|
+
# NOTE: This cop allows `initialize` method because `initialize` is
|
11
|
+
# a special method called from `new`. In some programming languages
|
12
|
+
# they are called constructor to distinguish it from method.
|
13
|
+
#
|
10
14
|
# @example
|
11
15
|
#
|
12
16
|
# # bad
|
@@ -103,6 +107,8 @@ module RuboCop
|
|
103
107
|
PATTERN
|
104
108
|
|
105
109
|
def on_def(node)
|
110
|
+
return if node.method?(:initialize)
|
111
|
+
|
106
112
|
parent = node.parent
|
107
113
|
module_function_node?(parent) ? check(parent) : check(node)
|
108
114
|
end
|
@@ -21,6 +21,7 @@ module RuboCop
|
|
21
21
|
# work
|
22
22
|
# end
|
23
23
|
class InfiniteLoop < Base
|
24
|
+
include Alignment
|
24
25
|
extend AutoCorrector
|
25
26
|
|
26
27
|
LEADING_SPACE = /\A(\s*)/.freeze
|
@@ -106,7 +107,7 @@ module RuboCop
|
|
106
107
|
else
|
107
108
|
indentation = body.source_range.source_line[LEADING_SPACE]
|
108
109
|
|
109
|
-
['loop do', body.source.gsub(/^/,
|
110
|
+
['loop do', body.source.gsub(/^/, indentation(node)), 'end'].join("\n#{indentation}")
|
110
111
|
end
|
111
112
|
end
|
112
113
|
|
@@ -120,10 +121,6 @@ module RuboCop
|
|
120
121
|
|
121
122
|
start_range.join(end_range)
|
122
123
|
end
|
123
|
-
|
124
|
-
def configured_indent
|
125
|
-
' ' * config.for_cop('Layout/IndentationWidth')['Width']
|
126
|
-
end
|
127
124
|
end
|
128
125
|
end
|
129
126
|
end
|