rubocop 1.91.0 → 1.92.2
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 +4 -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.rb +0 -4
- 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_obsoletion.rb +9 -0
- data/lib/rubocop/config_validator.rb +11 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/badge.rb +1 -1
- 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 +37 -7
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +25 -4
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +34 -0
- 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/argument_alignment.rb +5 -1
- 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 +29 -7
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/dot_position.rb +25 -15
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +21 -8
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +9 -3
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +21 -25
- data/lib/rubocop/cop/layout/extra_spacing.rb +21 -6
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -1
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +15 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +16 -8
- 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 +7 -3
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
- data/lib/rubocop/cop/layout/indentation_consistency.rb +22 -5
- 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 +176 -26
- 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 +9 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +30 -5
- 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 +16 -3
- 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_around_operators.rb +31 -4
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +16 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +32 -9
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +29 -11
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -12
- 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/ambiguous_regexp_literal.rb +6 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +4 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +20 -17
- 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/nested_percent_literal.rb +3 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +3 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +22 -1
- data/lib/rubocop/cop/lint/percent_string_array.rb +75 -9
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +39 -9
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +11 -4
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +47 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -0
- 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/useless_setter_call.rb +7 -4
- 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 +23 -19
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +8 -2
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +105 -0
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +41 -6
- 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 +39 -5
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/mixin/visibility_help.rb +2 -1
- 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/naming/rescued_exceptions_variable_name.rb +1 -1
- 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 +37 -2
- 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 +37 -10
- data/lib/rubocop/cop/style/arguments_forwarding.rb +32 -3
- 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 +35 -3
- data/lib/rubocop/cop/style/case_equality.rb +14 -3
- data/lib/rubocop/cop/style/case_like_if.rb +6 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +57 -16
- data/lib/rubocop/cop/style/class_methods_definitions.rb +15 -0
- data/lib/rubocop/cop/style/collection_querying.rb +79 -46
- data/lib/rubocop/cop/style/combinable_loops.rb +89 -11
- data/lib/rubocop/cop/style/concat_array_literals.rb +58 -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/empty_string_inside_interpolation.rb +53 -11
- data/lib/rubocop/cop/style/endless_method.rb +104 -11
- 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 +37 -2
- data/lib/rubocop/cop/style/for.rb +53 -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 +31 -22
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +4 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +42 -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 +32 -26
- 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 +94 -4
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
- data/lib/rubocop/cop/style/lambda.rb +34 -1
- 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 +80 -13
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +26 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
- data/lib/rubocop/cop/style/method_def_parentheses.rb +38 -4
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- data/lib/rubocop/cop/style/mixin_grouping.rb +12 -3
- 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 +52 -7
- 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 +28 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +13 -2
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +19 -1
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/quoted_symbols.rb +5 -7
- data/lib/rubocop/cop/style/raise_args.rb +80 -11
- data/lib/rubocop/cop/style/reduce_to_hash.rb +47 -33
- data/lib/rubocop/cop/style/redundant_begin.rb +45 -5
- 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 +27 -11
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +11 -3
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +24 -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/redundant_self.rb +9 -1
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +28 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +38 -4
- data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
- data/lib/rubocop/cop/style/require_order.rb +25 -8
- data/lib/rubocop/cop/style/rescue_modifier.rb +11 -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/send_with_literal_method_name.rb +4 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +42 -4
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +21 -4
- data/lib/rubocop/cop/style/struct_inheritance.rb +6 -0
- data/lib/rubocop/cop/style/super_arguments.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +24 -6
- 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/routes.rb +23 -23
- 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 +36 -8
- data/lib/rubocop/remote_config.rb +4 -1
- data/lib/rubocop/result_cache.rb +20 -13
- data/lib/rubocop/runner.rb +110 -42
- data/lib/rubocop/server/cache.rb +6 -6
- data/lib/rubocop/target_ruby.rb +21 -9
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +16 -5
|
@@ -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
|
|
@@ -29,8 +29,7 @@ module RuboCop
|
|
|
29
29
|
operation_produces_immutable_object?(node.receiver))
|
|
30
30
|
|
|
31
31
|
add_offense(node) do |corrector|
|
|
32
|
-
corrector.remove(node.loc.dot)
|
|
33
|
-
corrector.remove(node.loc.selector)
|
|
32
|
+
corrector.remove(node.loc.dot.join(node.loc.selector))
|
|
34
33
|
end
|
|
35
34
|
end
|
|
36
35
|
|
|
@@ -57,12 +56,21 @@ module RuboCop
|
|
|
57
56
|
def_node_matcher :operation_produces_immutable_object?, <<~PATTERN
|
|
58
57
|
{
|
|
59
58
|
(begin (send {float int} {:+ :- :* :** :/ :% :<<} _))
|
|
60
|
-
(begin (send
|
|
59
|
+
(begin (send #numeric_operation? {:+ :- :* :** :/ :%} {float int}))
|
|
61
60
|
(begin (send _ {:== :=== :!= :<= :>= :< :>} _))
|
|
62
61
|
(send _ {:count :length :size} ...)
|
|
63
62
|
(any_block (send _ {:count :length :size} ...) ...)
|
|
64
63
|
}
|
|
65
64
|
PATTERN
|
|
65
|
+
|
|
66
|
+
# @!method numeric_operation?(node)
|
|
67
|
+
def_node_matcher :numeric_operation?, <<~PATTERN
|
|
68
|
+
{
|
|
69
|
+
float int
|
|
70
|
+
(begin #numeric_operation?)
|
|
71
|
+
(send #numeric_operation? {:+ :- :* :** :/ :%} #numeric_operation?)
|
|
72
|
+
}
|
|
73
|
+
PATTERN
|
|
66
74
|
end
|
|
67
75
|
end
|
|
68
76
|
end
|
|
@@ -30,6 +30,10 @@ module RuboCop
|
|
|
30
30
|
|
|
31
31
|
minimum_target_ruby_version 3.0
|
|
32
32
|
|
|
33
|
+
def self.autocorrect_incompatible_with
|
|
34
|
+
[Layout::MultilineMethodCallBraceLayout]
|
|
35
|
+
end
|
|
36
|
+
|
|
33
37
|
# @!method redundant_unfreeze?(node)
|
|
34
38
|
def_node_matcher :redundant_unfreeze?, <<~PATTERN
|
|
35
39
|
{
|
|
@@ -41,9 +45,10 @@ module RuboCop
|
|
|
41
45
|
def on_dstr(node)
|
|
42
46
|
return if uninterpolated_string?(node) || uninterpolated_heredoc?(node)
|
|
43
47
|
return unless redundant_unfreeze?(node.parent)
|
|
48
|
+
return if comment_outside_string?(node)
|
|
44
49
|
|
|
45
50
|
add_offense(offense_range(node.parent)) do |corrector|
|
|
46
|
-
corrector
|
|
51
|
+
remove_unfreeze(corrector, node.parent, node)
|
|
47
52
|
end
|
|
48
53
|
end
|
|
49
54
|
|
|
@@ -56,6 +61,24 @@ module RuboCop
|
|
|
56
61
|
node.loc.selector
|
|
57
62
|
end
|
|
58
63
|
end
|
|
64
|
+
|
|
65
|
+
# Only the parts around the string are removed, so that an unfrozen string
|
|
66
|
+
# interpolated into it can be corrected in the same pass.
|
|
67
|
+
def remove_unfreeze(corrector, node, string)
|
|
68
|
+
corrector.remove(node.source_range.begin.join(string.source_range.begin))
|
|
69
|
+
corrector.remove(string.source_range.end.join(node.source_range.end))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def comment_outside_string?(node)
|
|
73
|
+
call_range = node.parent.source_range
|
|
74
|
+
string_range = node.source_range
|
|
75
|
+
|
|
76
|
+
processed_source.comments.any? do |comment|
|
|
77
|
+
range = comment.source_range
|
|
78
|
+
|
|
79
|
+
call_range.contains?(range) && !string_range.contains?(range)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
59
82
|
end
|
|
60
83
|
end
|
|
61
84
|
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,
|
|
@@ -115,7 +115,7 @@ module RuboCop
|
|
|
115
115
|
|
|
116
116
|
def on_send(node)
|
|
117
117
|
return unless node.self_receiver? && regular_method_call?(node)
|
|
118
|
-
return if node
|
|
118
|
+
return if multiple_assignment_target?(node)
|
|
119
119
|
return if allowed_send_node?(node)
|
|
120
120
|
return if it_method_in_block?(node)
|
|
121
121
|
|
|
@@ -154,6 +154,14 @@ module RuboCop
|
|
|
154
154
|
end
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
+
def multiple_assignment_target?(node)
|
|
158
|
+
return false unless (parent = node.parent)
|
|
159
|
+
|
|
160
|
+
parent = parent.parent if parent.splat_type?
|
|
161
|
+
|
|
162
|
+
parent.mlhs_type?
|
|
163
|
+
end
|
|
164
|
+
|
|
157
165
|
def allowed_send_node?(node)
|
|
158
166
|
@allowed_send_nodes.include?(node) ||
|
|
159
167
|
@local_variables_scopes[node].include?(node.method_name) ||
|
|
@@ -23,14 +23,20 @@ module RuboCop
|
|
|
23
23
|
# foo = bar unless condition
|
|
24
24
|
#
|
|
25
25
|
class RedundantSelfAssignmentBranch < Base
|
|
26
|
+
include RescueNode
|
|
26
27
|
extend AutoCorrector
|
|
27
28
|
|
|
28
29
|
MSG = 'Remove the self-assignment branch.'
|
|
29
30
|
|
|
31
|
+
STATEMENT_BODY_TYPES = %i[
|
|
32
|
+
kwbegin def defs block numblock itblock class module sclass rescue ensure
|
|
33
|
+
].freeze
|
|
34
|
+
|
|
30
35
|
def on_lvasgn(node)
|
|
31
36
|
expression = node.expression
|
|
32
37
|
|
|
33
38
|
return unless use_if_and_else_branch?(expression)
|
|
39
|
+
return unless statement?(node)
|
|
34
40
|
|
|
35
41
|
if_branch = expression.if_branch
|
|
36
42
|
else_branch = expression.else_branch
|
|
@@ -51,6 +57,28 @@ module RuboCop
|
|
|
51
57
|
!expression.ternary? || !expression.else?
|
|
52
58
|
end
|
|
53
59
|
|
|
60
|
+
def statement?(node)
|
|
61
|
+
parent = node.parent
|
|
62
|
+
return true if parent.nil? || parent.type?(*STATEMENT_BODY_TYPES)
|
|
63
|
+
return parent.loc.begin.nil? if parent.begin_type?
|
|
64
|
+
return !rescue_modifier?(parent) if parent.resbody_type?
|
|
65
|
+
|
|
66
|
+
statement_branch?(node, parent)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def statement_branch?(node, parent)
|
|
70
|
+
case parent.type
|
|
71
|
+
when :if
|
|
72
|
+
!parent.ternary? && !node.equal?(parent.condition)
|
|
73
|
+
when :when, :in_pattern, :while, :until, :for
|
|
74
|
+
node.equal?(parent.body)
|
|
75
|
+
when :case, :case_match
|
|
76
|
+
node.equal?(parent.else_branch)
|
|
77
|
+
else
|
|
78
|
+
false
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
54
82
|
def inconvertible_to_modifier?(if_branch, else_branch)
|
|
55
83
|
multiple_statements?(if_branch) || multiple_statements?(else_branch) ||
|
|
56
84
|
(else_branch.respond_to?(:elsif?) && else_branch.elsif?)
|
|
@@ -123,12 +123,29 @@ module RuboCop
|
|
|
123
123
|
end
|
|
124
124
|
|
|
125
125
|
def register_offense(node, sort_node, sorter, accessor)
|
|
126
|
+
return if code_after_accessor_kept_apart?(node)
|
|
127
|
+
|
|
126
128
|
message = message(node, sorter, accessor)
|
|
127
129
|
add_offense(offense_range(sort_node, node), message: message) do |corrector|
|
|
128
130
|
autocorrect(corrector, node, sort_node, sorter, accessor)
|
|
129
131
|
end
|
|
130
132
|
end
|
|
131
133
|
|
|
134
|
+
def code_after_accessor_kept_apart?(node)
|
|
135
|
+
return false if with_logical_operator?(node)
|
|
136
|
+
|
|
137
|
+
source = before_accessor_source(node)
|
|
138
|
+
return false if !source.include?("\n") || source.strip.empty?
|
|
139
|
+
|
|
140
|
+
rest = code_after_accessor(node)
|
|
141
|
+
|
|
142
|
+
!rest.empty? && !rest.match?(/\A(#|&?\.|[)\]},])/)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def code_after_accessor(node)
|
|
146
|
+
processed_source.lines[node.last_line - 1][node.source_range.last_column..].strip
|
|
147
|
+
end
|
|
148
|
+
|
|
132
149
|
def offense_range(sort_node, node)
|
|
133
150
|
range_between(sort_node.loc.selector.begin_pos, node.source_range.end_pos)
|
|
134
151
|
end
|
|
@@ -146,12 +163,29 @@ module RuboCop
|
|
|
146
163
|
end
|
|
147
164
|
|
|
148
165
|
def autocorrect(corrector, node, sort_node, sorter, accessor)
|
|
149
|
-
# Remove accessor, e.g. `first` or `[-1]`.
|
|
150
|
-
corrector.remove(range_between(accessor_start(node), node.source_range.end_pos))
|
|
151
166
|
# Replace "sort" or "sort_by" with the appropriate min/max method.
|
|
152
167
|
corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
|
|
153
|
-
|
|
154
|
-
|
|
168
|
+
remove_accessor(corrector, node)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def remove_accessor(corrector, node)
|
|
172
|
+
if removable_line_break_before_accessor?(node)
|
|
173
|
+
corrector.remove(node.receiver.source_range.end.join(node.source_range.end))
|
|
174
|
+
else
|
|
175
|
+
corrector.remove(range_between(accessor_start(node), node.source_range.end_pos))
|
|
176
|
+
|
|
177
|
+
replace_with_logical_operator(corrector, node) if with_logical_operator?(node)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def removable_line_break_before_accessor?(node)
|
|
182
|
+
source = before_accessor_source(node)
|
|
183
|
+
|
|
184
|
+
source.include?("\n") && source.strip.empty?
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def before_accessor_source(node)
|
|
188
|
+
node.receiver.source_range.end.join((node.loc.dot || node.loc.selector).begin).source
|
|
155
189
|
end
|
|
156
190
|
|
|
157
191
|
def replace_with_logical_operator(corrector, node)
|
|
@@ -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
|
|
@@ -99,25 +101,40 @@ module RuboCop
|
|
|
99
101
|
end
|
|
100
102
|
|
|
101
103
|
def find_previous_older_sibling(node) # rubocop:disable Metrics
|
|
102
|
-
|
|
104
|
+
oldest = nil
|
|
105
|
+
search_node(node).left_siblings.reverse_each do |sibling|
|
|
103
106
|
next unless sibling.is_a?(AST::Node)
|
|
104
107
|
|
|
105
|
-
|
|
106
|
-
break unless
|
|
107
|
-
break unless
|
|
108
|
-
break unless in_same_section?(
|
|
109
|
-
break unless node.first_argument.str_type? &&
|
|
108
|
+
required = sibling_node(sibling)
|
|
109
|
+
break unless required&.send_type? && required.method?(node.method_name)
|
|
110
|
+
break unless required.arguments? && !required.receiver
|
|
111
|
+
break unless in_same_section?(required, node)
|
|
112
|
+
break unless node.first_argument.str_type? && required.first_argument.str_type?
|
|
110
113
|
|
|
111
|
-
node.first_argument.value <
|
|
114
|
+
oldest = sibling if node.first_argument.value < required.first_argument.value
|
|
112
115
|
end
|
|
116
|
+
oldest
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def own_lines?(node)
|
|
120
|
+
range = node.source_range
|
|
121
|
+
rest_of_line = range.source_buffer.source_line(range.last_line)[range.last_column..]
|
|
122
|
+
|
|
123
|
+
begins_its_line?(range) && rest_of_line.match?(/\A\s*(#.*)?\z/)
|
|
113
124
|
end
|
|
114
125
|
|
|
115
126
|
def autocorrect(corrector, node, previous_older_sibling)
|
|
116
127
|
range1 = range_with_comments_and_lines(previous_older_sibling)
|
|
117
128
|
range2 = range_with_comments_and_lines(node.parent.if_type? ? node.parent : node)
|
|
129
|
+
source = range2.source
|
|
130
|
+
|
|
131
|
+
unless source.end_with?("\n")
|
|
132
|
+
source += "\n"
|
|
133
|
+
range2 = range2.with(begin_pos: range2.begin_pos - 1)
|
|
134
|
+
end
|
|
118
135
|
|
|
119
136
|
corrector.remove(range2)
|
|
120
|
-
corrector.insert_before(range1,
|
|
137
|
+
corrector.insert_before(range1.begin, source)
|
|
121
138
|
end
|
|
122
139
|
|
|
123
140
|
def search_node(node)
|
|
@@ -54,15 +54,24 @@ 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
|
+
next if inside_corrected_rescue_body?(rescue_node)
|
|
60
|
+
|
|
57
61
|
parenthesized = parenthesized?(rescue_node)
|
|
58
62
|
|
|
59
63
|
correct_rescue_block(corrector, rescue_node, parenthesized)
|
|
60
64
|
ParenthesesCorrector.correct(corrector, rescue_node.parent) if parenthesized
|
|
65
|
+
ignore_node(rescue_node)
|
|
61
66
|
end
|
|
62
67
|
end
|
|
63
68
|
|
|
64
69
|
private
|
|
65
70
|
|
|
71
|
+
def inside_corrected_rescue_body?(node)
|
|
72
|
+
node.each_ancestor(:resbody).any? { |resbody| ignored_node?(resbody.parent) }
|
|
73
|
+
end
|
|
74
|
+
|
|
66
75
|
def parenthesized?(node)
|
|
67
76
|
node.parent && parentheses?(node.parent)
|
|
68
77
|
end
|
|
@@ -95,15 +104,8 @@ module RuboCop
|
|
|
95
104
|
end
|
|
96
105
|
|
|
97
106
|
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
|
|
107
|
+
node.each_node(:any_str).select(&:heredoc?).map { |heredoc| heredoc.loc.heredoc_end }
|
|
108
|
+
.max_by(&:end_pos)
|
|
107
109
|
end
|
|
108
110
|
end
|
|
109
111
|
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)
|