rubocop 1.90.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 +241 -11
- data/config/obsoletion.yml +9 -0
- data/lib/rubocop/cached_data.rb +47 -7
- data/lib/rubocop/changed_files.rb +134 -0
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +23 -3
- 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 +11 -4
- data/lib/rubocop/comment_config/directive_range.rb +3 -1
- data/lib/rubocop/comment_config/disable_next.rb +49 -3
- data/lib/rubocop/comment_config/push_pop.rb +55 -0
- data/lib/rubocop/comment_config.rb +32 -53
- data/lib/rubocop/config.rb +10 -0
- data/lib/rubocop/config_loader.rb +18 -7
- data/lib/rubocop/config_loader_resolver.rb +79 -12
- data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
- data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +29 -3
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/badge.rb +1 -1
- data/lib/rubocop/cop/base.rb +57 -24
- 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/correctors.rb +2 -2
- 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/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/generator.rb +1 -1
- 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/on_send_without_on_csend.rb +1 -1
- 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 +2 -0
- 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/comment_indentation.rb +8 -5
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -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_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 +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_array_element_indentation.rb +17 -4
- 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/first_parameter_indentation.rb +11 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +15 -10
- 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 +4 -4
- 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 +71 -19
- 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 +10 -4
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +5 -1
- 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/argument_mismatch.rb +14 -4
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -0
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +88 -14
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +23 -2
- 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 +245 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +17 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +42 -17
- 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/lint.rb +1 -0
- 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/migration/department_name.rb +1 -1
- data/lib/rubocop/cop/mixin/alignment.rb +5 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
- 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 +26 -2
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +31 -3
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- 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 +29 -3
- 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 +4 -2
- data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
- data/lib/rubocop/cop/naming/block_forwarding.rb +4 -1
- data/lib/rubocop/cop/naming/block_parameter_name.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 +10 -2
- data/lib/rubocop/cop/security/json_load.rb +16 -4
- data/lib/rubocop/cop/severity.rb +12 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +10 -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 +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +6 -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 +29 -3
- data/lib/rubocop/cop/style/case_like_if.rb +9 -6
- 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/constant_visibility.rb +6 -2
- data/lib/rubocop/cop/style/data_inheritance.rb +14 -0
- data/lib/rubocop/cop/style/directive_scope.rb +154 -21
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +118 -18
- data/lib/rubocop/cop/style/documentation_method.rb +1 -9
- data/lib/rubocop/cop/style/double_negation.rb +11 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +15 -3
- data/lib/rubocop/cop/style/endless_method.rb +91 -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/file_null.rb +2 -2
- data/lib/rubocop/cop/style/float_division.rb +28 -14
- data/lib/rubocop/cop/style/for.rb +44 -1
- data/lib/rubocop/cop/style/format_string.rb +28 -6
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +13 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +35 -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/magic_comment_format.rb +1 -1
- 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 +36 -12
- 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 +48 -8
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +18 -2
- data/lib/rubocop/cop/style/not.rb +10 -3
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +14 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
- 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 +34 -17
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +10 -2
- data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +23 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +25 -5
- 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_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- 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/struct_inheritance.rb +14 -0
- 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_comma_in_block_args.rb +1 -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/style.rb +0 -1
- data/lib/rubocop/cop/team.rb +10 -5
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -1
- data/lib/rubocop/cops_documentation_generator.rb +23 -2
- data/lib/rubocop/directive_comment.rb +37 -8
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -1
- data/lib/rubocop/formatter/formatter_set.rb +6 -1
- data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
- data/lib/rubocop/formatter/html_formatter.rb +2 -2
- data/lib/rubocop/formatter/json_formatter.rb +71 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -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 +186 -0
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
- data/lib/rubocop/formatter.rb +1 -0
- 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/magic_comment.rb +27 -0
- 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 +97 -4
- data/lib/rubocop/path_util.rb +1 -1
- data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +8 -5
- data/lib/rubocop/result_cache.rb +36 -18
- data/lib/rubocop/runner.rb +160 -49
- data/lib/rubocop/server/cache.rb +2 -2
- data/lib/rubocop/unified_diff.rb +257 -0
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +9 -1
- metadata +21 -6
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
|
@@ -53,6 +53,12 @@ module RuboCop
|
|
|
53
53
|
# @!method hash_from_array?(node)
|
|
54
54
|
def_node_matcher :hash_from_array?, '(send (const {nil? cbase} :Hash) :[] ...)'
|
|
55
55
|
|
|
56
|
+
# A hash literal as the first argument needs the parentheses of the call,
|
|
57
|
+
# which `Style/MethodCallWithArgsParentheses` removes in the same pass.
|
|
58
|
+
def self.autocorrect_incompatible_with
|
|
59
|
+
[Style::MethodCallWithArgsParentheses]
|
|
60
|
+
end
|
|
61
|
+
|
|
56
62
|
def on_send(node)
|
|
57
63
|
return if part_of_ignored_node?(node) || !hash_from_array?(node)
|
|
58
64
|
|
|
@@ -95,12 +101,30 @@ module RuboCop
|
|
|
95
101
|
def register_offense_for_hash(node, hash_argument)
|
|
96
102
|
add_offense(node, message: MSG_LITERAL_HASH_ARG) do |corrector|
|
|
97
103
|
corrector.replace(node, "{#{hash_argument.source}}")
|
|
98
|
-
|
|
99
|
-
parent = node.parent
|
|
100
|
-
add_parentheses(parent, corrector) if parent&.send_type? && !parent.parenthesized?
|
|
104
|
+
add_parentheses_to_parent_call(node, corrector)
|
|
101
105
|
end
|
|
102
106
|
end
|
|
103
107
|
|
|
108
|
+
# Without parentheses, a hash literal at the start of the first argument would be
|
|
109
|
+
# parsed as a block. That includes an argument like `Hash[a, b].merge(c)`.
|
|
110
|
+
def add_parentheses_to_parent_call(node, corrector)
|
|
111
|
+
node = node.parent while starts_parent?(node)
|
|
112
|
+
parent = node.parent
|
|
113
|
+
return unless parent&.type?(:call, :super, :yield)
|
|
114
|
+
return if parent.parenthesized? || operator_syntax?(parent)
|
|
115
|
+
|
|
116
|
+
add_parentheses(parent, corrector)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def starts_parent?(node)
|
|
120
|
+
node.parent && node.parent.source_range.begin_pos == node.source_range.begin_pos
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# `foo[x]`, `foo.bar = x` and `foo == x` take a hash literal as it is.
|
|
124
|
+
def operator_syntax?(call)
|
|
125
|
+
call.setter_method? || (call.operator_method? && !call.loc?(:dot))
|
|
126
|
+
end
|
|
127
|
+
|
|
104
128
|
def register_offense_for_zip_method(node, zip_method)
|
|
105
129
|
add_offense(node, message: MSG_TO_H) do |corrector|
|
|
106
130
|
if zip_method.parenthesized?
|
|
@@ -135,11 +159,7 @@ module RuboCop
|
|
|
135
159
|
def correct_multi_argument(node)
|
|
136
160
|
add_offense(node, message: MSG_LITERAL_MULTI_ARG) do |corrector|
|
|
137
161
|
corrector.replace(node, args_to_hash(node.arguments))
|
|
138
|
-
|
|
139
|
-
parent = node.parent
|
|
140
|
-
if parent&.send_type? && !parent.method?(:to_h) && !parent.parenthesized?
|
|
141
|
-
add_parentheses(parent, corrector)
|
|
142
|
-
end
|
|
162
|
+
add_parentheses_to_parent_call(node, corrector)
|
|
143
163
|
end
|
|
144
164
|
end
|
|
145
165
|
|
|
@@ -34,6 +34,9 @@ module RuboCop
|
|
|
34
34
|
# # good - fetch with block is allowed
|
|
35
35
|
# hash.fetch(key) { default }
|
|
36
36
|
#
|
|
37
|
+
# # good - `ENV.fetch` is left to `Style/FetchEnvVar` when it is enabled
|
|
38
|
+
# ENV.fetch(key)
|
|
39
|
+
#
|
|
37
40
|
# @example EnforcedStyle: fetch
|
|
38
41
|
# # bad
|
|
39
42
|
# hash[key]
|
|
@@ -55,14 +58,20 @@ module RuboCop
|
|
|
55
58
|
|
|
56
59
|
RESTRICT_ON_SEND = %i[[] fetch].freeze
|
|
57
60
|
|
|
61
|
+
# @!method env_const?(node)
|
|
62
|
+
def_node_matcher :env_const?, '(const {nil? cbase} :ENV)'
|
|
63
|
+
|
|
58
64
|
def on_send(node)
|
|
59
65
|
return if (receiver = node.receiver) && allowed_receiver?(receiver)
|
|
66
|
+
return if part_of_ignored_node?(node)
|
|
60
67
|
|
|
61
68
|
if offense_for_brackets?(node)
|
|
69
|
+
ignore_node(node.first_argument)
|
|
62
70
|
add_offense(node.loc.selector, message: BRACKET_MSG) do |corrector|
|
|
63
71
|
correct_fetch_to_brackets(corrector, node)
|
|
64
72
|
end
|
|
65
73
|
elsif offense_for_fetch?(node)
|
|
74
|
+
ignore_node(node.first_argument)
|
|
66
75
|
add_offense(node, message: FETCH_MSG) do |corrector|
|
|
67
76
|
correct_brackets_to_fetch(corrector, node)
|
|
68
77
|
end
|
|
@@ -73,28 +82,45 @@ module RuboCop
|
|
|
73
82
|
private
|
|
74
83
|
|
|
75
84
|
def offense_for_brackets?(node)
|
|
76
|
-
style
|
|
77
|
-
|
|
85
|
+
return false if style != :brackets || !node.receiver
|
|
86
|
+
return false if !node.method?(:fetch) || !node.arguments.one?
|
|
87
|
+
return false if node.block_literal? || node.csend_type?
|
|
88
|
+
|
|
89
|
+
!exempt_from_brackets?(node)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def exempt_from_brackets?(node)
|
|
93
|
+
comment_before_dot?(node) || env_fetch_preferred?(node.receiver)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def comment_before_dot?(node)
|
|
97
|
+
processed_source.contains_comment?(node.receiver.source_range.end.join(node.loc.dot))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def env_fetch_preferred?(receiver)
|
|
101
|
+
env_const?(receiver) && processed_source.registry.enabled?(Style::FetchEnvVar, config)
|
|
78
102
|
end
|
|
79
103
|
|
|
80
104
|
def offense_for_fetch?(node)
|
|
81
|
-
style == :fetch && node.method?(:[]) && node.arguments.one?
|
|
105
|
+
style == :fetch && node.method?(:[]) && node.arguments.one? &&
|
|
106
|
+
!compound_assignment_target?(node)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def compound_assignment_target?(node)
|
|
110
|
+
node.parent&.type?(:op_asgn, :or_asgn, :and_asgn) && node.parent.children.first == node
|
|
82
111
|
end
|
|
83
112
|
|
|
84
113
|
def correct_fetch_to_brackets(corrector, node)
|
|
85
114
|
key = node.first_argument.source
|
|
86
115
|
|
|
87
|
-
corrector.replace(node.
|
|
116
|
+
corrector.replace(node.receiver.source_range.end.join(node.source_range.end), "[#{key}]")
|
|
88
117
|
end
|
|
89
118
|
|
|
90
119
|
def correct_brackets_to_fetch(corrector, node)
|
|
91
120
|
key = node.first_argument.source
|
|
121
|
+
replacement = node.loc.dot ? "fetch(#{key})" : ".fetch(#{key})"
|
|
92
122
|
|
|
93
|
-
|
|
94
|
-
corrector.replace(node.loc.dot.join(node.source_range.end), "&.fetch(#{key})")
|
|
95
|
-
else
|
|
96
|
-
corrector.replace(node.loc.selector.join(node.source_range.end), ".fetch(#{key})")
|
|
97
|
-
end
|
|
123
|
+
corrector.replace(node.loc.selector.join(node.source_range.end), replacement)
|
|
98
124
|
end
|
|
99
125
|
end
|
|
100
126
|
end
|
|
@@ -142,6 +142,13 @@ module RuboCop
|
|
|
142
142
|
MSG_HASH_ROCKETS = 'Use hash rockets syntax.'
|
|
143
143
|
NO_MIXED_KEYS_STYLES = %i[ruby19_no_mixed_keys no_mixed_keys].freeze
|
|
144
144
|
|
|
145
|
+
# Omitting the last hash value of a call without parentheses adds the parentheses,
|
|
146
|
+
# which `Style/MethodCallWithArgsParentheses` and `Style/SuperWithArgsParentheses`
|
|
147
|
+
# would add again in the same pass.
|
|
148
|
+
def self.autocorrect_incompatible_with
|
|
149
|
+
[Style::MethodCallWithArgsParentheses, Style::SuperWithArgsParentheses]
|
|
150
|
+
end
|
|
151
|
+
|
|
145
152
|
def on_hash(node)
|
|
146
153
|
pairs = node.pairs
|
|
147
154
|
|
|
@@ -241,6 +248,8 @@ module RuboCop
|
|
|
241
248
|
def check(pairs, delim, msg)
|
|
242
249
|
pairs.each do |pair|
|
|
243
250
|
if pair.delimiter == delim
|
|
251
|
+
next if pair.value_omission? && keyword_value?(pair)
|
|
252
|
+
|
|
244
253
|
location = pair.source_range.begin.join(pair.loc.operator)
|
|
245
254
|
add_offense(location, message: msg) do |corrector|
|
|
246
255
|
autocorrect(corrector, pair)
|
|
@@ -283,12 +292,16 @@ module RuboCop
|
|
|
283
292
|
end
|
|
284
293
|
|
|
285
294
|
def autocorrect_hash_rockets(corrector, pair_node)
|
|
286
|
-
op = pair_node.loc.operator
|
|
287
|
-
|
|
288
295
|
key_with_hash_rocket = ":#{pair_node.key.source}#{pair_node.inverse_delimiter(true)}"
|
|
289
296
|
key_with_hash_rocket += pair_node.key.source if pair_node.value_omission?
|
|
290
297
|
corrector.replace(pair_node.key, key_with_hash_rocket)
|
|
291
|
-
corrector.remove(
|
|
298
|
+
corrector.remove(operator_range(pair_node))
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def operator_range(pair_node)
|
|
302
|
+
op = pair_node.loc.operator
|
|
303
|
+
|
|
304
|
+
range_with_surrounding_space(op, newlines: !pair_node.value_omission?)
|
|
292
305
|
end
|
|
293
306
|
|
|
294
307
|
def autocorrect_no_mixed_keys(corrector, pair_node)
|
|
@@ -188,7 +188,7 @@ module RuboCop
|
|
|
188
188
|
end
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
-
# rubocop:disable-next Metrics/
|
|
191
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
192
192
|
def check_expressions(node, expressions, insert_position)
|
|
193
193
|
return if expressions.any?(&:nil?)
|
|
194
194
|
|
|
@@ -198,8 +198,7 @@ module RuboCop
|
|
|
198
198
|
add_offense(expression) do |corrector|
|
|
199
199
|
next if node.if_type? && (node.ternary? || node.then?)
|
|
200
200
|
|
|
201
|
-
|
|
202
|
-
corrector.remove(range)
|
|
201
|
+
corrector.remove(removal_range(expression))
|
|
203
202
|
next if inserted_expression
|
|
204
203
|
|
|
205
204
|
if node.parent&.assignment?
|
|
@@ -213,6 +212,26 @@ module RuboCop
|
|
|
213
212
|
end
|
|
214
213
|
end
|
|
215
214
|
|
|
215
|
+
def removal_range(expression)
|
|
216
|
+
range = expression.source_range
|
|
217
|
+
whole_lines = range_by_whole_lines(range, include_final_newline: true)
|
|
218
|
+
return whole_lines if whole_lines.source.strip == expression.source
|
|
219
|
+
|
|
220
|
+
range_with_separator(range)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def range_with_separator(range)
|
|
224
|
+
source = range.source_buffer.source
|
|
225
|
+
|
|
226
|
+
if (following = source[range.end_pos..][/\A[ \t]*;[ \t]*/])
|
|
227
|
+
range.adjust(end_pos: following.length)
|
|
228
|
+
elsif (preceding = source[0...range.begin_pos][/[ \t]*;[ \t]*\z/])
|
|
229
|
+
range.adjust(begin_pos: -preceding.length)
|
|
230
|
+
else
|
|
231
|
+
range_with_surrounding_space(range, side: :right, newlines: false)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
216
235
|
def correct_assignment(corrector, node, expression, insert_position)
|
|
217
236
|
indentation = indentation_of(node.parent)
|
|
218
237
|
|
|
@@ -75,7 +75,7 @@ module RuboCop
|
|
|
75
75
|
return if comments_between_else_and_if?(node, else_branch)
|
|
76
76
|
|
|
77
77
|
add_offense(else_branch.loc.keyword) do |corrector|
|
|
78
|
-
next if part_of_ignored_node?(node)
|
|
78
|
+
next if part_of_ignored_node?(node) || shares_lines_with_other_code?(else_branch)
|
|
79
79
|
|
|
80
80
|
autocorrect(corrector, else_branch)
|
|
81
81
|
ignore_node(node)
|
|
@@ -84,6 +84,26 @@ module RuboCop
|
|
|
84
84
|
|
|
85
85
|
private
|
|
86
86
|
|
|
87
|
+
# The `elsif` correction moves and removes whole lines, so it can't be applied when
|
|
88
|
+
# the nested `if` condition, its `if` branch or its `end` shares a line with other code.
|
|
89
|
+
# A modifier `if` on the `else` line would leave its body on the `elsif` line.
|
|
90
|
+
def shares_lines_with_other_code?(node)
|
|
91
|
+
return false if node.then?
|
|
92
|
+
return !begins_its_line?(node.source_range) if node.modifier_form?
|
|
93
|
+
|
|
94
|
+
moved_ranges(node).any? { |range| !begins_its_line?(range) || !ends_its_line?(range) }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def moved_ranges(node)
|
|
98
|
+
ranges = [if_condition_range(node, node.condition), find_end_range(node)]
|
|
99
|
+
ranges << range_with_comments(node.if_branch) if node.if_branch
|
|
100
|
+
ranges
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def ends_its_line?(range)
|
|
104
|
+
processed_source.lines[range.last_line - 1][range.last_column..].match?(/\A\s*(#|\z)/)
|
|
105
|
+
end
|
|
106
|
+
|
|
87
107
|
def autocorrect(corrector, node)
|
|
88
108
|
if node.then?
|
|
89
109
|
# If the nested `if` is a then node, correct it first,
|
|
@@ -159,7 +159,7 @@ module RuboCop
|
|
|
159
159
|
corrector.replace(node, replacement)
|
|
160
160
|
end
|
|
161
161
|
|
|
162
|
-
def replacement_for_modifier_form(corrector, node)
|
|
162
|
+
def replacement_for_modifier_form(corrector, node)
|
|
163
163
|
comment = comment_on_node_line(node)
|
|
164
164
|
if comment && too_long_due_to_comment_after_modifier?(node, comment)
|
|
165
165
|
remove_comment(corrector, node, comment)
|
|
@@ -167,12 +167,11 @@ module RuboCop
|
|
|
167
167
|
return to_modifier_form_with_move_comment(node, indent(node), comment)
|
|
168
168
|
end
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
remove_heredoc(corrector, heredoc)
|
|
170
|
+
heredoc_ranges = heredoc_ranges_in(node.if_branch)
|
|
171
|
+
unless heredoc_ranges.empty?
|
|
172
|
+
remove_heredoc(corrector, heredoc_ranges)
|
|
174
173
|
|
|
175
|
-
return to_normal_form_with_heredoc(node, indent(node),
|
|
174
|
+
return to_normal_form_with_heredoc(node, indent(node), heredoc_ranges)
|
|
176
175
|
end
|
|
177
176
|
|
|
178
177
|
to_normal_form(node, indent(node))
|
|
@@ -275,14 +274,19 @@ module RuboCop
|
|
|
275
274
|
RUBY
|
|
276
275
|
end
|
|
277
276
|
|
|
278
|
-
def
|
|
279
|
-
|
|
277
|
+
def remove_heredoc(corrector, heredoc_ranges)
|
|
278
|
+
heredoc_ranges.each do |range|
|
|
279
|
+
corrector.remove(range_by_whole_lines(range, include_final_newline: true))
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def to_normal_form_with_heredoc(node, indentation, heredoc_ranges)
|
|
284
|
+
heredoc_lines = heredoc_ranges.map(&:source)
|
|
280
285
|
|
|
281
286
|
<<~RUBY.chomp
|
|
282
287
|
#{node.keyword} #{node.condition.source}
|
|
283
288
|
#{indentation} #{node.body.source}
|
|
284
|
-
#{
|
|
285
|
-
#{indentation} #{heredoc_end.source.chomp}
|
|
289
|
+
#{heredoc_lines.join("\n")}
|
|
286
290
|
#{indentation}end
|
|
287
291
|
RUBY
|
|
288
292
|
end
|
|
@@ -294,17 +298,12 @@ module RuboCop
|
|
|
294
298
|
RUBY
|
|
295
299
|
end
|
|
296
300
|
|
|
297
|
-
def
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
[heredoc_body, heredoc_end]
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
def remove_heredoc(corrector, heredoc)
|
|
305
|
-
heredoc.each do |range|
|
|
306
|
-
corrector.remove(range_by_whole_lines(range, include_final_newline: true))
|
|
301
|
+
def heredoc_ranges_in(body)
|
|
302
|
+
ranges = body.each_node(:any_str).select(&:heredoc?).map do |heredoc|
|
|
303
|
+
range_by_whole_lines(heredoc.loc.heredoc_body.join(heredoc.loc.heredoc_end))
|
|
307
304
|
end
|
|
305
|
+
# A heredoc opened in another heredoc's interpolation is moved along with it.
|
|
306
|
+
ranges.reject { |range| ranges.any? { |other| other.contains?(range) } }
|
|
308
307
|
end
|
|
309
308
|
|
|
310
309
|
def comment_on_node_line(node)
|
|
@@ -28,6 +28,10 @@ module RuboCop
|
|
|
28
28
|
|
|
29
29
|
MSG = 'Avoid modifier `%<keyword>s` after another conditional.'
|
|
30
30
|
|
|
31
|
+
def self.autocorrect_incompatible_with
|
|
32
|
+
[Style::SoleNestedConditional]
|
|
33
|
+
end
|
|
34
|
+
|
|
31
35
|
# rubocop:disable-next Metrics/AbcSize
|
|
32
36
|
def on_if(node)
|
|
33
37
|
return unless node.modifier_form? && node.body.if_type?
|
|
@@ -21,6 +21,10 @@ module RuboCop
|
|
|
21
21
|
MSG_NEWLINE = 'Do not use `%<keyword>s %<expr>s;` - use a newline instead.'
|
|
22
22
|
MSG_TERNARY = 'Do not use `%<keyword>s %<expr>s;` - use a ternary operator instead.'
|
|
23
23
|
|
|
24
|
+
LOWER_PRECEDENCE_THAN_TERNARY_TYPES = %i[
|
|
25
|
+
and or if rescue any_match_pattern while until while_post until_post
|
|
26
|
+
].freeze
|
|
27
|
+
|
|
24
28
|
def on_normal_if_unless(node)
|
|
25
29
|
return if node.parent&.if_type?
|
|
26
30
|
return if part_of_ignored_node?(node)
|
|
@@ -77,12 +81,14 @@ module RuboCop
|
|
|
77
81
|
def replacement(node)
|
|
78
82
|
return correct_elsif(node) if node.else_branch&.if_type?
|
|
79
83
|
|
|
80
|
-
then_code = node.if_branch ?
|
|
81
|
-
else_code = node.else_branch ?
|
|
84
|
+
then_code = node.if_branch ? ternary_operand(node.if_branch) : 'nil'
|
|
85
|
+
else_code = node.else_branch ? ternary_operand(node.else_branch) : 'nil'
|
|
82
86
|
|
|
83
87
|
then_code, else_code = else_code, then_code if node.unless?
|
|
84
88
|
|
|
85
|
-
"#{ternary_condition(node)} ? #{then_code} : #{else_code}"
|
|
89
|
+
ternary = "#{ternary_condition(node)} ? #{then_code} : #{else_code}"
|
|
90
|
+
|
|
91
|
+
operand_of_parent?(node) ? "(#{ternary})" : ternary
|
|
86
92
|
end
|
|
87
93
|
|
|
88
94
|
def correct_elsif(node)
|
|
@@ -108,7 +114,34 @@ module RuboCop
|
|
|
108
114
|
# `(a = b) ? c : d`), changing what gets assigned.
|
|
109
115
|
def ternary_condition(node)
|
|
110
116
|
condition = node.condition
|
|
111
|
-
condition.assignment? ? "(#{condition.source})" : condition
|
|
117
|
+
condition.assignment? ? "(#{condition.source})" : ternary_operand(condition)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def ternary_operand(expr)
|
|
121
|
+
lower_precedence_than_ternary?(expr) ? "(#{expr.source})" : build_expression(expr)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Expressions that bind looser than `?:` (or cannot appear unparenthesized
|
|
125
|
+
# inside it) would otherwise absorb or break the ternary.
|
|
126
|
+
def lower_precedence_than_ternary?(node)
|
|
127
|
+
return true if node.type?(*LOWER_PRECEDENCE_THAN_TERNARY_TYPES)
|
|
128
|
+
return true if node.send_type? && (node.prefix_not? || prefix_bang_on_command?(node))
|
|
129
|
+
|
|
130
|
+
node.type?(:yield, :super, :defined?) && node.arguments.any? && !node.parenthesized?
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def operand_of_parent?(node)
|
|
134
|
+
return false unless (parent = node.parent)
|
|
135
|
+
return true if parent.operator_keyword?
|
|
136
|
+
|
|
137
|
+
parent.call_type? && call_operand?(parent, node)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def call_operand?(call, node)
|
|
141
|
+
return false if call.prefix_not?
|
|
142
|
+
return true if call.receiver.equal?(node)
|
|
143
|
+
|
|
144
|
+
call.operator_method? && !call.method?(:[]) && !call.method?(:[]=)
|
|
112
145
|
end
|
|
113
146
|
|
|
114
147
|
def build_else_branch(second_condition)
|
|
@@ -131,6 +164,16 @@ module RuboCop
|
|
|
131
164
|
result
|
|
132
165
|
end
|
|
133
166
|
|
|
167
|
+
# `!foo a` leaves the arguments of `foo` unparenthesized at the end of the operand,
|
|
168
|
+
# where they would absorb the rest of the ternary.
|
|
169
|
+
def prefix_bang_on_command?(node)
|
|
170
|
+
return false unless node.prefix_bang?
|
|
171
|
+
|
|
172
|
+
receiver = node.receiver
|
|
173
|
+
|
|
174
|
+
require_argument_parentheses?(receiver) || lower_precedence_than_ternary?(receiver)
|
|
175
|
+
end
|
|
176
|
+
|
|
134
177
|
def require_argument_parentheses?(node)
|
|
135
178
|
return false if !node.call_type? || node.arithmetic_operation?
|
|
136
179
|
|
|
@@ -114,9 +114,31 @@ module RuboCop
|
|
|
114
114
|
method_call, _lhs, method, _rhs = inverse_candidate?(node)
|
|
115
115
|
return unless method_call && method
|
|
116
116
|
|
|
117
|
-
corrector
|
|
117
|
+
remove_negation(corrector, node, method, method_call)
|
|
118
118
|
corrector.replace(method_call.loc.selector, inverse_methods[method].to_s)
|
|
119
|
-
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def remove_negation(corrector, node, method, method_call)
|
|
122
|
+
if !keep_parentheses?(node, method_call)
|
|
123
|
+
corrector.remove(not_to_receiver(node, method_call))
|
|
124
|
+
remove_end_parenthesis(corrector, node, method, method_call)
|
|
125
|
+
elsif node.parenthesized?
|
|
126
|
+
corrector.remove(node.loc.selector)
|
|
127
|
+
else
|
|
128
|
+
corrector.remove(node.loc.selector.join(node.receiver.source_range.begin))
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def keep_parentheses?(node, method_call)
|
|
133
|
+
return false unless node.receiver.begin_type? || node.parenthesized?
|
|
134
|
+
return false unless method_call.operator_method?
|
|
135
|
+
return false unless (parent = node.parent)&.call_type?
|
|
136
|
+
|
|
137
|
+
binary_operator?(parent) || parent.receiver.equal?(node)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def binary_operator?(node)
|
|
141
|
+
node.operator_method? && !node.loc.dot && !node.method?(:[]) && !node.method?(:[]=)
|
|
120
142
|
end
|
|
121
143
|
|
|
122
144
|
def correct_inverse_block(corrector, node)
|
|
@@ -61,6 +61,12 @@ module RuboCop
|
|
|
61
61
|
|
|
62
62
|
minimum_target_ruby_version 3.4
|
|
63
63
|
|
|
64
|
+
# `Style/StabbyLambdaParentheses` wraps the parameter this cop removes in the same pass,
|
|
65
|
+
# which would leave an empty parameter list that forbids `it`.
|
|
66
|
+
def self.autocorrect_incompatible_with
|
|
67
|
+
[Style::Lambda, Style::StabbyLambdaParentheses]
|
|
68
|
+
end
|
|
69
|
+
|
|
64
70
|
def on_block(node)
|
|
65
71
|
return unless style == :always
|
|
66
72
|
return unless node.arguments.one?
|
|
@@ -68,9 +74,10 @@ module RuboCop
|
|
|
68
74
|
# `restarg`, `kwrestarg`, `blockarg` nodes can return early.
|
|
69
75
|
return unless node.first_argument.arg_type?
|
|
70
76
|
|
|
71
|
-
|
|
77
|
+
block_argument_name = node.first_argument.source
|
|
78
|
+
return if used_within_inner_block?(node.body, block_argument_name)
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
find_block_variables(node, block_argument_name).each do |variable|
|
|
74
81
|
add_offense(variable, message: MSG_USE_IT_PARAMETER) do |corrector|
|
|
75
82
|
corrector.remove(node.arguments)
|
|
76
83
|
corrector.replace(variable, 'it')
|
|
@@ -111,7 +118,29 @@ module RuboCop
|
|
|
111
118
|
def find_block_variables(node, block_argument_name)
|
|
112
119
|
return [] unless node.body
|
|
113
120
|
|
|
114
|
-
node.body
|
|
121
|
+
ranges = inner_block_ranges(node.body)
|
|
122
|
+
|
|
123
|
+
block_variables(node.body, block_argument_name).reject do |variable|
|
|
124
|
+
ranges.any? { |range| range.contains?(variable.source_range) }
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def inner_block_ranges(body)
|
|
129
|
+
body.each_node(:any_block).map { |block| block.loc.begin.join(block.loc.end) }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def used_within_inner_block?(body, block_argument_name)
|
|
133
|
+
return false unless body
|
|
134
|
+
|
|
135
|
+
ranges = inner_block_ranges(body)
|
|
136
|
+
|
|
137
|
+
block_variables(body, block_argument_name).any? do |variable|
|
|
138
|
+
ranges.any? { |range| range.contains?(variable.source_range) }
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def block_variables(body, block_argument_name)
|
|
143
|
+
body.each_descendant(:lvar).select do |descendant|
|
|
115
144
|
descendant.source == block_argument_name
|
|
116
145
|
end
|
|
117
146
|
end
|
|
@@ -75,7 +75,9 @@ module RuboCop
|
|
|
75
75
|
|
|
76
76
|
def remove_kwargs(kwarg_nodes, corrector)
|
|
77
77
|
kwarg_nodes.each do |kwarg|
|
|
78
|
-
|
|
78
|
+
range = range_with_surrounding_space(kwarg.source_range, side: :left, whitespace: true)
|
|
79
|
+
with_space = range_with_surrounding_space(range, side: :right)
|
|
80
|
+
|
|
79
81
|
corrector.remove(range_with_surrounding_comma(with_space, :left))
|
|
80
82
|
end
|
|
81
83
|
end
|
|
@@ -48,6 +48,8 @@ module RuboCop
|
|
|
48
48
|
# end
|
|
49
49
|
class Lambda < Base
|
|
50
50
|
include ConfigurableEnforcedStyle
|
|
51
|
+
include PatternMatchingHelp
|
|
52
|
+
include RescueNode
|
|
51
53
|
extend AutoCorrector
|
|
52
54
|
|
|
53
55
|
LITERAL_MESSAGE = 'Use the `-> { ... }` lambda literal syntax for %<modifier>s lambdas.'
|
|
@@ -71,6 +73,7 @@ module RuboCop
|
|
|
71
73
|
selector = node.send_node.source
|
|
72
74
|
|
|
73
75
|
return unless offending_selector?(node, selector)
|
|
76
|
+
return if uncorrectable_lambda_literal?(node)
|
|
74
77
|
|
|
75
78
|
add_offense(node.send_node, message: message(node, selector)) do |corrector|
|
|
76
79
|
if node.send_node.lambda_literal?
|
|
@@ -91,6 +94,21 @@ module RuboCop
|
|
|
91
94
|
selector == OFFENDING_SELECTORS[:style][style][lines]
|
|
92
95
|
end
|
|
93
96
|
|
|
97
|
+
def uncorrectable_lambda_literal?(node)
|
|
98
|
+
return false unless node.send_node.lambda_literal?
|
|
99
|
+
return true if in_pattern?(node)
|
|
100
|
+
return false unless rescue_or_ensure_clause?(node.body)
|
|
101
|
+
|
|
102
|
+
LambdaLiteralToMethodCorrector.new(node).replace_delimiters?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def rescue_or_ensure_clause?(body)
|
|
106
|
+
return false unless body
|
|
107
|
+
return true if body.ensure_type?
|
|
108
|
+
|
|
109
|
+
body.rescue_type? && !rescue_modifier?(body.resbody_branches.first)
|
|
110
|
+
end
|
|
111
|
+
|
|
94
112
|
def message(node, selector)
|
|
95
113
|
message = selector == '->' ? METHOD_MESSAGE : LITERAL_MESSAGE
|
|
96
114
|
|
|
@@ -28,8 +28,9 @@ module RuboCop
|
|
|
28
28
|
def on_send(node)
|
|
29
29
|
return unless node.receiver
|
|
30
30
|
# Rewriting the call rebuilds it as a single expression, which would drop
|
|
31
|
-
# any comments inside the argument list, so leave it to be
|
|
32
|
-
|
|
31
|
+
# any comments or heredoc bodies inside the argument list, so leave it to be
|
|
32
|
+
# fixed manually.
|
|
33
|
+
return if comments_in_node?(node) || heredoc_argument?(node)
|
|
33
34
|
|
|
34
35
|
if offense?(node)
|
|
35
36
|
prefer = prefer(node)
|
|
@@ -59,6 +60,10 @@ module RuboCop
|
|
|
59
60
|
end
|
|
60
61
|
end
|
|
61
62
|
|
|
63
|
+
def heredoc_argument?(node)
|
|
64
|
+
node.arguments.any? { |argument| argument.each_node(:any_str).any?(&:heredoc?) }
|
|
65
|
+
end
|
|
66
|
+
|
|
62
67
|
def offense?(node)
|
|
63
68
|
(explicit_style? && node.implicit_call?) || (implicit_style? && !node.implicit_call?)
|
|
64
69
|
end
|
|
@@ -187,7 +187,7 @@ module RuboCop
|
|
|
187
187
|
issues[:directives] << directive if directive_offends?(directive)
|
|
188
188
|
end
|
|
189
189
|
|
|
190
|
-
comment.values.each do |value| # rubocop:disable Style/HashEachMethods
|
|
190
|
+
comment.values.each do |value| # rubocop:disable Style/HashEachMethods -- the receiver is a magic comment, not a Hash
|
|
191
191
|
issues[:values] << value if wrong_capitalization?(value.source, value_capitalization)
|
|
192
192
|
end
|
|
193
193
|
|
|
@@ -112,8 +112,7 @@ module RuboCop
|
|
|
112
112
|
|
|
113
113
|
def on_block(node)
|
|
114
114
|
return unless each_block_with_push?(node)
|
|
115
|
-
|
|
116
|
-
dest_var = find_dest_var(node)
|
|
115
|
+
return unless (dest_var = find_dest_var(node))
|
|
117
116
|
|
|
118
117
|
if offending_empty_array_tap?(node, dest_var)
|
|
119
118
|
asgn = dest_var.declaration_node
|