rubocop 1.91.0 → 1.92.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 +3 -1
- data/lib/rubocop/cached_data.rb +47 -7
- data/lib/rubocop/changed_files.rb +35 -13
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +2 -2
- data/lib/rubocop/cli/command/explain.rb +34 -0
- data/lib/rubocop/cli/command/show_cops.rb +6 -0
- data/lib/rubocop/cli/command/show_docs_url.rb +6 -4
- data/lib/rubocop/cli.rb +3 -2
- data/lib/rubocop/comment_config.rb +17 -8
- data/lib/rubocop/config_loader.rb +6 -3
- data/lib/rubocop/config_loader_resolver.rb +37 -12
- data/lib/rubocop/config_obsoletion/removed_cop.rb +1 -1
- data/lib/rubocop/config_validator.rb +11 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/base.rb +42 -21
- data/lib/rubocop/cop/bundler/gem_comment.rb +0 -1
- data/lib/rubocop/cop/bundler/ordered_gems.rb +0 -8
- data/lib/rubocop/cop/cop_documentation.rb +81 -0
- data/lib/rubocop/cop/cop_explanation.rb +140 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +13 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +23 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +45 -8
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +0 -6
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -5
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
- data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
- data/lib/rubocop/cop/layout/block_alignment.rb +27 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/class_structure.rb +9 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +16 -10
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -3
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +16 -12
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -0
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +8 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/line_length.rb +52 -18
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +12 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +8 -1
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +7 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +14 -0
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
- data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +6 -11
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +2 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +15 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +63 -19
- data/lib/rubocop/cop/lint/loop.rb +24 -2
- data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +71 -11
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +18 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +14 -7
- data/lib/rubocop/cop/lint/void.rb +8 -1
- data/lib/rubocop/cop/metrics/class_length.rb +4 -2
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
- data/lib/rubocop/cop/metrics/module_length.rb +4 -2
- data/lib/rubocop/cop/mixin/alignment.rb +4 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +17 -14
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -1
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +26 -2
- data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +17 -2
- data/lib/rubocop/cop/mixin/project_index_help.rb +15 -0
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +13 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +22 -2
- data/lib/rubocop/cop/mixin.rb +2 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_prefix.rb +7 -22
- data/lib/rubocop/cop/offense.rb +59 -3
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/security/json_load.rb +16 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +7 -0
- data/lib/rubocop/cop/style/alias.rb +18 -5
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
- data/lib/rubocop/cop/style/and_or.rb +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +4 -1
- data/lib/rubocop/cop/style/attr.rb +3 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +6 -4
- data/lib/rubocop/cop/style/block_delimiters.rb +29 -3
- data/lib/rubocop/cop/style/case_like_if.rb +6 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +54 -16
- data/lib/rubocop/cop/style/class_methods_definitions.rb +8 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +85 -11
- data/lib/rubocop/cop/style/concat_array_literals.rb +46 -7
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +65 -9
- data/lib/rubocop/cop/style/double_negation.rb +11 -0
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +3 -1
- data/lib/rubocop/cop/style/endless_method.rb +67 -6
- data/lib/rubocop/cop/style/exact_regexp_match.rb +45 -8
- data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
- data/lib/rubocop/cop/style/float_division.rb +22 -2
- data/lib/rubocop/cop/style/for.rb +40 -2
- data/lib/rubocop/cop/style/format_string.rb +28 -6
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +9 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +32 -9
- data/lib/rubocop/cop/style/hash_syntax.rb +16 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +21 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +19 -20
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +47 -4
- data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
- data/lib/rubocop/cop/style/it_block_parameter.rb +32 -3
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
- data/lib/rubocop/cop/style/lambda.rb +18 -0
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/map_into_array.rb +1 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +45 -10
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
- data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -3
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -5
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
- data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
- data/lib/rubocop/cop/style/mutable_constant.rb +28 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +2 -1
- data/lib/rubocop/cop/style/negative_array_index.rb +9 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +27 -8
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
- data/lib/rubocop/cop/style/next.rb +24 -10
- data/lib/rubocop/cop/style/nil_comparison.rb +16 -4
- data/lib/rubocop/cop/style/non_nil_check.rb +1 -1
- data/lib/rubocop/cop/style/not.rb +10 -5
- data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +13 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +20 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +30 -13
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -0
- data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +12 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +20 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +4 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
- data/lib/rubocop/cop/style/require_order.rb +9 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +5 -9
- data/lib/rubocop/cop/style/return_nil.rb +17 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
- data/lib/rubocop/cop/style/sample.rb +9 -8
- data/lib/rubocop/cop/style/self_assignment.rb +12 -15
- data/lib/rubocop/cop/style/semicolon.rb +16 -5
- data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +9 -3
- data/lib/rubocop/cop/style/super_arguments.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +23 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +23 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -19
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -9
- data/lib/rubocop/cop/style/yoda_expression.rb +10 -1
- data/lib/rubocop/cop/team.rb +10 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -1
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/formatter_set.rb +4 -0
- data/lib/rubocop/formatter/json_formatter.rb +71 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +3 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
- data/lib/rubocop/formatter/sarif_formatter.rb +12 -7
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
- data/lib/rubocop/lsp/runtime.rb +47 -11
- data/lib/rubocop/lsp/stdin_runner.rb +11 -5
- data/lib/rubocop/lsp.rb +5 -2
- data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
- data/lib/rubocop/mcp/explain_tool.rb +68 -0
- data/lib/rubocop/mcp/scope.rb +65 -0
- data/lib/rubocop/mcp/server.rb +184 -76
- data/lib/rubocop/mcp/source_files.rb +35 -0
- data/lib/rubocop/offense_limit.rb +30 -0
- data/lib/rubocop/options.rb +45 -10
- data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
- data/lib/rubocop/remote_config.rb +4 -1
- data/lib/rubocop/result_cache.rb +20 -13
- data/lib/rubocop/runner.rb +109 -41
- data/lib/rubocop/server/cache.rb +2 -2
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +16 -5
|
@@ -78,7 +78,10 @@ module RuboCop
|
|
|
78
78
|
].freeze
|
|
79
79
|
|
|
80
80
|
def on_if(node)
|
|
81
|
-
return
|
|
81
|
+
return unless redundant_condition_offense?(node)
|
|
82
|
+
return if node.each_ancestor(:if).any? do |ancestor|
|
|
83
|
+
redundant_condition_offense?(ancestor)
|
|
84
|
+
end
|
|
82
85
|
|
|
83
86
|
message = message(node)
|
|
84
87
|
|
|
@@ -89,6 +92,10 @@ module RuboCop
|
|
|
89
92
|
|
|
90
93
|
private
|
|
91
94
|
|
|
95
|
+
def redundant_condition_offense?(node)
|
|
96
|
+
!node.modifier_form? && !node.elsif_conditional? && offense?(node)
|
|
97
|
+
end
|
|
98
|
+
|
|
92
99
|
def message(node)
|
|
93
100
|
if redundant_condition?(node)
|
|
94
101
|
REDUNDANT_CONDITION
|
|
@@ -240,10 +247,10 @@ module RuboCop
|
|
|
240
247
|
end
|
|
241
248
|
|
|
242
249
|
# rubocop:disable-next Metrics/AbcSize
|
|
243
|
-
def if_source(if_branch,
|
|
250
|
+
def if_source(if_branch, binary_operator)
|
|
244
251
|
if branches_have_method?(if_branch.parent) && if_branch.parenthesized?
|
|
245
252
|
if_branch.source.delete_suffix(')')
|
|
246
|
-
elsif
|
|
253
|
+
elsif binary_operator
|
|
247
254
|
argument_source = if_branch.first_argument.source
|
|
248
255
|
|
|
249
256
|
"#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
|
|
@@ -257,8 +264,8 @@ module RuboCop
|
|
|
257
264
|
end
|
|
258
265
|
end
|
|
259
266
|
|
|
260
|
-
def else_source(else_branch,
|
|
261
|
-
if
|
|
267
|
+
def else_source(else_branch, binary_operator) # rubocop:disable Metrics/AbcSize
|
|
268
|
+
if binary_operator
|
|
262
269
|
"#{else_branch.first_argument.source})"
|
|
263
270
|
elsif branches_have_method?(else_branch.parent)
|
|
264
271
|
else_source_if_has_method(else_branch)
|
|
@@ -295,11 +302,11 @@ module RuboCop
|
|
|
295
302
|
|
|
296
303
|
def make_ternary_form(node)
|
|
297
304
|
_condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring -- takes all three branches in one step
|
|
298
|
-
|
|
305
|
+
binary_operator = branches_have_method?(node) && binary_operator?(if_branch)
|
|
299
306
|
|
|
300
307
|
ternary_form = [
|
|
301
|
-
if_source(if_branch,
|
|
302
|
-
else_source(else_branch,
|
|
308
|
+
if_source(if_branch, binary_operator),
|
|
309
|
+
else_source(else_branch, binary_operator)
|
|
303
310
|
].join(' || ')
|
|
304
311
|
ternary_form += ')' if branches_have_method?(node) && if_branch.parenthesized?
|
|
305
312
|
|
|
@@ -320,17 +327,27 @@ module RuboCop
|
|
|
320
327
|
|
|
321
328
|
def require_parentheses?(node)
|
|
322
329
|
(node.basic_conditional? && node.modifier_form?) ||
|
|
323
|
-
node.range_type? ||
|
|
324
|
-
node.
|
|
325
|
-
|
|
330
|
+
node.range_type? || node.rescue_type? ||
|
|
331
|
+
(node.respond_to?(:semantic_operator?) && node.semantic_operator?) ||
|
|
332
|
+
low_precedence_keyword?(node)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# e.g. `not foo`, `return foo`, and `yield foo`
|
|
336
|
+
def low_precedence_keyword?(node)
|
|
337
|
+
return node.prefix_not? if node.send_type?
|
|
338
|
+
|
|
339
|
+
node.type?(:return, :next, :break, :yield, :super) &&
|
|
340
|
+
node.arguments? && !node.parenthesized?
|
|
326
341
|
end
|
|
327
342
|
|
|
328
343
|
def require_braces?(node)
|
|
329
344
|
node.hash_type? && !node.braces?
|
|
330
345
|
end
|
|
331
346
|
|
|
332
|
-
|
|
333
|
-
|
|
347
|
+
# Any binary operator binds tighter than `||`, so the fallback must be
|
|
348
|
+
# parenthesized as its argument, e.g. `stack << (foo || :new)`.
|
|
349
|
+
def binary_operator?(node)
|
|
350
|
+
node.binary_operation? && !node.dot?
|
|
334
351
|
end
|
|
335
352
|
|
|
336
353
|
def without_argument_parentheses_method?(node)
|
|
@@ -25,6 +25,12 @@ module RuboCop
|
|
|
25
25
|
MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
|
|
26
26
|
MERGE_METHODS = %i[merge merge!].freeze
|
|
27
27
|
|
|
28
|
+
# `Style/TrailingCommaInHashLiteral` adds a comma to the hash literal whose braces
|
|
29
|
+
# this cop removes in the same pass, which would leave a dangling comma.
|
|
30
|
+
def self.autocorrect_incompatible_with
|
|
31
|
+
[Style::TrailingCommaInHashLiteral]
|
|
32
|
+
end
|
|
33
|
+
|
|
28
34
|
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
29
35
|
def on_hash(node)
|
|
30
36
|
return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
|
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def replaced_exploded(node, command, message)
|
|
52
|
-
arg =
|
|
52
|
+
arg = message_source(message)
|
|
53
53
|
arg = node.parenthesized? ? "(#{arg})" : " #{arg}"
|
|
54
54
|
"#{command}#{arg}"
|
|
55
55
|
end
|
|
@@ -63,19 +63,31 @@ module RuboCop
|
|
|
63
63
|
next if message.nil_type?
|
|
64
64
|
|
|
65
65
|
add_offense(node, message: MSG_2) do |corrector|
|
|
66
|
-
corrector.replace(new_call,
|
|
66
|
+
corrector.replace(new_call, message_source(message))
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
def
|
|
71
|
+
def message_source(message)
|
|
72
72
|
if string_message?(message)
|
|
73
73
|
message.source
|
|
74
|
+
elsif require_parentheses?(message)
|
|
75
|
+
"(#{message.source}).to_s"
|
|
74
76
|
else
|
|
75
77
|
"#{message.source}.to_s"
|
|
76
78
|
end
|
|
77
79
|
end
|
|
78
80
|
|
|
81
|
+
def require_parentheses?(message)
|
|
82
|
+
if message.call_type?
|
|
83
|
+
!message.method?(:[]) &&
|
|
84
|
+
(message.operator_method? || (message.arguments? && !message.parenthesized?))
|
|
85
|
+
else
|
|
86
|
+
!(message.basic_literal? || message.variable? ||
|
|
87
|
+
message.type?(:const, :self, :begin, :array))
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
79
91
|
# @!method exploded?(node)
|
|
80
92
|
def_node_matcher :exploded?, <<~PATTERN
|
|
81
93
|
(send nil? ${:raise :fail} (const {nil? cbase} :RuntimeError) $_)
|
|
@@ -74,7 +74,8 @@ module RuboCop
|
|
|
74
74
|
def should_not_check?(send, body)
|
|
75
75
|
(body&.const_type? && !check_for_constant?) ||
|
|
76
76
|
(body&.str_type? && !check_for_string?) ||
|
|
77
|
-
rails_cache?(send.receiver)
|
|
77
|
+
rails_cache?(send.receiver) ||
|
|
78
|
+
unappendable_argument?(send)
|
|
78
79
|
end
|
|
79
80
|
|
|
80
81
|
# @!method rails_cache?(node)
|
|
@@ -107,6 +108,13 @@ module RuboCop
|
|
|
107
108
|
def check_for_string?
|
|
108
109
|
frozen_string_literals_enabled?
|
|
109
110
|
end
|
|
111
|
+
|
|
112
|
+
def unappendable_argument?(send)
|
|
113
|
+
argument = send.first_argument
|
|
114
|
+
|
|
115
|
+
argument.type?(:splat, :forwarded_restarg) ||
|
|
116
|
+
(argument.hash_type? && !argument.braces?)
|
|
117
|
+
end
|
|
110
118
|
end
|
|
111
119
|
end
|
|
112
120
|
end
|
|
@@ -57,12 +57,21 @@ module RuboCop
|
|
|
57
57
|
def_node_matcher :operation_produces_immutable_object?, <<~PATTERN
|
|
58
58
|
{
|
|
59
59
|
(begin (send {float int} {:+ :- :* :** :/ :% :<<} _))
|
|
60
|
-
(begin (send
|
|
60
|
+
(begin (send #numeric_operation? {:+ :- :* :** :/ :%} {float int}))
|
|
61
61
|
(begin (send _ {:== :=== :!= :<= :>= :< :>} _))
|
|
62
62
|
(send _ {:count :length :size} ...)
|
|
63
63
|
(any_block (send _ {:count :length :size} ...) ...)
|
|
64
64
|
}
|
|
65
65
|
PATTERN
|
|
66
|
+
|
|
67
|
+
# @!method numeric_operation?(node)
|
|
68
|
+
def_node_matcher :numeric_operation?, <<~PATTERN
|
|
69
|
+
{
|
|
70
|
+
float int
|
|
71
|
+
(begin #numeric_operation?)
|
|
72
|
+
(send #numeric_operation? {:+ :- :* :** :/ :%} #numeric_operation?)
|
|
73
|
+
}
|
|
74
|
+
PATTERN
|
|
66
75
|
end
|
|
67
76
|
end
|
|
68
77
|
end
|
|
@@ -66,7 +66,8 @@ module RuboCop
|
|
|
66
66
|
rescue?(node) ||
|
|
67
67
|
in_pattern_matching_in_method_argument?(node) ||
|
|
68
68
|
allowed_pin_operator?(node) ||
|
|
69
|
-
allowed_expression?(node)
|
|
69
|
+
allowed_expression?(node) ||
|
|
70
|
+
ParenthesesCorrector.heredoc_strands_code_after_close_paren?(node)
|
|
70
71
|
end
|
|
71
72
|
|
|
72
73
|
def ignore_syntax?(node)
|
|
@@ -232,12 +233,22 @@ module RuboCop
|
|
|
232
233
|
node = node.send_node if node.any_block_type?
|
|
233
234
|
|
|
234
235
|
return check_unary(begin_node, node) if node.unary_operation?
|
|
236
|
+
return if setter_in_condition?(begin_node, node)
|
|
235
237
|
|
|
236
238
|
return unless method_call_with_redundant_parentheses?(begin_node, node)
|
|
237
239
|
|
|
238
240
|
offense(begin_node, 'a method call')
|
|
239
241
|
end
|
|
240
242
|
|
|
243
|
+
# Like a variable assignment, `if (foo.bar = baz)` is a safe assignment
|
|
244
|
+
# that `Lint/AssignmentInCondition` asks for, not redundant parentheses.
|
|
245
|
+
def setter_in_condition?(begin_node, node)
|
|
246
|
+
return false unless node.setter_method?
|
|
247
|
+
return false unless (parent = begin_node.parent)&.basic_conditional?
|
|
248
|
+
|
|
249
|
+
parent.condition.equal?(begin_node)
|
|
250
|
+
end
|
|
251
|
+
|
|
241
252
|
def check_unary(begin_node, node)
|
|
242
253
|
return if begin_node.chained?
|
|
243
254
|
|
|
@@ -90,6 +90,8 @@ module RuboCop
|
|
|
90
90
|
quote = enforce_double_quotes? ? '"' : "'"
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
+
new_argument = escape_interpolation_like_text(new_argument) if quote == '"'
|
|
94
|
+
|
|
93
95
|
"#{quote}#{new_argument}#{quote}"
|
|
94
96
|
end
|
|
95
97
|
|
|
@@ -109,6 +111,11 @@ module RuboCop
|
|
|
109
111
|
char
|
|
110
112
|
end.join
|
|
111
113
|
end
|
|
114
|
+
|
|
115
|
+
# `#{`, `#$` and `#@` would start an interpolation in a double-quoted string.
|
|
116
|
+
def escape_interpolation_like_text(string)
|
|
117
|
+
string.gsub(/#(?=[{$@])/) { '\#' }
|
|
118
|
+
end
|
|
112
119
|
end
|
|
113
120
|
end
|
|
114
121
|
end
|
|
@@ -34,12 +34,32 @@ module RuboCop
|
|
|
34
34
|
return unless (regexp = redundant_regexp_constructor(node))
|
|
35
35
|
|
|
36
36
|
add_offense(node, message: format(MSG, method: node.method_name)) do |corrector|
|
|
37
|
+
next if ambiguous_slash_regexp?(node, regexp)
|
|
38
|
+
|
|
37
39
|
# Reuse the inner literal's own source so its delimiters are preserved.
|
|
38
40
|
# Forcing `/.../` would break patterns like `%r{foo/bar}` that contain
|
|
39
41
|
# an unescaped slash.
|
|
40
42
|
corrector.replace(node, regexp.source)
|
|
41
43
|
end
|
|
42
44
|
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
# `p / a/` and `p /=a/` parse as division, so a slash regexp starting
|
|
49
|
+
# with whitespace or `=` can't begin the first argument of a command.
|
|
50
|
+
def ambiguous_slash_regexp?(node, regexp)
|
|
51
|
+
return false unless regexp.slash_literal? && regexp.content.match?(/\A[\s=]/)
|
|
52
|
+
|
|
53
|
+
begin_pos = node.source_range.begin_pos
|
|
54
|
+
|
|
55
|
+
node.each_ancestor(:call).any? do |call|
|
|
56
|
+
command?(call) && call.first_argument.source_range.begin_pos == begin_pos
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def command?(call)
|
|
61
|
+
call.arguments? && !call.parenthesized? && !call.operator_method? && !call.setter_method?
|
|
62
|
+
end
|
|
43
63
|
end
|
|
44
64
|
end
|
|
45
65
|
end
|
|
@@ -43,6 +43,10 @@ module RuboCop
|
|
|
43
43
|
ALLOWED_OUTSIDE_CHAR_CLASS_METACHAR_ESCAPES = '.*+?{}()|$'.chars.freeze
|
|
44
44
|
INTERPOLATION_SIGILS = %w[@ $].freeze
|
|
45
45
|
|
|
46
|
+
def self.autocorrect_incompatible_with
|
|
47
|
+
[Style::RegexpLiteral]
|
|
48
|
+
end
|
|
49
|
+
|
|
46
50
|
def on_regexp(node)
|
|
47
51
|
each_escape(node) do |char, index, within_character_class|
|
|
48
52
|
next if char.valid_encoding? && allowed_escape?(node, char, index,
|
|
@@ -104,6 +104,7 @@ module RuboCop
|
|
|
104
104
|
['{', '}'] => /\\.|[{}]/,
|
|
105
105
|
['<', '>'] => /\\.|[<>]/
|
|
106
106
|
}.freeze
|
|
107
|
+
DELIMITERS_KEEPING_ESCAPE = %w[$ * + . ? ^ | ( ) [ ] { } < >].freeze
|
|
107
108
|
|
|
108
109
|
def on_regexp(node)
|
|
109
110
|
return if slash_literal?(node) && percent_r_delimiters_conflict?(node)
|
|
@@ -119,6 +120,7 @@ module RuboCop
|
|
|
119
120
|
add_offense(node, message: message) do |corrector|
|
|
120
121
|
correct_delimiters(node, corrector)
|
|
121
122
|
correct_inner_slashes(node, corrector)
|
|
123
|
+
correct_escaped_delimiters(node, corrector)
|
|
122
124
|
end
|
|
123
125
|
end
|
|
124
126
|
|
|
@@ -174,9 +176,8 @@ module RuboCop
|
|
|
174
176
|
cop_config['AllowInnerSlashes']
|
|
175
177
|
end
|
|
176
178
|
|
|
177
|
-
def node_body(node
|
|
178
|
-
|
|
179
|
-
node.each_child_node(*types).map(&:source).join
|
|
179
|
+
def node_body(node)
|
|
180
|
+
node.each_child_node(:str).map(&:source).join
|
|
180
181
|
end
|
|
181
182
|
|
|
182
183
|
def slash_literal?(node)
|
|
@@ -190,12 +191,20 @@ module RuboCop
|
|
|
190
191
|
def allowed_omit_parentheses_with_percent_r_literal?(node)
|
|
191
192
|
return false unless node.parent&.call_type?
|
|
192
193
|
return true if node.content.start_with?(' ', '=')
|
|
194
|
+
return true if first_argument_of_command?(node) && node.content.match?(/\A\s/)
|
|
193
195
|
|
|
194
196
|
enforced_style = config.for_cop('Style/MethodCallWithArgsParentheses')['EnforcedStyle']
|
|
195
197
|
|
|
196
198
|
enforced_style == 'omit_parentheses'
|
|
197
199
|
end
|
|
198
200
|
|
|
201
|
+
def first_argument_of_command?(node)
|
|
202
|
+
call = node.parent
|
|
203
|
+
return false unless call.first_argument.equal?(node)
|
|
204
|
+
|
|
205
|
+
!call.parenthesized? && !call.operator_method? && !call.setter_method?
|
|
206
|
+
end
|
|
207
|
+
|
|
199
208
|
def correct_delimiters(node, corrector)
|
|
200
209
|
replacement = calculate_replacement(node)
|
|
201
210
|
corrector.replace(node.loc.begin, replacement.first)
|
|
@@ -203,32 +212,16 @@ module RuboCop
|
|
|
203
212
|
end
|
|
204
213
|
|
|
205
214
|
def correct_inner_slashes(node, corrector)
|
|
206
|
-
regexp_begin = node.loc.begin.end_pos
|
|
207
|
-
|
|
208
|
-
inner_slash_indices(node).each do |index|
|
|
209
|
-
start = regexp_begin + index
|
|
210
|
-
|
|
211
|
-
corrector.replace(
|
|
212
|
-
range_between(
|
|
213
|
-
start,
|
|
214
|
-
start + inner_slash_before_correction(node).length
|
|
215
|
-
),
|
|
216
|
-
inner_slash_after_correction(node)
|
|
217
|
-
)
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
def inner_slash_indices(node)
|
|
222
|
-
text = node_body(node, include_begin_nodes: true)
|
|
223
215
|
pattern = inner_slash_before_correction(node)
|
|
224
|
-
|
|
225
|
-
indices = []
|
|
216
|
+
replacement = inner_slash_after_correction(node)
|
|
226
217
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
218
|
+
node.each_child_node(:str) do |str_node|
|
|
219
|
+
inner_slash_indices(str_node.source, pattern).each do |index|
|
|
220
|
+
start = str_node.source_range.begin_pos + index
|
|
230
221
|
|
|
231
|
-
|
|
222
|
+
corrector.replace(range_between(start, start + pattern.length), replacement)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
232
225
|
end
|
|
233
226
|
|
|
234
227
|
def inner_slash_before_correction(node)
|
|
@@ -239,6 +232,17 @@ module RuboCop
|
|
|
239
232
|
inner_slash_for(calculate_replacement(node).first)
|
|
240
233
|
end
|
|
241
234
|
|
|
235
|
+
def inner_slash_indices(text, pattern)
|
|
236
|
+
index = -1
|
|
237
|
+
indices = []
|
|
238
|
+
|
|
239
|
+
while (index = text.index(pattern, index + 1))
|
|
240
|
+
indices << index
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
indices
|
|
244
|
+
end
|
|
245
|
+
|
|
242
246
|
def inner_slash_for(opening_delimiter)
|
|
243
247
|
if ['/', '%r/'].include?(opening_delimiter)
|
|
244
248
|
'\/'
|
|
@@ -254,6 +258,51 @@ module RuboCop
|
|
|
254
258
|
%w[/ /]
|
|
255
259
|
end
|
|
256
260
|
end
|
|
261
|
+
|
|
262
|
+
def correct_escaped_delimiters(node, corrector)
|
|
263
|
+
return unless (delimiter = delimiter_to_unescape(node))
|
|
264
|
+
|
|
265
|
+
node.each_child_node(:str) do |str_node|
|
|
266
|
+
text = str_node.source
|
|
267
|
+
|
|
268
|
+
escaped_delimiter_indices(text, delimiter).each do |index|
|
|
269
|
+
start = str_node.source_range.begin_pos + index
|
|
270
|
+
replacement = escaped_delimiter_replacement(node, delimiter, text[index + 2])
|
|
271
|
+
|
|
272
|
+
corrector.replace(range_between(start, start + 2), replacement)
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def delimiter_to_unescape(node)
|
|
278
|
+
return if slash_literal?(node)
|
|
279
|
+
|
|
280
|
+
delimiter = node.delimiters.first
|
|
281
|
+
|
|
282
|
+
delimiter unless delimiter == '/' || DELIMITERS_KEEPING_ESCAPE.include?(delimiter)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def escaped_delimiter_indices(text, delimiter)
|
|
286
|
+
indices = []
|
|
287
|
+
index = 0
|
|
288
|
+
|
|
289
|
+
while (index = text.index('\\', index))
|
|
290
|
+
indices << index if text[index + 1] == delimiter
|
|
291
|
+
index += 2
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
indices
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# A bare `#` before `{`, `@` or `$` would start an interpolation between slashes.
|
|
298
|
+
# `\#` still reads as a literal `#` there, except in extended mode, where `%r#a\#{b}#x`
|
|
299
|
+
# reads `#{b}` as a comment; `#\{` keeps both that comment and a `#` inside
|
|
300
|
+
# a character class.
|
|
301
|
+
def escaped_delimiter_replacement(node, delimiter, next_char)
|
|
302
|
+
return delimiter unless delimiter == '#' && next_char&.match?(/[{@$]/)
|
|
303
|
+
|
|
304
|
+
node.extended? ? '#\\' : '\\#'
|
|
305
|
+
end
|
|
257
306
|
end
|
|
258
307
|
end
|
|
259
308
|
end
|
|
@@ -88,6 +88,8 @@ module RuboCop
|
|
|
88
88
|
return unless previous_older_sibling
|
|
89
89
|
|
|
90
90
|
add_offense(node, message: format(MSG, name: node.method_name)) do |corrector|
|
|
91
|
+
next unless own_lines?(previous_older_sibling) && own_lines?(search_node(node))
|
|
92
|
+
|
|
91
93
|
autocorrect(corrector, node, previous_older_sibling)
|
|
92
94
|
end
|
|
93
95
|
end
|
|
@@ -112,6 +114,13 @@ module RuboCop
|
|
|
112
114
|
end
|
|
113
115
|
end
|
|
114
116
|
|
|
117
|
+
def own_lines?(node)
|
|
118
|
+
range = node.source_range
|
|
119
|
+
rest_of_line = range.source_buffer.source_line(range.last_line)[range.last_column..]
|
|
120
|
+
|
|
121
|
+
begins_its_line?(range) && rest_of_line.match?(/\A\s*(#.*)?\z/)
|
|
122
|
+
end
|
|
123
|
+
|
|
115
124
|
def autocorrect(corrector, node, previous_older_sibling)
|
|
116
125
|
range1 = range_with_comments_and_lines(previous_older_sibling)
|
|
117
126
|
range2 = range_with_comments_and_lines(node.parent.if_type? ? node.parent : node)
|
|
@@ -54,6 +54,9 @@ module RuboCop
|
|
|
54
54
|
|
|
55
55
|
rescue_node = node.parent
|
|
56
56
|
add_offense(rescue_node) do |corrector|
|
|
57
|
+
# The heredoc body would be left behind when the rescue body is moved.
|
|
58
|
+
next if heredoc_end(node)
|
|
59
|
+
|
|
57
60
|
parenthesized = parenthesized?(rescue_node)
|
|
58
61
|
|
|
59
62
|
correct_rescue_block(corrector, rescue_node, parenthesized)
|
|
@@ -95,15 +98,8 @@ module RuboCop
|
|
|
95
98
|
end
|
|
96
99
|
|
|
97
100
|
def heredoc_end(node)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
heredoc = node.arguments.reverse.find do |argument|
|
|
101
|
-
argument.respond_to?(:heredoc?) && argument.heredoc?
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
return unless heredoc
|
|
105
|
-
|
|
106
|
-
heredoc.loc.heredoc_end
|
|
101
|
+
node.each_node(:any_str).select(&:heredoc?).map { |heredoc| heredoc.loc.heredoc_end }
|
|
102
|
+
.max_by(&:end_pos)
|
|
107
103
|
end
|
|
108
104
|
end
|
|
109
105
|
end
|
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
|
65
65
|
return if correct_style?(node)
|
|
66
66
|
|
|
67
67
|
add_offense(node) do |corrector|
|
|
68
|
-
corrected = style == :return ? 'return' :
|
|
68
|
+
corrected = style == :return ? 'return' : return_nil(node)
|
|
69
69
|
|
|
70
70
|
corrector.replace(node, corrected)
|
|
71
71
|
end
|
|
@@ -79,13 +79,28 @@ module RuboCop
|
|
|
79
79
|
|
|
80
80
|
def correct_style?(node)
|
|
81
81
|
(style == :return && !return_nil_node?(node)) ||
|
|
82
|
-
(style == :return_nil && !return_node?(node))
|
|
82
|
+
(style == :return_nil && (!return_node?(node) || top_level_return?(node)))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def top_level_return?(node)
|
|
86
|
+
node.each_ancestor(:any_block, :any_def).none?
|
|
83
87
|
end
|
|
84
88
|
|
|
85
89
|
def scoped_node?(node)
|
|
86
90
|
node.any_def_type? || node.lambda?
|
|
87
91
|
end
|
|
88
92
|
|
|
93
|
+
def return_nil(node)
|
|
94
|
+
return 'return nil' unless (parent = node.parent)
|
|
95
|
+
|
|
96
|
+
if (parent.operator_keyword? && parent.logical_operator?) ||
|
|
97
|
+
(parent.if_type? && parent.ternary?)
|
|
98
|
+
'(return nil)'
|
|
99
|
+
else
|
|
100
|
+
'return nil'
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
89
104
|
# @!method chained_send?(node)
|
|
90
105
|
def_node_matcher :chained_send?, '(send !nil? ...)'
|
|
91
106
|
|
|
@@ -116,7 +116,17 @@ module RuboCop
|
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
def handle_return(return_node)
|
|
119
|
-
|
|
119
|
+
return unless return_nil?(return_node)
|
|
120
|
+
|
|
121
|
+
replacement = requires_parentheses?(return_node) ? '(return false)' : 'return false'
|
|
122
|
+
register_offense(return_node, replacement)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def requires_parentheses?(node)
|
|
126
|
+
parent = node.parent
|
|
127
|
+
|
|
128
|
+
(parent.operator_keyword? && parent.logical_operator?) ||
|
|
129
|
+
(parent.if_type? && parent.ternary?)
|
|
120
130
|
end
|
|
121
131
|
|
|
122
132
|
def handle_nil(nil_node)
|
|
@@ -98,22 +98,23 @@ module RuboCop
|
|
|
98
98
|
second.int_type? ? second.to_a.first : :unknown
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
102
101
|
def range_size(range_node)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
low, high = vals.map { |val| val.nil? ? 0 : val.children[0] }
|
|
107
|
-
return :unknown unless low.zero? && high >= 0
|
|
102
|
+
low, high = range_node.to_a
|
|
103
|
+
# An endless range takes the rest of the collection, whatever its size.
|
|
104
|
+
return :unknown unless zero_or_beginless?(low) && high&.int_type? && high.value >= 0
|
|
108
105
|
|
|
109
106
|
case range_node.type
|
|
110
107
|
when :erange
|
|
111
|
-
|
|
108
|
+
high.value
|
|
112
109
|
when :irange
|
|
113
|
-
|
|
110
|
+
high.value + 1
|
|
114
111
|
end
|
|
115
112
|
end
|
|
116
113
|
|
|
114
|
+
def zero_or_beginless?(low)
|
|
115
|
+
low.nil? || (low.int_type? && low.value.zero?)
|
|
116
|
+
end
|
|
117
|
+
|
|
117
118
|
def source_range(shuffle_node, node)
|
|
118
119
|
shuffle_node.loc.selector.join(node.source_range.end)
|
|
119
120
|
end
|
|
@@ -37,15 +37,20 @@ module RuboCop
|
|
|
37
37
|
private
|
|
38
38
|
|
|
39
39
|
def check(node, var_type)
|
|
40
|
-
return unless (rhs = node.expression)
|
|
40
|
+
return unless (rhs = unparenthesized(node.expression))
|
|
41
41
|
|
|
42
42
|
if rhs.send_type? && rhs.arguments.one?
|
|
43
43
|
check_send_node(node, rhs, node.name, var_type)
|
|
44
|
-
elsif rhs.operator_keyword?
|
|
44
|
+
elsif rhs.operator_keyword? && rhs.logical_operator?
|
|
45
45
|
check_boolean_node(node, rhs, node.name, var_type)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
def unparenthesized(node)
|
|
50
|
+
node = node.children.first while node&.begin_type? && node.children.one?
|
|
51
|
+
node
|
|
52
|
+
end
|
|
53
|
+
|
|
49
54
|
def check_send_node(node, rhs, var_name, var_type)
|
|
50
55
|
return unless OPS.include?(rhs.method_name)
|
|
51
56
|
|
|
@@ -68,26 +73,18 @@ module RuboCop
|
|
|
68
73
|
end
|
|
69
74
|
|
|
70
75
|
def autocorrect(corrector, node)
|
|
71
|
-
rhs = node.expression
|
|
76
|
+
rhs = unparenthesized(node.expression)
|
|
72
77
|
|
|
73
78
|
if rhs.send_type?
|
|
74
|
-
|
|
79
|
+
apply_autocorrect(corrector, node, rhs.method_name, rhs.first_argument)
|
|
75
80
|
elsif rhs.operator_keyword?
|
|
76
|
-
|
|
81
|
+
apply_autocorrect(corrector, node, rhs.loc.operator.source, rhs.rhs)
|
|
77
82
|
end
|
|
78
83
|
end
|
|
79
84
|
|
|
80
|
-
def
|
|
81
|
-
apply_autocorrect(corrector, node, rhs, rhs.method_name, rhs.first_argument)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def autocorrect_boolean_node(corrector, node, rhs)
|
|
85
|
-
apply_autocorrect(corrector, node, rhs, rhs.loc.operator.source, rhs.rhs)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def apply_autocorrect(corrector, node, rhs, operator, new_rhs)
|
|
85
|
+
def apply_autocorrect(corrector, node, operator, new_rhs)
|
|
89
86
|
corrector.insert_before(node.loc.operator, operator)
|
|
90
|
-
corrector.replace(
|
|
87
|
+
corrector.replace(node.expression, new_rhs.source)
|
|
91
88
|
end
|
|
92
89
|
end
|
|
93
90
|
end
|