rubocop 1.79.2 → 1.82.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/README.md +1 -1
- data/config/default.yml +35 -7
- data/config/obsoletion.yml +4 -0
- data/exe/rubocop +1 -8
- data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
- data/lib/rubocop/cli.rb +8 -3
- data/lib/rubocop/comment_config.rb +62 -17
- data/lib/rubocop/config_loader.rb +5 -2
- data/lib/rubocop/config_loader_resolver.rb +7 -6
- data/lib/rubocop/config_store.rb +5 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +6 -4
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +8 -7
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -4
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +16 -5
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
- data/lib/rubocop/cop/lint/debugger.rb +0 -2
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/else_layout.rb +19 -0
- data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
- data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +17 -8
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +15 -6
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/useless_or.rb +15 -2
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +7 -0
- data/lib/rubocop/cop/message_annotator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +0 -4
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
- data/lib/rubocop/cop/mixin/trailing_comma.rb +5 -6
- data/lib/rubocop/cop/naming/method_name.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_method.rb +19 -6
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/style/array_intersect.rb +46 -12
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
- data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
- data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
- data/lib/rubocop/cop/style/case_equality.rb +11 -13
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
- data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +0 -6
- data/lib/rubocop/cop/style/endless_method.rb +15 -2
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/float_division.rb +15 -1
- data/lib/rubocop/cop/style/guard_clause.rb +0 -11
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
- data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +0 -4
- data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
- data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
- data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +34 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +26 -5
- data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -11
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
- data/lib/rubocop/cop/style/safe_navigation.rb +18 -1
- data/lib/rubocop/cop/style/semicolon.rb +23 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
- data/lib/rubocop/cop/style/super_arguments.rb +2 -2
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/util.rb +2 -3
- data/lib/rubocop/cop/utils/format_string.rb +10 -0
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +9 -7
- data/lib/rubocop/cops_documentation_generator.rb +4 -4
- data/lib/rubocop/directive_comment.rb +46 -3
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -5
- data/lib/rubocop/lsp/diagnostic.rb +10 -14
- data/lib/rubocop/lsp/routes.rb +31 -2
- data/lib/rubocop/lsp/stdin_runner.rb +0 -16
- data/lib/rubocop/magic_comment.rb +20 -0
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +7 -8
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/rspec/support.rb +1 -1
- data/lib/rubocop/runner.rb +6 -4
- data/lib/rubocop/target_finder.rb +9 -9
- data/lib/rubocop/target_ruby.rb +11 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -0
- data/lib/ruby_lsp/rubocop/addon.rb +23 -8
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
- metadata +8 -6
|
@@ -142,6 +142,7 @@ module RuboCop
|
|
|
142
142
|
# @!method strip_begin(node)
|
|
143
143
|
def_node_matcher :strip_begin, '{ (begin $!begin) $!(begin) }'
|
|
144
144
|
|
|
145
|
+
# rubocop:disable Metrics/AbcSize
|
|
145
146
|
def on_if(node)
|
|
146
147
|
return if allowed_if_condition?(node)
|
|
147
148
|
|
|
@@ -155,9 +156,11 @@ module RuboCop
|
|
|
155
156
|
removal_ranges = [begin_range(node, body), end_range(node, body)]
|
|
156
157
|
|
|
157
158
|
report_offense(node, method_chain, method_call, *removal_ranges) do |corrector|
|
|
159
|
+
corrector.replace(receiver, checked_variable.source) if checked_variable.csend_type?
|
|
158
160
|
corrector.insert_before(method_call.loc.dot, '&') unless method_call.safe_navigation?
|
|
159
161
|
end
|
|
160
162
|
end
|
|
163
|
+
# rubocop:enable Metrics/AbcSize
|
|
161
164
|
|
|
162
165
|
def on_and(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
163
166
|
collect_and_clauses(node).each do |(lhs, lhs_operator_range), (rhs, _rhs_operator_range)|
|
|
@@ -259,8 +262,14 @@ module RuboCop
|
|
|
259
262
|
end
|
|
260
263
|
|
|
261
264
|
def dotless_operator_call?(method_call)
|
|
265
|
+
return true if dotless_operator_method?(method_call)
|
|
266
|
+
|
|
262
267
|
method_call = method_call.parent while method_call.parent.send_type?
|
|
263
268
|
|
|
269
|
+
dotless_operator_method?(method_call)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def dotless_operator_method?(method_call)
|
|
264
273
|
return false if method_call.loc.dot
|
|
265
274
|
|
|
266
275
|
method_call.method?(:[]) || method_call.method?(:[]=) || method_call.operator_method?
|
|
@@ -335,8 +344,16 @@ module RuboCop
|
|
|
335
344
|
|
|
336
345
|
def matching_call_nodes?(left, right)
|
|
337
346
|
return false unless left && right.respond_to?(:call_type?)
|
|
347
|
+
return false unless left.call_type? && right.call_type?
|
|
348
|
+
|
|
349
|
+
# Compare receiver and method name, but ignore the difference between
|
|
350
|
+
# safe navigation method call (`&.`) and dot method call (`.`).
|
|
351
|
+
left_receiver, left_method, *left_args = left.children
|
|
352
|
+
right_receiver, right_method, *right_args = right.children
|
|
338
353
|
|
|
339
|
-
|
|
354
|
+
left_method == right_method &&
|
|
355
|
+
matching_nodes?(left_receiver, right_receiver) &&
|
|
356
|
+
left_args == right_args
|
|
340
357
|
end
|
|
341
358
|
|
|
342
359
|
def chain_length(method_chain, method)
|
|
@@ -69,10 +69,11 @@ module RuboCop
|
|
|
69
69
|
|
|
70
70
|
def each_semicolon
|
|
71
71
|
tokens_for_lines.each do |line, tokens|
|
|
72
|
-
semicolon_pos = semicolon_position(tokens)
|
|
72
|
+
next unless (semicolon_pos = semicolon_position(tokens))
|
|
73
|
+
|
|
73
74
|
after_expr_pos = semicolon_pos == -1 ? -2 : semicolon_pos
|
|
74
75
|
|
|
75
|
-
yield line, tokens[semicolon_pos].column, tokens[after_expr_pos]
|
|
76
|
+
yield line, tokens[semicolon_pos].column, tokens[after_expr_pos]
|
|
76
77
|
end
|
|
77
78
|
end
|
|
78
79
|
|
|
@@ -119,6 +120,7 @@ module RuboCop
|
|
|
119
120
|
tokens[1]&.type == :tSTRING_DBEG && tokens[2]&.semicolon?
|
|
120
121
|
end
|
|
121
122
|
|
|
123
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
122
124
|
def register_semicolon(line, column, after_expression, token_before_semicolon = nil)
|
|
123
125
|
range = source_range(processed_source.buffer, line, column)
|
|
124
126
|
|
|
@@ -130,14 +132,19 @@ module RuboCop
|
|
|
130
132
|
# without parentheses.
|
|
131
133
|
# See: https://github.com/rubocop/rubocop/issues/10791
|
|
132
134
|
if token_before_semicolon&.regexp_dots?
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
node = find_node(range_nodes, token_before_semicolon)
|
|
136
|
+
elsif token_before_semicolon&.type == :tLABEL
|
|
137
|
+
node = find_node(value_omission_pair_nodes, token_before_semicolon).parent
|
|
138
|
+
space = node.parent.loc.selector.end.join(node.source_range.begin)
|
|
139
|
+
corrector.remove(space)
|
|
135
140
|
end
|
|
136
141
|
|
|
142
|
+
corrector.wrap(node, '(', ')') if node
|
|
137
143
|
corrector.remove(range)
|
|
138
144
|
end
|
|
139
145
|
end
|
|
140
146
|
end
|
|
147
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
141
148
|
|
|
142
149
|
def expressions_per_line(exprs)
|
|
143
150
|
# create a map matching lines to the number of expressions on them
|
|
@@ -153,9 +160,9 @@ module RuboCop
|
|
|
153
160
|
end
|
|
154
161
|
end
|
|
155
162
|
|
|
156
|
-
def
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
def find_node(nodes, token_before_semicolon)
|
|
164
|
+
nodes.detect do |node|
|
|
165
|
+
node.source_range.overlaps?(token_before_semicolon.pos)
|
|
159
166
|
end
|
|
160
167
|
end
|
|
161
168
|
|
|
@@ -166,6 +173,15 @@ module RuboCop
|
|
|
166
173
|
@range_nodes = ast.range_type? ? [ast] : []
|
|
167
174
|
@range_nodes.concat(ast.each_descendant(:range).to_a)
|
|
168
175
|
end
|
|
176
|
+
|
|
177
|
+
def value_omission_pair_nodes
|
|
178
|
+
if instance_variable_defined?(:@value_omission_pair_nodes)
|
|
179
|
+
return @value_omission_pair_nodes
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
ast = processed_source.ast
|
|
183
|
+
@value_omission_pair_nodes = ast.each_descendant(:pair).to_a.select(&:value_omission?)
|
|
184
|
+
end
|
|
169
185
|
end
|
|
170
186
|
end
|
|
171
187
|
end
|
|
@@ -129,6 +129,7 @@ module RuboCop
|
|
|
129
129
|
corrector.remove(range_with_surrounding_space(range, newlines: false))
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
+
# rubocop:disable Metrics/AbcSize
|
|
132
133
|
def correct_for_basic_condition_style(corrector, node, if_branch)
|
|
133
134
|
range = range_between(
|
|
134
135
|
node.condition.source_range.end_pos, if_branch.condition.source_range.begin_pos
|
|
@@ -137,8 +138,14 @@ module RuboCop
|
|
|
137
138
|
|
|
138
139
|
corrector.replace(if_branch.condition, chainable_condition(if_branch))
|
|
139
140
|
|
|
140
|
-
|
|
141
|
+
end_range = if same_line?(node.loc.end, node.if_branch.loc.end)
|
|
142
|
+
node.loc.end
|
|
143
|
+
else
|
|
144
|
+
range_by_whole_lines(node.loc.end, include_final_newline: true)
|
|
145
|
+
end
|
|
146
|
+
corrector.remove(end_range)
|
|
141
147
|
end
|
|
148
|
+
# rubocop:enable Metrics/AbcSize
|
|
142
149
|
|
|
143
150
|
def autocorrect_outer_condition_modify_form(corrector, node, if_branch)
|
|
144
151
|
correct_node(corrector, if_branch)
|
|
@@ -100,7 +100,7 @@ module RuboCop
|
|
|
100
100
|
node.receiver.str_type? &&
|
|
101
101
|
node.first_argument.str_type? &&
|
|
102
102
|
node.multiline? &&
|
|
103
|
-
node.source
|
|
103
|
+
node.source.match?(/\+\s*\n/)
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def find_topmost_plus_node(node)
|
|
@@ -141,22 +141,26 @@ module RuboCop
|
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
def replacement(parts)
|
|
144
|
-
interpolated_parts = parts.map
|
|
145
|
-
case part.type
|
|
146
|
-
when :str
|
|
147
|
-
adjust_str(part)
|
|
148
|
-
when :dstr
|
|
149
|
-
part.children.all?(&:str_type?) ? adjust_str(part) : part.value
|
|
150
|
-
else
|
|
151
|
-
"\#{#{part.source}}"
|
|
152
|
-
end
|
|
153
|
-
end
|
|
144
|
+
interpolated_parts = parts.map { |part| adjust_str(part) }
|
|
154
145
|
|
|
155
146
|
"\"#{handle_quotes(interpolated_parts).join}\""
|
|
156
147
|
end
|
|
157
148
|
|
|
158
|
-
def adjust_str(
|
|
159
|
-
|
|
149
|
+
def adjust_str(part)
|
|
150
|
+
case part.type
|
|
151
|
+
when :str
|
|
152
|
+
if single_quoted?(part)
|
|
153
|
+
part.value.gsub(/(\\|"|#\{|#@|#\$)/, '\\\\\&')
|
|
154
|
+
else
|
|
155
|
+
part.value.inspect[1..-2]
|
|
156
|
+
end
|
|
157
|
+
when :dstr, :begin
|
|
158
|
+
part.children.map do |child|
|
|
159
|
+
adjust_str(child)
|
|
160
|
+
end.join
|
|
161
|
+
else
|
|
162
|
+
"\#{#{part.source}}"
|
|
163
|
+
end
|
|
160
164
|
end
|
|
161
165
|
|
|
162
166
|
def handle_quotes(parts)
|
|
@@ -109,7 +109,7 @@ module RuboCop
|
|
|
109
109
|
|
|
110
110
|
def_args.zip(super_args).each do |def_arg, super_arg|
|
|
111
111
|
next if positional_arg_same?(def_arg, super_arg)
|
|
112
|
-
next if positional_rest_arg_same(def_arg, super_arg)
|
|
112
|
+
next if positional_rest_arg_same?(def_arg, super_arg)
|
|
113
113
|
next if keyword_arg_same?(def_arg, super_arg)
|
|
114
114
|
next if keyword_rest_arg_same?(def_arg, super_arg)
|
|
115
115
|
next if block_arg_same?(def_node, super_node, def_arg, super_arg)
|
|
@@ -147,7 +147,7 @@ module RuboCop
|
|
|
147
147
|
def_arg.name == super_arg.children.first
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
-
def positional_rest_arg_same(def_arg, super_arg)
|
|
150
|
+
def positional_rest_arg_same?(def_arg, super_arg)
|
|
151
151
|
return false unless def_arg.restarg_type?
|
|
152
152
|
# anonymous forwarding
|
|
153
153
|
return true if def_arg.name.nil? && super_arg.forwarded_restarg_type?
|
|
@@ -81,7 +81,7 @@ module RuboCop
|
|
|
81
81
|
|
|
82
82
|
content = *sym
|
|
83
83
|
content = content.map { |c| c.is_a?(AST::Node) ? c.source : c }.join
|
|
84
|
-
content_without_delimiter_pairs = content.gsub(/(\[[^\s\[\]]*\])|(\([^\s
|
|
84
|
+
content_without_delimiter_pairs = content.gsub(/(\[[^\s\[\]]*\])|(\([^\s()]*\))/, '')
|
|
85
85
|
|
|
86
86
|
content.include?(' ') || DELIMITERS.any? do |delimiter|
|
|
87
87
|
content_without_delimiter_pairs.include?(delimiter)
|
|
@@ -10,6 +10,9 @@ module RuboCop
|
|
|
10
10
|
# for all parenthesized multi-line method calls with arguments.
|
|
11
11
|
# * `comma`: Requires a comma after the last argument, but only for
|
|
12
12
|
# parenthesized method calls where each argument is on its own line.
|
|
13
|
+
# * `diff_comma`: Requires a comma after the last argument, but only
|
|
14
|
+
# when that argument is followed by an immediate newline, even if
|
|
15
|
+
# there is an inline comment on the same line.
|
|
13
16
|
# * `no_comma`: Requires that there is no comma after the last
|
|
14
17
|
# argument.
|
|
15
18
|
#
|
|
@@ -75,6 +78,48 @@ module RuboCop
|
|
|
75
78
|
# 2,
|
|
76
79
|
# )
|
|
77
80
|
#
|
|
81
|
+
# @example EnforcedStyleForMultiline: diff_comma
|
|
82
|
+
# # bad
|
|
83
|
+
# method(1, 2,)
|
|
84
|
+
#
|
|
85
|
+
# # good
|
|
86
|
+
# method(1, 2)
|
|
87
|
+
#
|
|
88
|
+
# # good
|
|
89
|
+
# method(
|
|
90
|
+
# 1, 2,
|
|
91
|
+
# 3,
|
|
92
|
+
# )
|
|
93
|
+
#
|
|
94
|
+
# # good
|
|
95
|
+
# method(
|
|
96
|
+
# 1, 2, 3,
|
|
97
|
+
# )
|
|
98
|
+
#
|
|
99
|
+
# # good
|
|
100
|
+
# method(
|
|
101
|
+
# 1,
|
|
102
|
+
# 2,
|
|
103
|
+
# )
|
|
104
|
+
#
|
|
105
|
+
# # bad
|
|
106
|
+
# method(1, [
|
|
107
|
+
# 2,
|
|
108
|
+
# ],)
|
|
109
|
+
#
|
|
110
|
+
# # good
|
|
111
|
+
# method(1, [
|
|
112
|
+
# 2,
|
|
113
|
+
# ])
|
|
114
|
+
#
|
|
115
|
+
# # bad
|
|
116
|
+
# object[1, 2,
|
|
117
|
+
# 3, 4,]
|
|
118
|
+
#
|
|
119
|
+
# # good
|
|
120
|
+
# object[1, 2,
|
|
121
|
+
# 3, 4]
|
|
122
|
+
#
|
|
78
123
|
# @example EnforcedStyleForMultiline: no_comma (default)
|
|
79
124
|
# # bad
|
|
80
125
|
# method(1, 2,)
|
|
@@ -7,26 +7,26 @@ module RuboCop
|
|
|
7
7
|
#
|
|
8
8
|
# @example
|
|
9
9
|
# # bad
|
|
10
|
-
# a, b, _ = foo
|
|
11
|
-
# a, b, _, = foo
|
|
12
|
-
# a, _, _ = foo
|
|
13
|
-
# a, _, _, = foo
|
|
10
|
+
# a, b, _ = foo
|
|
11
|
+
# a, b, _, = foo
|
|
12
|
+
# a, _, _ = foo
|
|
13
|
+
# a, _, _, = foo
|
|
14
14
|
#
|
|
15
15
|
# # good
|
|
16
|
-
# a, b, = foo
|
|
17
|
-
# a, = foo
|
|
18
|
-
# *a, b, _ = foo
|
|
16
|
+
# a, b, = foo
|
|
17
|
+
# a, = foo
|
|
18
|
+
# *a, b, _ = foo
|
|
19
19
|
# # => We need to know to not include 2 variables in a
|
|
20
|
-
# a, *b, _ = foo
|
|
21
|
-
# # => The correction `a, *b, = foo
|
|
20
|
+
# a, *b, _ = foo
|
|
21
|
+
# # => The correction `a, *b, = foo` is a syntax error
|
|
22
22
|
#
|
|
23
23
|
# @example AllowNamedUnderscoreVariables: true (default)
|
|
24
24
|
# # good
|
|
25
|
-
# a, b, _something = foo
|
|
25
|
+
# a, b, _something = foo
|
|
26
26
|
#
|
|
27
27
|
# @example AllowNamedUnderscoreVariables: false
|
|
28
28
|
# # bad
|
|
29
|
-
# a, b, _something = foo
|
|
29
|
+
# a, b, _something = foo
|
|
30
30
|
#
|
|
31
31
|
class TrailingUnderscoreVariable < Base
|
|
32
32
|
include SurroundingSpace
|
|
@@ -20,7 +20,6 @@ module RuboCop
|
|
|
20
20
|
# # do a different thing...
|
|
21
21
|
# end
|
|
22
22
|
class UnlessElse < Base
|
|
23
|
-
include RangeHelp
|
|
24
23
|
extend AutoCorrector
|
|
25
24
|
|
|
26
25
|
MSG = 'Do not use `unless` with `else`. Rewrite these with the positive case first.'
|
|
@@ -29,25 +28,27 @@ module RuboCop
|
|
|
29
28
|
return unless node.unless? && node.else?
|
|
30
29
|
|
|
31
30
|
add_offense(node) do |corrector|
|
|
32
|
-
body_range = range_between_condition_and_else(node, node.condition)
|
|
33
|
-
else_range = range_between_else_and_end(node)
|
|
34
|
-
|
|
35
31
|
next if part_of_ignored_node?(node)
|
|
36
32
|
|
|
37
33
|
corrector.replace(node.loc.keyword, 'if')
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
|
|
35
|
+
body_range = range_between_condition_and_else(node)
|
|
36
|
+
else_range = range_between_else_and_end(node)
|
|
37
|
+
|
|
38
|
+
corrector.swap(body_range, else_range)
|
|
40
39
|
end
|
|
41
40
|
|
|
42
41
|
ignore_node(node)
|
|
43
42
|
end
|
|
44
43
|
|
|
45
|
-
def range_between_condition_and_else(node
|
|
46
|
-
|
|
44
|
+
def range_between_condition_and_else(node)
|
|
45
|
+
range = node.loc.begin ? node.loc.begin.end : node.condition.source_range
|
|
46
|
+
|
|
47
|
+
range.end.join(node.loc.else.begin)
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
def range_between_else_and_end(node)
|
|
50
|
-
|
|
51
|
+
node.loc.else.end.join(node.loc.end.begin)
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
end
|
data/lib/rubocop/cop/util.rb
CHANGED
|
@@ -117,10 +117,9 @@ module RuboCop
|
|
|
117
117
|
# with calls chained to the end of it.
|
|
118
118
|
def first_part_of_call_chain(node)
|
|
119
119
|
while node
|
|
120
|
-
|
|
121
|
-
when :send
|
|
120
|
+
if node.call_type?
|
|
122
121
|
node = node.receiver
|
|
123
|
-
|
|
122
|
+
elsif node.any_block_type?
|
|
124
123
|
node = node.send_node
|
|
125
124
|
else
|
|
126
125
|
break
|
|
@@ -71,6 +71,16 @@ module RuboCop
|
|
|
71
71
|
name && @source.include?('{')
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
def variable_width?
|
|
75
|
+
!!width&.start_with?('*')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def variable_width_argument_number
|
|
79
|
+
return unless variable_width?
|
|
80
|
+
|
|
81
|
+
width == '*' ? 1 : width.match(DIGIT_DOLLAR)['arg_number'].to_i
|
|
82
|
+
end
|
|
83
|
+
|
|
74
84
|
# Number of arguments required for the format sequence
|
|
75
85
|
def arity
|
|
76
86
|
@source.scan('*').count + 1
|
|
@@ -238,11 +238,16 @@ module RuboCop
|
|
|
238
238
|
end
|
|
239
239
|
|
|
240
240
|
def process_loop(node)
|
|
241
|
-
if
|
|
241
|
+
if node.post_condition_loop?
|
|
242
242
|
# See the comment at the end of file for this behavior.
|
|
243
243
|
condition_node, body_node = *node
|
|
244
244
|
process_node(body_node)
|
|
245
245
|
process_node(condition_node)
|
|
246
|
+
elsif node.for_type?
|
|
247
|
+
# In `for item in items` the rightmost expression is evaluated first.
|
|
248
|
+
process_node(node.collection)
|
|
249
|
+
process_node(node.variable)
|
|
250
|
+
process_node(node.body) if node.body
|
|
246
251
|
else
|
|
247
252
|
process_children(node)
|
|
248
253
|
end
|
|
@@ -356,17 +361,14 @@ module RuboCop
|
|
|
356
361
|
end
|
|
357
362
|
|
|
358
363
|
def reference_assignments(loop_assignments, loop_node)
|
|
359
|
-
node = loop_assignments.first.node
|
|
360
|
-
|
|
361
364
|
# If inside a branching statement, mark all as referenced.
|
|
362
365
|
# Otherwise, mark only the last assignment as referenced.
|
|
363
366
|
# Note that `rescue` must be considered as branching because of
|
|
364
367
|
# the `retry` keyword.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
else
|
|
368
|
-
loop_assignments.last&.reference!(loop_node)
|
|
368
|
+
loop_assignments.each do |assignment|
|
|
369
|
+
assignment.reference!(loop_node) if assignment.node.each_ancestor(*BRANCH_NODES).any?
|
|
369
370
|
end
|
|
371
|
+
loop_assignments.last&.reference!(loop_node)
|
|
370
372
|
end
|
|
371
373
|
|
|
372
374
|
def scanned_node?(node)
|
|
@@ -194,10 +194,10 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
194
194
|
|
|
195
195
|
def configurations(department, cop, cop_config)
|
|
196
196
|
header = ['Name', 'Default value', 'Configurable values']
|
|
197
|
-
configs = cop_config
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
configs = cop_config.each_key.reject do |key|
|
|
198
|
+
key == 'AllowMultipleStyles' ||
|
|
199
|
+
(key != 'SupportedTypes' && key.start_with?('Supported'))
|
|
200
|
+
end
|
|
201
201
|
return '' if configs.empty?
|
|
202
202
|
|
|
203
203
|
content = configs.map do |name|
|
|
@@ -14,11 +14,17 @@ module RuboCop
|
|
|
14
14
|
# @api private
|
|
15
15
|
COP_NAME_PATTERN = '([A-Za-z]\w+/)*(?:[A-Za-z]\w+)'
|
|
16
16
|
# @api private
|
|
17
|
+
COP_NAME_PATTERN_NC = '(?:[A-Za-z]\w+/)*[A-Za-z]\w+'
|
|
18
|
+
# @api private
|
|
19
|
+
COP_NAMES_PATTERN_NC = "(?:#{COP_NAME_PATTERN_NC} , )*#{COP_NAME_PATTERN_NC}"
|
|
20
|
+
# @api private
|
|
17
21
|
COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
|
|
18
22
|
# @api private
|
|
19
23
|
COPS_PATTERN = "(all|#{COP_NAMES_PATTERN})"
|
|
20
24
|
# @api private
|
|
21
|
-
|
|
25
|
+
PUSH_POP_ARGS_PATTERN = "([+\\-]#{COP_NAME_PATTERN_NC}(?:\\s+[+\\-]#{COP_NAME_PATTERN_NC})*)"
|
|
26
|
+
# @api private
|
|
27
|
+
AVAILABLE_MODES = %w[disable enable todo push pop].freeze
|
|
22
28
|
# @api private
|
|
23
29
|
DIRECTIVE_MARKER_PATTERN = '# rubocop : '
|
|
24
30
|
# @api private
|
|
@@ -27,7 +33,7 @@ module RuboCop
|
|
|
27
33
|
DIRECTIVE_HEADER_PATTERN = "#{DIRECTIVE_MARKER_PATTERN}((?:#{AVAILABLE_MODES.join('|')}))\\b"
|
|
28
34
|
# @api private
|
|
29
35
|
DIRECTIVE_COMMENT_REGEXP = Regexp.new(
|
|
30
|
-
"#{DIRECTIVE_HEADER_PATTERN}
|
|
36
|
+
"#{DIRECTIVE_HEADER_PATTERN}(?:\\s+#{COPS_PATTERN}|\\s+#{PUSH_POP_ARGS_PATTERN})?"
|
|
31
37
|
.gsub(' ', '\s*')
|
|
32
38
|
)
|
|
33
39
|
# @api private
|
|
@@ -58,6 +64,7 @@ module RuboCop
|
|
|
58
64
|
# Checks if the comment is malformed as a `# rubocop:` directive
|
|
59
65
|
def malformed?
|
|
60
66
|
return true if !start_with_marker? || @match_data.nil?
|
|
67
|
+
return true if missing_cop_name?
|
|
61
68
|
|
|
62
69
|
tail = @match_data.post_match.lstrip
|
|
63
70
|
!(tail.empty? || tail.start_with?(TRAILING_COMMENT_MARKER))
|
|
@@ -65,6 +72,8 @@ module RuboCop
|
|
|
65
72
|
|
|
66
73
|
# Checks if the directive comment is missing a cop name
|
|
67
74
|
def missing_cop_name?
|
|
75
|
+
return false if push? || pop?
|
|
76
|
+
|
|
68
77
|
MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text)
|
|
69
78
|
end
|
|
70
79
|
|
|
@@ -88,7 +97,13 @@ module RuboCop
|
|
|
88
97
|
|
|
89
98
|
# Returns match captures to directive comment pattern
|
|
90
99
|
def match_captures
|
|
91
|
-
@match_captures ||= @match_data
|
|
100
|
+
@match_captures ||= @match_data && begin
|
|
101
|
+
captures = @match_data.captures
|
|
102
|
+
mode = captures[0]
|
|
103
|
+
# COPS_PATTERN is at captures[1], PUSH_POP_ARGS_PATTERN is at captures[4]
|
|
104
|
+
cops = captures[1] || captures[4]
|
|
105
|
+
[mode, cops]
|
|
106
|
+
end
|
|
92
107
|
end
|
|
93
108
|
|
|
94
109
|
# Checks if this directive disables cops
|
|
@@ -101,6 +116,21 @@ module RuboCop
|
|
|
101
116
|
mode == 'enable'
|
|
102
117
|
end
|
|
103
118
|
|
|
119
|
+
# Checks if this directive is a push
|
|
120
|
+
def push?
|
|
121
|
+
mode == 'push'
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Checks if this directive is a pop
|
|
125
|
+
def pop?
|
|
126
|
+
mode == 'pop'
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Returns the push arguments as a hash of cop names with their operations
|
|
130
|
+
def push_args
|
|
131
|
+
@push_args ||= parse_push_args
|
|
132
|
+
end
|
|
133
|
+
|
|
104
134
|
# Checks if this directive enables all cops
|
|
105
135
|
def enabled_all?
|
|
106
136
|
!disabled? && all_cops?
|
|
@@ -176,5 +206,18 @@ module RuboCop
|
|
|
176
206
|
def exclude_lint_department_cops(cops)
|
|
177
207
|
cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
|
|
178
208
|
end
|
|
209
|
+
|
|
210
|
+
def parse_push_args
|
|
211
|
+
return {} unless push? && cops
|
|
212
|
+
|
|
213
|
+
args = {}
|
|
214
|
+
cops.split.each do |cop_spec|
|
|
215
|
+
op = cop_spec[0]
|
|
216
|
+
cop_name = cop_spec[1..]
|
|
217
|
+
args[op] ||= []
|
|
218
|
+
args[op] << cop_name
|
|
219
|
+
end
|
|
220
|
+
args
|
|
221
|
+
end
|
|
179
222
|
end
|
|
180
223
|
end
|
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
|
4
4
|
module Formatter
|
|
5
5
|
# This formatter displays a YAML configuration file where all cops that
|
|
6
6
|
# detected any offenses are configured to not detect the offense.
|
|
7
|
-
class DisabledConfigFormatter < BaseFormatter
|
|
7
|
+
class DisabledConfigFormatter < BaseFormatter # rubocop:disable Metrics/ClassLength
|
|
8
8
|
include PathUtil
|
|
9
9
|
|
|
10
10
|
HEADING = <<~COMMENTS
|
|
@@ -17,6 +17,23 @@ module RuboCop
|
|
|
17
17
|
# versions of RuboCop, may require this file to be generated again.
|
|
18
18
|
COMMENTS
|
|
19
19
|
|
|
20
|
+
EXCLUDED_CONFIG_KEYS = %w[
|
|
21
|
+
AutoCorrect
|
|
22
|
+
Description
|
|
23
|
+
Enabled
|
|
24
|
+
Exclude
|
|
25
|
+
Include
|
|
26
|
+
Reference
|
|
27
|
+
References
|
|
28
|
+
Safe
|
|
29
|
+
SafeAutoCorrect
|
|
30
|
+
Severity
|
|
31
|
+
StyleGuide
|
|
32
|
+
VersionAdded
|
|
33
|
+
VersionChanged
|
|
34
|
+
VersionRemoved
|
|
35
|
+
].freeze
|
|
36
|
+
|
|
20
37
|
@config_to_allow_offenses = {}
|
|
21
38
|
@detected_styles = {}
|
|
22
39
|
|
|
@@ -163,10 +180,7 @@ module RuboCop
|
|
|
163
180
|
end
|
|
164
181
|
|
|
165
182
|
def cop_config_params(default_cfg, cfg)
|
|
166
|
-
default_cfg.keys -
|
|
167
|
-
%w[Description StyleGuide Reference References Enabled Exclude Safe
|
|
168
|
-
SafeAutoCorrect VersionAdded VersionChanged VersionRemoved] -
|
|
169
|
-
cfg.keys
|
|
183
|
+
default_cfg.keys - EXCLUDED_CONFIG_KEYS - cfg.keys
|
|
170
184
|
end
|
|
171
185
|
|
|
172
186
|
def output_cop_param_comments(output_buffer, params, default_cfg)
|
|
@@ -45,11 +45,11 @@ module RuboCop
|
|
|
45
45
|
range: LanguageServer::Protocol::Interface::Range.new(
|
|
46
46
|
start: LanguageServer::Protocol::Interface::Position.new(
|
|
47
47
|
line: @offense.line - 1,
|
|
48
|
-
character: highlighted.begin_pos
|
|
48
|
+
character: to_position_character(highlighted.begin_pos)
|
|
49
49
|
),
|
|
50
50
|
end: LanguageServer::Protocol::Interface::Position.new(
|
|
51
51
|
line: @offense.line - 1,
|
|
52
|
-
character: highlighted.end_pos
|
|
52
|
+
character: to_position_character(highlighted.end_pos)
|
|
53
53
|
)
|
|
54
54
|
),
|
|
55
55
|
data: {
|
|
@@ -107,11 +107,11 @@ module RuboCop
|
|
|
107
107
|
range: LanguageServer::Protocol::Interface::Range.new(
|
|
108
108
|
start: LanguageServer::Protocol::Interface::Position.new(
|
|
109
109
|
line: range.line - 1,
|
|
110
|
-
character: range.column
|
|
110
|
+
character: to_position_character(range.column)
|
|
111
111
|
),
|
|
112
112
|
end: LanguageServer::Protocol::Interface::Position.new(
|
|
113
113
|
line: range.last_line - 1,
|
|
114
|
-
character: range.last_column
|
|
114
|
+
character: to_position_character(range.last_column)
|
|
115
115
|
)
|
|
116
116
|
),
|
|
117
117
|
new_text: replacement
|
|
@@ -149,7 +149,7 @@ module RuboCop
|
|
|
149
149
|
|
|
150
150
|
eol = LanguageServer::Protocol::Interface::Position.new(
|
|
151
151
|
line: @offense.line - 1,
|
|
152
|
-
character:
|
|
152
|
+
character: to_position_character(@offense.source_line.length)
|
|
153
153
|
)
|
|
154
154
|
|
|
155
155
|
# TODO: fails for multiline strings - may be preferable to use block
|
|
@@ -162,16 +162,12 @@ module RuboCop
|
|
|
162
162
|
[inline_comment]
|
|
163
163
|
end
|
|
164
164
|
|
|
165
|
-
def
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
line_length += 1
|
|
170
|
-
line_length += 1 if codepoint > RubyLsp::Document::Scanner::SURROGATE_PAIR_START
|
|
171
|
-
end
|
|
172
|
-
line_length
|
|
165
|
+
def to_position_character(utf8_index)
|
|
166
|
+
str = @offense.source_line[0, utf8_index]
|
|
167
|
+
if @document_encoding == Encoding::UTF_16LE || @document_encoding.nil?
|
|
168
|
+
str.length + str.b.count("\xf0-\xff".b)
|
|
173
169
|
else
|
|
174
|
-
|
|
170
|
+
str.length
|
|
175
171
|
end
|
|
176
172
|
end
|
|
177
173
|
|