rubocop 1.71.1 → 1.92.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +23 -19
- data/config/default.yml +886 -168
- data/config/internal_affairs.yml +20 -0
- data/config/obsoletion.yml +47 -4
- data/exe/rubocop +2 -9
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cached_data.rb +50 -5
- data/lib/rubocop/changed_files.rb +134 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +54 -3
- data/lib/rubocop/cli/command/explain.rb +34 -0
- data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
- data/lib/rubocop/cli/command/lsp.rb +1 -1
- data/lib/rubocop/cli/command/mcp.rb +19 -0
- data/lib/rubocop/cli/command/show_cops.rb +8 -2
- data/lib/rubocop/cli/command/show_docs_url.rb +8 -10
- data/lib/rubocop/cli/command/suggest_extensions.rb +8 -2
- data/lib/rubocop/cli.rb +59 -17
- data/lib/rubocop/comment_config/directive_range.rb +34 -0
- data/lib/rubocop/comment_config/disable_next.rb +143 -0
- data/lib/rubocop/comment_config/push_pop.rb +55 -0
- data/lib/rubocop/comment_config.rb +98 -45
- data/lib/rubocop/config.rb +137 -19
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader.rb +75 -49
- data/lib/rubocop/config_loader_resolver.rb +124 -33
- data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +6 -3
- data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
- data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
- data/lib/rubocop/config_obsoletion.rb +47 -3
- data/lib/rubocop/config_store.rb +7 -2
- data/lib/rubocop/config_validator.rb +75 -12
- data/lib/rubocop/cop/autocorrect_logic.rb +43 -17
- data/lib/rubocop/cop/badge.rb +10 -2
- data/lib/rubocop/cop/base.rb +128 -35
- data/lib/rubocop/cop/bundler/gem_comment.rb +5 -4
- data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
- data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -11
- data/lib/rubocop/cop/bundler.rb +19 -0
- data/lib/rubocop/cop/commissioner.rb +13 -11
- data/lib/rubocop/cop/cop_documentation.rb +81 -0
- data/lib/rubocop/cop/cop_explanation.rb +140 -0
- data/lib/rubocop/cop/corrector.rb +4 -4
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +92 -11
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -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/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +31 -4
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +35 -5
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +73 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors.rb +28 -0
- data/lib/rubocop/cop/documentation.rb +3 -4
- data/lib/rubocop/cop/exclude_limit.rb +31 -5
- data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
- data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +49 -17
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +2 -9
- data/lib/rubocop/cop/gemspec/require_mfa.rb +22 -5
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
- data/lib/rubocop/cop/gemspec.rb +22 -0
- data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
- data/lib/rubocop/cop/generator.rb +5 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
- data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
- data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +142 -0
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +16 -20
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +6 -2
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +2 -2
- data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
- data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
- data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
- data/lib/rubocop/cop/internal_affairs.rb +3 -16
- data/lib/rubocop/cop/layout/argument_alignment.rb +9 -3
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +86 -4
- data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +28 -10
- data/lib/rubocop/cop/layout/class_structure.rb +191 -41
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
- data/lib/rubocop/cop/layout/comment_indentation.rb +17 -7
- data/lib/rubocop/cop/layout/condition_position.rb +13 -3
- data/lib/rubocop/cop/layout/def_end_alignment.rb +5 -1
- data/lib/rubocop/cop/layout/dot_position.rb +27 -17
- data/lib/rubocop/cop/layout/else_alignment.rb +3 -15
- data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +27 -9
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +21 -8
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +46 -21
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +34 -4
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +22 -5
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +17 -3
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
- data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
- data/lib/rubocop/cop/layout/end_alignment.rb +23 -15
- data/lib/rubocop/cop/layout/extra_spacing.rb +109 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +82 -3
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +18 -5
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +41 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +36 -23
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
- 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 +20 -18
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +9 -5
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +48 -3
- data/lib/rubocop/cop/layout/indentation_consistency.rb +22 -5
- data/lib/rubocop/cop/layout/indentation_style.rb +5 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +159 -12
- data/lib/rubocop/cop/layout/leading_comment_space.rb +40 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +10 -4
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/line_length.rb +300 -31
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +69 -57
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +8 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +11 -1
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +65 -56
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +7 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +270 -40
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
- data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +111 -7
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +29 -9
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
- data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
- data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
- data/lib/rubocop/cop/layout/space_around_keyword.rb +20 -3
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +30 -4
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +5 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +6 -39
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +55 -36
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +32 -8
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -12
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/layout.rb +114 -0
- data/lib/rubocop/cop/lazy_loader.rb +41 -0
- data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -17
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +72 -1
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +3 -11
- data/lib/rubocop/cop/lint/ambiguous_range.rb +6 -2
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +6 -1
- data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +15 -1
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -8
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
- data/lib/rubocop/cop/lint/constant_reassignment.rb +94 -15
- data/lib/rubocop/cop/lint/constant_resolution.rb +31 -6
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +240 -0
- data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
- data/lib/rubocop/cop/lint/debugger.rb +13 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
- data/lib/rubocop/cop/lint/deprecated_reference.rb +194 -0
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +506 -41
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/else_layout.rb +19 -0
- data/lib/rubocop/cop/lint/empty_block.rb +4 -4
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +22 -65
- data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
- data/lib/rubocop/cop/lint/empty_when.rb +8 -1
- data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -8
- data/lib/rubocop/cop/lint/float_comparison.rb +33 -10
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +4 -0
- data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
- data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
- data/lib/rubocop/cop/lint/interpolation_check.rb +25 -6
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +152 -11
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +75 -37
- 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 +60 -23
- data/lib/rubocop/cop/lint/missing_super.rb +31 -1
- data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
- data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
- data/lib/rubocop/cop/lint/name_typo.rb +270 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +20 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +4 -4
- data/lib/rubocop/cop/lint/number_conversion.rb +22 -11
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +11 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -4
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +20 -14
- data/lib/rubocop/cop/lint/raise_exception.rb +30 -11
- data/lib/rubocop/cop/lint/rand_one.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +160 -39
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +53 -19
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +28 -6
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +5 -25
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +134 -12
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +13 -4
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +267 -0
- data/lib/rubocop/cop/lint/redundant_with_index.rb +5 -3
- data/lib/rubocop/cop/lint/redundant_with_object.rb +8 -0
- data/lib/rubocop/cop/lint/refinement_import_methods.rb +8 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +9 -1
- data/lib/rubocop/cop/lint/require_parentheses.rb +13 -4
- data/lib/rubocop/cop/lint/require_range_parentheses.rb +3 -2
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +7 -5
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/rescue_type.rb +2 -2
- data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +28 -4
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +56 -6
- data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
- data/lib/rubocop/cop/lint/script_permission.rb +5 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +63 -6
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -1
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +14 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
- data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +122 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +22 -4
- data/lib/rubocop/cop/lint/syntax.rb +25 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +73 -5
- data/lib/rubocop/cop/lint/to_json.rb +20 -17
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +5 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +54 -11
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +16 -9
- data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
- data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
- data/lib/rubocop/cop/lint/unused_private_method.rb +234 -0
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +31 -6
- data/lib/rubocop/cop/lint/useless_assignment.rb +63 -27
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +107 -0
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +92 -0
- data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +11 -10
- data/lib/rubocop/cop/lint/useless_or.rb +111 -0
- data/lib/rubocop/cop/lint/useless_rescue.rb +2 -3
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +13 -7
- data/lib/rubocop/cop/lint/useless_setter_call.rb +11 -5
- data/lib/rubocop/cop/lint/useless_times.rb +22 -1
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +201 -0
- data/lib/rubocop/cop/lint/void.rb +68 -22
- data/lib/rubocop/cop/lint.rb +179 -0
- data/lib/rubocop/cop/message_annotator.rb +7 -3
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/metrics/block_length.rb +2 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
- data/lib/rubocop/cop/metrics/class_length.rb +4 -2
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
- data/lib/rubocop/cop/metrics/method_length.rb +3 -2
- data/lib/rubocop/cop/metrics/module_length.rb +4 -2
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +37 -7
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
- data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
- data/lib/rubocop/cop/metrics.rb +31 -0
- data/lib/rubocop/cop/migration/department_name.rb +11 -5
- data/lib/rubocop/cop/migration.rb +13 -0
- data/lib/rubocop/cop/mixin/alignment.rb +7 -3
- data/lib/rubocop/cop/mixin/allowed_methods.rb +5 -5
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -5
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +50 -28
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +13 -9
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +2 -3
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
- data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +13 -2
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +105 -0
- data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
- data/lib/rubocop/cop/mixin/forbidden_pattern.rb +20 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
- data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +68 -21
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +52 -25
- data/lib/rubocop/cop/mixin/hash_subset.rb +28 -6
- data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +32 -78
- data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
- data/lib/rubocop/cop/mixin/line_length_help.rb +52 -11
- data/lib/rubocop/cop/mixin/method_complexity.rb +2 -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_expression_indentation.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +10 -1
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +2 -2
- data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +79 -8
- data/lib/rubocop/cop/mixin/project_index_help.rb +203 -0
- data/lib/rubocop/cop/mixin/range_help.rb +16 -5
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +181 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +69 -12
- data/lib/rubocop/cop/mixin/string_help.rb +1 -1
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +23 -6
- data/lib/rubocop/cop/mixin/visibility_help.rb +2 -1
- data/lib/rubocop/cop/mixin.rb +93 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +8 -0
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +17 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +7 -4
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/file_name.rb +6 -5
- 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/inclusive_language.rb +8 -2
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +13 -6
- data/lib/rubocop/cop/naming/method_name.rb +190 -15
- data/lib/rubocop/cop/naming/predicate_method.rb +330 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +65 -8
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -7
- data/lib/rubocop/cop/naming/variable_name.rb +51 -6
- data/lib/rubocop/cop/naming/variable_number.rb +3 -1
- data/lib/rubocop/cop/naming.rb +31 -0
- data/lib/rubocop/cop/offense.rb +108 -9
- data/lib/rubocop/cop/registry.rb +234 -65
- data/lib/rubocop/cop/security/eval.rb +17 -3
- data/lib/rubocop/cop/security/io_methods.rb +2 -2
- data/lib/rubocop/cop/security/json_load.rb +45 -11
- data/lib/rubocop/cop/security/marshal_load.rb +1 -1
- data/lib/rubocop/cop/security/open.rb +1 -0
- data/lib/rubocop/cop/security.rb +19 -0
- data/lib/rubocop/cop/severity.rb +12 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +83 -14
- data/lib/rubocop/cop/style/accessor_grouping.rb +47 -10
- data/lib/rubocop/cop/style/alias.rb +33 -8
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
- data/lib/rubocop/cop/style/and_or.rb +8 -3
- data/lib/rubocop/cop/style/arguments_forwarding.rb +80 -39
- data/lib/rubocop/cop/style/array_first_last.rb +13 -3
- data/lib/rubocop/cop/style/array_intersect.rb +136 -38
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +50 -0
- data/lib/rubocop/cop/style/array_join.rb +4 -2
- data/lib/rubocop/cop/style/ascii_comments.rb +6 -3
- data/lib/rubocop/cop/style/attr.rb +8 -6
- data/lib/rubocop/cop/style/bare_percent_literals.rb +4 -3
- data/lib/rubocop/cop/style/begin_block.rb +3 -1
- data/lib/rubocop/cop/style/bitwise_predicate.rb +13 -5
- data/lib/rubocop/cop/style/block_delimiters.rb +77 -40
- data/lib/rubocop/cop/style/case_equality.rb +29 -15
- data/lib/rubocop/cop/style/case_like_if.rb +12 -11
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +181 -27
- data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -14
- data/lib/rubocop/cop/style/class_methods_definitions.rb +26 -5
- data/lib/rubocop/cop/style/collection_compact.rb +37 -17
- data/lib/rubocop/cop/style/collection_methods.rb +1 -0
- data/lib/rubocop/cop/style/collection_querying.rb +200 -0
- data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
- data/lib/rubocop/cop/style/combinable_loops.rb +92 -9
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
- data/lib/rubocop/cop/style/comparable_between.rb +78 -0
- data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +65 -9
- data/lib/rubocop/cop/style/conditional_assignment.rb +58 -24
- data/lib/rubocop/cop/style/constant_visibility.rb +23 -12
- data/lib/rubocop/cop/style/copyright.rb +27 -12
- data/lib/rubocop/cop/style/data_inheritance.rb +25 -0
- data/lib/rubocop/cop/style/date_time.rb +4 -4
- data/lib/rubocop/cop/style/def_with_parentheses.rb +22 -5
- data/lib/rubocop/cop/style/dig_chain.rb +6 -1
- data/lib/rubocop/cop/style/dir_empty.rb +4 -0
- data/lib/rubocop/cop/style/directive_scope.rb +304 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +184 -20
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
- data/lib/rubocop/cop/style/documentation.rb +53 -6
- data/lib/rubocop/cop/style/documentation_method.rb +8 -12
- data/lib/rubocop/cop/style/double_negation.rb +14 -3
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +4 -3
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_case_condition.rb +13 -4
- data/lib/rubocop/cop/style/empty_class_definition.rb +126 -0
- data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +12 -3
- data/lib/rubocop/cop/style/empty_method.rb +15 -9
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +152 -0
- data/lib/rubocop/cop/style/encoding.rb +7 -1
- data/lib/rubocop/cop/style/end_block.rb +3 -1
- data/lib/rubocop/cop/style/endless_method.rb +256 -19
- data/lib/rubocop/cop/style/env_home.rb +4 -0
- data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
- data/lib/rubocop/cop/style/even_odd.rb +11 -1
- data/lib/rubocop/cop/style/exact_regexp_match.rb +52 -8
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
- data/lib/rubocop/cop/style/explicit_block_argument.rb +62 -9
- data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
- data/lib/rubocop/cop/style/fetch_env_var.rb +33 -7
- data/lib/rubocop/cop/style/file_null.rb +6 -4
- data/lib/rubocop/cop/style/file_open.rb +84 -0
- data/lib/rubocop/cop/style/file_write.rb +21 -16
- data/lib/rubocop/cop/style/float_division.rb +43 -15
- data/lib/rubocop/cop/style/for.rb +61 -1
- data/lib/rubocop/cop/style/format_string.rb +44 -9
- data/lib/rubocop/cop/style/format_string_token.rb +86 -16
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +5 -3
- data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
- data/lib/rubocop/cop/style/global_vars.rb +5 -2
- data/lib/rubocop/cop/style/guard_clause.rb +58 -40
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +31 -9
- data/lib/rubocop/cop/style/hash_conversion.rb +52 -16
- data/lib/rubocop/cop/style/hash_each_methods.rb +4 -4
- data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
- data/lib/rubocop/cop/style/hash_lookup_method.rb +128 -0
- data/lib/rubocop/cop/style/hash_slice.rb +16 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +23 -6
- data/lib/rubocop/cop/style/hash_transform_keys.rb +19 -9
- data/lib/rubocop/cop/style/hash_transform_values.rb +19 -9
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +39 -11
- data/lib/rubocop/cop/style/if_inside_else.rb +46 -21
- data/lib/rubocop/cop/style/if_unless_modifier.rb +101 -70
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +19 -19
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -2
- data/lib/rubocop/cop/style/if_with_semicolon.rb +61 -8
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inline_comment.rb +5 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +34 -8
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +27 -7
- data/lib/rubocop/cop/style/ip_addresses.rb +3 -4
- data/lib/rubocop/cop/style/it_assignment.rb +69 -12
- data/lib/rubocop/cop/style/it_block_parameter.rb +211 -0
- data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +23 -11
- data/lib/rubocop/cop/style/lambda.rb +46 -2
- data/lib/rubocop/cop/style/lambda_call.rb +31 -10
- data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
- data/lib/rubocop/cop/style/magic_comment_format.rb +4 -4
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
- data/lib/rubocop/cop/style/map_into_array.rb +6 -4
- data/lib/rubocop/cop/style/map_join.rb +123 -0
- data/lib/rubocop/cop/style/map_to_hash.rb +13 -5
- data/lib/rubocop/cop/style/map_to_set.rb +1 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +110 -27
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +58 -6
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +36 -8
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +36 -8
- data/lib/rubocop/cop/style/min_max_comparison.rb +17 -6
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +40 -7
- data/lib/rubocop/cop/style/mixin_grouping.rb +12 -3
- data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
- data/lib/rubocop/cop/style/module_function.rb +4 -2
- data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
- data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +47 -5
- data/lib/rubocop/cop/style/multiline_if_then.rb +10 -4
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
- data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +15 -22
- 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/multiple_comparison.rb +33 -22
- data/lib/rubocop/cop/style/mutable_constant.rb +158 -14
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +3 -3
- data/lib/rubocop/cop/style/negative_array_index.rb +228 -0
- 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 +68 -10
- data/lib/rubocop/cop/style/nil_comparison.rb +53 -13
- data/lib/rubocop/cop/style/nil_lambda.rb +9 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +21 -11
- data/lib/rubocop/cop/style/not.rb +12 -3
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
- data/lib/rubocop/cop/style/numeric_predicate.rb +22 -6
- data/lib/rubocop/cop/style/object_then.rb +1 -0
- data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
- data/lib/rubocop/cop/style/one_line_conditional.rb +35 -15
- data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +10 -2
- data/lib/rubocop/cop/style/option_hash.rb +1 -1
- data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
- data/lib/rubocop/cop/style/parallel_assignment.rb +58 -27
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +7 -2
- data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +18 -3
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
- data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
- data/lib/rubocop/cop/style/proc.rb +4 -2
- data/lib/rubocop/cop/style/raise_args.rb +28 -18
- data/lib/rubocop/cop/style/reduce_to_hash.rb +216 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
- data/lib/rubocop/cop/style/redundant_assignment.rb +12 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +60 -7
- data/lib/rubocop/cop/style/redundant_condition.rb +93 -18
- data/lib/rubocop/cop/style/redundant_constant_base.rb +42 -6
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +26 -4
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +17 -3
- data/lib/rubocop/cop/style/redundant_each.rb +4 -5
- data/lib/rubocop/cop/style/redundant_exception.rb +22 -4
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +11 -11
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +319 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +13 -5
- data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +6 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +49 -10
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +83 -119
- data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +176 -83
- data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +15 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +27 -7
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +16 -0
- data/lib/rubocop/cop/style/redundant_return.rb +4 -3
- data/lib/rubocop/cop/style/redundant_self.rb +20 -7
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -3
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +27 -4
- data/lib/rubocop/cop/style/redundant_sort.rb +45 -11
- data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
- data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +107 -29
- data/lib/rubocop/cop/style/require_order.rb +25 -8
- data/lib/rubocop/cop/style/rescue_modifier.rb +16 -12
- data/lib/rubocop/cop/style/return_nil.rb +19 -4
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
- data/lib/rubocop/cop/style/reverse_find.rb +51 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +76 -20
- data/lib/rubocop/cop/style/sample.rb +19 -13
- data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
- data/lib/rubocop/cop/style/select_by_range.rb +197 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +54 -22
- data/lib/rubocop/cop/style/self_assignment.rb +13 -16
- data/lib/rubocop/cop/style/semicolon.rb +56 -14
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +4 -0
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +22 -8
- data/lib/rubocop/cop/style/single_line_methods.rb +33 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +96 -104
- data/lib/rubocop/cop/style/special_global_vars.rb +7 -2
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +32 -6
- data/lib/rubocop/cop/style/static_class.rb +21 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +38 -16
- data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +44 -2
- data/lib/rubocop/cop/style/super_arguments.rb +7 -6
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +35 -15
- data/lib/rubocop/cop/style/tally_method.rb +181 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +34 -1
- data/lib/rubocop/cop/style/time_now.rb +41 -0
- data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -2
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +2 -2
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +35 -32
- data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
- data/lib/rubocop/cop/style/while_until_do.rb +7 -0
- data/lib/rubocop/cop/style/while_until_modifier.rb +16 -1
- data/lib/rubocop/cop/style/word_array.rb +1 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +26 -12
- data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
- data/lib/rubocop/cop/style.rb +311 -0
- data/lib/rubocop/cop/team.rb +172 -49
- data/lib/rubocop/cop/util.rb +7 -10
- data/lib/rubocop/cop/utils/format_string.rb +20 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +8 -4
- data/lib/rubocop/cop/variable_force/branch.rb +30 -6
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +42 -11
- data/lib/rubocop/cop/variable_force.rb +26 -9
- data/lib/rubocop/cops_documentation_generator.rb +49 -15
- data/lib/rubocop/directive_comment.rb +147 -5
- data/lib/rubocop/ext/regexp_node.rb +0 -1
- data/lib/rubocop/feature_loader.rb +0 -6
- data/lib/rubocop/file_patterns.rb +9 -1
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +57 -14
- data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
- data/lib/rubocop/formatter/formatter_set.rb +7 -2
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
- data/lib/rubocop/formatter/html_formatter.rb +3 -5
- data/lib/rubocop/formatter/json_formatter.rb +82 -7
- data/lib/rubocop/formatter/junit_formatter.rb +27 -10
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
- data/lib/rubocop/formatter/offense_count_formatter.rb +5 -4
- data/lib/rubocop/formatter/pacman_formatter.rb +5 -2
- data/lib/rubocop/formatter/sarif_formatter.rb +186 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +4 -5
- data/lib/rubocop/formatter/tap_formatter.rb +8 -3
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +5 -4
- data/lib/rubocop/formatter.rb +23 -21
- data/lib/rubocop/lockfile.rb +18 -0
- data/lib/rubocop/lsp/diagnostic.rb +22 -41
- data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
- data/lib/rubocop/lsp/routes.rb +158 -55
- data/lib/rubocop/lsp/runtime.rb +66 -15
- data/lib/rubocop/lsp/server.rb +4 -2
- data/lib/rubocop/lsp/stdin_runner.rb +38 -19
- data/lib/rubocop/lsp.rb +5 -2
- data/lib/rubocop/magic_comment.rb +55 -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 +307 -0
- data/lib/rubocop/mcp/source_files.rb +35 -0
- data/lib/rubocop/offense_limit.rb +30 -0
- data/lib/rubocop/options.rb +166 -23
- data/lib/rubocop/path_util.rb +20 -5
- data/lib/rubocop/pending_cops_reporter.rb +51 -0
- data/lib/rubocop/plugin/configuration_integrator.rb +153 -0
- data/lib/rubocop/plugin/load_error.rb +26 -0
- data/lib/rubocop/plugin/loader.rb +100 -0
- data/lib/rubocop/plugin/not_supported_error.rb +29 -0
- data/lib/rubocop/plugin.rb +46 -0
- data/lib/rubocop/project_index_loader.rb +82 -0
- data/lib/rubocop/rake_task.rb +6 -4
- data/lib/rubocop/remote_config.rb +18 -13
- data/lib/rubocop/result_cache.rb +110 -65
- data/lib/rubocop/rspec/cop_helper.rb +21 -1
- data/lib/rubocop/rspec/expect_offense.rb +11 -7
- data/lib/rubocop/rspec/shared_contexts.rb +85 -3
- data/lib/rubocop/rspec/support.rb +4 -0
- data/lib/rubocop/runner.rb +368 -106
- data/lib/rubocop/server/cache.rb +67 -48
- data/lib/rubocop/server/cli.rb +2 -4
- data/lib/rubocop/server/client_command/base.rb +10 -0
- data/lib/rubocop/server/client_command/exec.rb +2 -1
- data/lib/rubocop/server/client_command/start.rb +11 -1
- data/lib/rubocop/server/core.rb +8 -0
- data/lib/rubocop/server.rb +14 -0
- data/lib/rubocop/target_finder.rb +25 -11
- data/lib/rubocop/target_ruby.rb +52 -23
- data/lib/rubocop/todo_audit.rb +111 -0
- data/lib/rubocop/unified_diff.rb +257 -0
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +48 -10
- data/lib/rubocop.rb +35 -682
- data/lib/ruby_lsp/rubocop/addon.rb +28 -17
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
- metadata +129 -21
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
- data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +0 -50
|
@@ -17,39 +17,81 @@ module RuboCop
|
|
|
17
17
|
class MultilineIfModifier < Base
|
|
18
18
|
include StatementModifier
|
|
19
19
|
include Alignment
|
|
20
|
+
include RangeHelp
|
|
20
21
|
extend AutoCorrector
|
|
21
22
|
|
|
22
23
|
MSG = 'Favor a normal %<keyword>s-statement over a modifier ' \
|
|
23
24
|
'clause in a multiline statement.'
|
|
24
25
|
|
|
25
26
|
def on_if(node)
|
|
27
|
+
return if part_of_ignored_node?(node)
|
|
26
28
|
return unless node.modifier_form? && node.body.multiline?
|
|
27
29
|
|
|
28
30
|
add_offense(node, message: format(MSG, keyword: node.keyword)) do |corrector|
|
|
29
|
-
corrector
|
|
31
|
+
autocorrect(corrector, node)
|
|
30
32
|
end
|
|
33
|
+
ignore_node(node)
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
private
|
|
34
37
|
|
|
35
|
-
def
|
|
38
|
+
def autocorrect(corrector, node)
|
|
39
|
+
condition_heredoc, body_heredoc = [node.condition, node.body].map do |part|
|
|
40
|
+
next unless (range = heredoc_after(part, node))
|
|
41
|
+
|
|
42
|
+
corrector.remove(range)
|
|
43
|
+
range.source.chomp
|
|
44
|
+
end
|
|
45
|
+
corrector.replace(node, to_normal_if(node, condition_heredoc, body_heredoc))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Heredocs opened on the modifier line have their bodies after it, so
|
|
49
|
+
# they are moved along with the part of the `if` they belong to.
|
|
50
|
+
def heredoc_after(part, node)
|
|
51
|
+
ranges = part.each_node(:any_str).select(&:heredoc?).map do |heredoc|
|
|
52
|
+
heredoc.loc.heredoc_body.join(heredoc.loc.heredoc_end)
|
|
53
|
+
end
|
|
54
|
+
ranges.select! { |range| range.line > node.last_line }
|
|
55
|
+
return if ranges.empty?
|
|
56
|
+
|
|
57
|
+
range_by_whole_lines(ranges.reduce(:join), include_final_newline: true)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def to_normal_if(node, condition_heredoc, body_heredoc)
|
|
36
61
|
indented_body = indented_body(node.body, node)
|
|
37
62
|
condition = "#{node.keyword} #{node.condition.source}"
|
|
38
63
|
indented_end = "#{offset(node)}end"
|
|
39
64
|
|
|
40
|
-
[condition, indented_body, indented_end]
|
|
65
|
+
lines = [condition, condition_heredoc, indented_body, body_heredoc, indented_end]
|
|
66
|
+
lines.compact.join("\n")
|
|
41
67
|
end
|
|
42
68
|
|
|
43
69
|
def indented_body(body, node)
|
|
44
70
|
body_source = "#{offset(node)}#{body.source}"
|
|
45
|
-
|
|
46
|
-
|
|
71
|
+
verbatim_lines = verbatim_lines_in(body)
|
|
72
|
+
body_source.each_line.with_index(body.first_line).map do |line, line_number|
|
|
73
|
+
if line == "\n" || verbatim_lines.include?(line_number)
|
|
47
74
|
line
|
|
48
75
|
else
|
|
49
76
|
line.sub(/^\s{#{offset(node).length}}/, indentation(node))
|
|
50
77
|
end
|
|
51
78
|
end.join
|
|
52
79
|
end
|
|
80
|
+
|
|
81
|
+
def verbatim_lines_in(body)
|
|
82
|
+
body.each_node(:any_str).filter_map { |str| verbatim_line_range(str) }.flat_map(&:to_a)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# The indentation of a line that starts inside a string is part of the
|
|
86
|
+
# string. Only squiggly heredocs strip it from their bodies, and a `<<`
|
|
87
|
+
# terminator has to stay at the start of its line.
|
|
88
|
+
def verbatim_line_range(str)
|
|
89
|
+
if str.heredoc?
|
|
90
|
+
str.loc.heredoc_body.line..str.loc.heredoc_end.line unless str.source.start_with?('<<~')
|
|
91
|
+
elsif str.loc?(:begin) && str.loc?(:end)
|
|
92
|
+
(str.first_line + 1)..str.last_line
|
|
93
|
+
end
|
|
94
|
+
end
|
|
53
95
|
end
|
|
54
96
|
end
|
|
55
97
|
end
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Checks for uses of the `then` keyword in multi-line if statements.
|
|
6
|
+
# Checks for uses of the `then` keyword in multi-line `if` statements.
|
|
7
|
+
# In multi-line `if` statements, `then` is redundant because the newline
|
|
8
|
+
# already separates the condition from the body.
|
|
7
9
|
#
|
|
8
10
|
# @example
|
|
9
11
|
# # bad
|
|
@@ -21,8 +23,6 @@ module RuboCop
|
|
|
21
23
|
include RangeHelp
|
|
22
24
|
extend AutoCorrector
|
|
23
25
|
|
|
24
|
-
NON_MODIFIER_THEN = /then\s*(#.*)?$/.freeze
|
|
25
|
-
|
|
26
26
|
MSG = 'Do not use `then` for multi-line `%<keyword>s`.'
|
|
27
27
|
|
|
28
28
|
def on_normal_if_unless(node)
|
|
@@ -36,7 +36,13 @@ module RuboCop
|
|
|
36
36
|
private
|
|
37
37
|
|
|
38
38
|
def non_modifier_then?(node)
|
|
39
|
-
|
|
39
|
+
node.multiline? && own_then?(node) && node.loc.begin.line != node.if_branch&.loc&.line
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Prism gives an `elsif` with no `then` of its own the previous branch's `then` location,
|
|
43
|
+
# which lies outside the node.
|
|
44
|
+
def own_then?(node)
|
|
45
|
+
node.then? && node.source_range.contains?(node.loc.begin)
|
|
40
46
|
end
|
|
41
47
|
end
|
|
42
48
|
end
|
|
@@ -50,10 +50,17 @@ module RuboCop
|
|
|
50
50
|
# Requires `then` for write `in` and its body on the same line.
|
|
51
51
|
def require_then?(in_pattern_node)
|
|
52
52
|
return true unless in_pattern_node.pattern.single_line?
|
|
53
|
+
return true if ends_with_endless_range?(in_pattern_node.pattern)
|
|
53
54
|
return false unless in_pattern_node.body
|
|
54
55
|
|
|
55
56
|
same_line?(in_pattern_node, in_pattern_node.body)
|
|
56
57
|
end
|
|
58
|
+
|
|
59
|
+
def ends_with_endless_range?(node)
|
|
60
|
+
node.each_node(:range).any? do |range|
|
|
61
|
+
range.end.nil? && range.source_range.end_pos == node.source_range.end_pos
|
|
62
|
+
end
|
|
63
|
+
end
|
|
57
64
|
end
|
|
58
65
|
end
|
|
59
66
|
end
|
|
@@ -65,10 +65,16 @@ module RuboCop
|
|
|
65
65
|
if style == :keyword
|
|
66
66
|
rhs.begin_type?
|
|
67
67
|
else
|
|
68
|
-
|
|
68
|
+
# A `begin` block with `rescue`/`ensure` cannot be expressed with
|
|
69
|
+
# parentheses, so wrapping it in `(` and `)` is not possible.
|
|
70
|
+
rhs.kwbegin_type? && !contains_rescue_or_ensure?(rhs)
|
|
69
71
|
end
|
|
70
72
|
end
|
|
71
73
|
|
|
74
|
+
def contains_rescue_or_ensure?(node)
|
|
75
|
+
node.each_child_node(:rescue, :ensure).any?
|
|
76
|
+
end
|
|
77
|
+
|
|
72
78
|
def keyword_autocorrect(node, corrector)
|
|
73
79
|
node_buf = node.source_range.source_buffer
|
|
74
80
|
corrector.replace(node.loc.begin, keyword_begin_str(node, node_buf))
|
|
@@ -27,6 +27,7 @@ module RuboCop
|
|
|
27
27
|
def on_def(node)
|
|
28
28
|
return unless node.arguments?
|
|
29
29
|
return if opening_line(node) == closing_line(node)
|
|
30
|
+
return if node.arguments.any?(&:multiline?)
|
|
30
31
|
return if correction_exceeds_max_line_length?(node)
|
|
31
32
|
return unless (begin_of_arguments = node.arguments.loc.begin)
|
|
32
33
|
|
|
@@ -38,7 +39,7 @@ module RuboCop
|
|
|
38
39
|
|
|
39
40
|
private
|
|
40
41
|
|
|
41
|
-
# rubocop:disable Metrics/AbcSize
|
|
42
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
42
43
|
def autocorrect(corrector, node, begin_of_arguments)
|
|
43
44
|
arguments = node.arguments
|
|
44
45
|
joined_arguments = arguments.map(&:source).join(', ')
|
|
@@ -50,30 +51,23 @@ module RuboCop
|
|
|
50
51
|
corrector.remove(range_by_whole_lines(arguments.loc.end, include_final_newline: true))
|
|
51
52
|
end
|
|
52
53
|
|
|
53
|
-
arguments_range = arguments_range(node)
|
|
54
|
-
# If the method name isn't on the same line as def
|
|
54
|
+
arguments_range = range_with_surrounding_space(arguments_range(node), side: :left)
|
|
55
|
+
# If the method name isn't on the same line as `def`, pull the name and
|
|
56
|
+
# the opening parenthesis up next to `def` so the collapsed signature
|
|
57
|
+
# stays on a single line and remains valid Ruby.
|
|
55
58
|
if arguments_range.first_line != opening_line(node)
|
|
56
|
-
|
|
57
|
-
corrector.
|
|
59
|
+
prefix_range = range_between(node.loc.keyword.end_pos, begin_of_arguments.begin_pos)
|
|
60
|
+
corrector.replace(prefix_range, " #{prefix_range.source.strip}")
|
|
58
61
|
end
|
|
59
62
|
|
|
60
63
|
corrector.remove(arguments_range)
|
|
61
64
|
corrector.insert_after(begin_of_arguments, joined_arguments)
|
|
62
65
|
end
|
|
63
|
-
# rubocop:enable Metrics/AbcSize
|
|
64
66
|
|
|
65
67
|
def last_line_source_of_arguments(arguments)
|
|
66
68
|
processed_source[arguments.last_line - 1].strip
|
|
67
69
|
end
|
|
68
70
|
|
|
69
|
-
def arguments_range(node)
|
|
70
|
-
range = range_between(
|
|
71
|
-
node.first_argument.source_range.begin_pos, node.last_argument.source_range.end_pos
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
range_with_surrounding_space(range, side: :left)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
71
|
def opening_line(node)
|
|
78
72
|
node.first_line
|
|
79
73
|
end
|
|
@@ -83,19 +77,18 @@ module RuboCop
|
|
|
83
77
|
end
|
|
84
78
|
|
|
85
79
|
def correction_exceeds_max_line_length?(node)
|
|
86
|
-
|
|
87
|
-
end
|
|
80
|
+
return false unless max_line_length
|
|
88
81
|
|
|
89
|
-
|
|
90
|
-
processed_source.line_indentation(node.source_range.line)
|
|
82
|
+
node.source_range.column + definition_width(node) > max_line_length
|
|
91
83
|
end
|
|
92
84
|
|
|
93
85
|
def definition_width(node)
|
|
94
|
-
|
|
95
|
-
|
|
86
|
+
# Measure the collapsed single-line width the autocorrect would
|
|
87
|
+
# produce, not the multi-line source length, so a signature that
|
|
88
|
+
# would fit on one line is not skipped.
|
|
89
|
+
signature = node.source_range.begin.join(node.arguments.source_range.end).source
|
|
96
90
|
|
|
97
|
-
|
|
98
|
-
config.for_cop('Layout/LineLength')['Max'] || 120
|
|
91
|
+
signature.gsub(/\s+/, ' ').length
|
|
99
92
|
end
|
|
100
93
|
end
|
|
101
94
|
end
|
|
@@ -7,7 +7,8 @@ module RuboCop
|
|
|
7
7
|
#
|
|
8
8
|
# NOTE: `return if ... else ... end` is syntax error. If `return` is used before
|
|
9
9
|
# multiline ternary operator expression, it will be autocorrected to single-line
|
|
10
|
-
# ternary operator. The same is true for `break`, `next`,
|
|
10
|
+
# ternary operator. The same is true for `break`, `next`, `yield`, `super`,
|
|
11
|
+
# `defined?` without parentheses, and method call.
|
|
11
12
|
#
|
|
12
13
|
# @example
|
|
13
14
|
# # bad
|
|
@@ -39,7 +40,7 @@ module RuboCop
|
|
|
39
40
|
|
|
40
41
|
MSG_IF = 'Avoid multi-line ternary operators, use `if` or `unless` instead.'
|
|
41
42
|
MSG_SINGLE_LINE = 'Avoid multi-line ternary operators, use single-line instead.'
|
|
42
|
-
SINGLE_LINE_TYPES = %i[return break next send csend].freeze
|
|
43
|
+
SINGLE_LINE_TYPES = %i[return break next send csend super yield].freeze
|
|
43
44
|
|
|
44
45
|
def on_if(node)
|
|
45
46
|
return unless offense?(node)
|
|
@@ -90,7 +91,10 @@ module RuboCop
|
|
|
90
91
|
end
|
|
91
92
|
|
|
92
93
|
def enforce_single_line_ternary_operator?(node)
|
|
93
|
-
|
|
94
|
+
return false unless (parent = node.parent)
|
|
95
|
+
return !parent.parenthesized? if parent.defined_type?
|
|
96
|
+
|
|
97
|
+
SINGLE_LINE_TYPES.include?(parent.type) && !use_assignment_method?(parent)
|
|
94
98
|
end
|
|
95
99
|
|
|
96
100
|
def use_assignment_method?(node)
|
|
@@ -50,10 +50,17 @@ module RuboCop
|
|
|
50
50
|
unless when_node.conditions.first.first_line == when_node.conditions.last.last_line
|
|
51
51
|
return true
|
|
52
52
|
end
|
|
53
|
+
return true if ends_with_endless_range?(when_node.conditions.last)
|
|
53
54
|
return false unless when_node.body
|
|
54
55
|
|
|
55
56
|
same_line?(when_node, when_node.body)
|
|
56
57
|
end
|
|
58
|
+
|
|
59
|
+
def ends_with_endless_range?(node)
|
|
60
|
+
node.each_node(:range).any? do |range|
|
|
61
|
+
range.end.nil? && range.source_range.end_pos == node.source_range.end_pos
|
|
62
|
+
end
|
|
63
|
+
end
|
|
57
64
|
end
|
|
58
65
|
end
|
|
59
66
|
end
|
|
@@ -70,48 +70,59 @@ module RuboCop
|
|
|
70
70
|
(send $_ :== ${lvar call})
|
|
71
71
|
PATTERN
|
|
72
72
|
|
|
73
|
-
# rubocop:disable Metrics/AbcSize
|
|
74
73
|
def on_or(node)
|
|
75
|
-
|
|
76
|
-
return unless node == root_of_or_node
|
|
74
|
+
return unless node == root_of_or_node(node)
|
|
77
75
|
return unless nested_comparison?(node)
|
|
78
|
-
|
|
79
|
-
return unless (variable, values = find_offending_var(node))
|
|
76
|
+
return unless (variable, values, skipped = find_offending_var(node))
|
|
80
77
|
return if values.size < comparisons_threshold
|
|
81
78
|
|
|
82
79
|
range = offense_range(values)
|
|
80
|
+
# Bail when an allowed method comparison sits between the collected
|
|
81
|
+
# values: collapsing them into a single `include?` would drop it.
|
|
82
|
+
return if skipped_within_range?(skipped, range)
|
|
83
83
|
|
|
84
84
|
add_offense(range) do |corrector|
|
|
85
|
-
|
|
86
|
-
argument = variable.lvar_type? ? variable_name(variable) : variable.source
|
|
87
|
-
prefer_method = "[#{elements}].include?(#{argument})"
|
|
88
|
-
|
|
89
|
-
corrector.replace(range, prefer_method)
|
|
85
|
+
corrector.replace(range, preferred_method(variable, values))
|
|
90
86
|
end
|
|
91
87
|
end
|
|
92
|
-
# rubocop:enable Metrics/AbcSize
|
|
93
88
|
|
|
94
89
|
private
|
|
95
90
|
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
def skipped_within_range?(skipped, range)
|
|
92
|
+
skipped.any? { |node_part| range.contains?(node_part.source_range) }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def preferred_method(variable, values)
|
|
96
|
+
elements = values.map(&:source).join(', ')
|
|
97
|
+
argument = variable.lvar_type? ? variable_name(variable) : variable.source
|
|
98
|
+
"[#{elements}].include?(#{argument})"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def find_offending_var(node, variables = Set.new, values = [], skipped = [])
|
|
98
102
|
if node.or_type?
|
|
99
|
-
find_offending_var(node.lhs, variables, values)
|
|
100
|
-
find_offending_var(node.rhs, variables, values)
|
|
103
|
+
find_offending_var(node.lhs, variables, values, skipped)
|
|
104
|
+
find_offending_var(node.rhs, variables, values, skipped)
|
|
101
105
|
elsif simple_double_comparison?(node)
|
|
102
106
|
return
|
|
103
|
-
elsif (
|
|
104
|
-
|
|
107
|
+
elsif (comparison = simple_comparison(node))
|
|
108
|
+
collect_comparison(node, comparison, variables, values, skipped)
|
|
109
|
+
end
|
|
105
110
|
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
[variables.first, values, skipped] if variables.any?
|
|
112
|
+
end
|
|
108
113
|
|
|
109
|
-
|
|
114
|
+
def collect_comparison(node, comparison, variables, values, skipped)
|
|
115
|
+
var, obj = comparison
|
|
116
|
+
if allow_method_comparison? && obj.call_type?
|
|
117
|
+
skipped << node
|
|
118
|
+
return
|
|
110
119
|
end
|
|
111
120
|
|
|
112
|
-
|
|
121
|
+
variables << var
|
|
122
|
+
return if variables.size > 1
|
|
123
|
+
|
|
124
|
+
values << obj
|
|
113
125
|
end
|
|
114
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
115
126
|
|
|
116
127
|
def offense_range(values)
|
|
117
128
|
values.first.parent.source_range.begin.join(values.last.parent.source_range.end)
|
|
@@ -6,6 +6,14 @@ module RuboCop
|
|
|
6
6
|
# Checks whether some constant value isn't a
|
|
7
7
|
# mutable literal (e.g. array or hash).
|
|
8
8
|
#
|
|
9
|
+
# When the `Recursive` option is enabled, mutable literals nested inside
|
|
10
|
+
# arrays and hashes are also frozen, so an offense on the outermost
|
|
11
|
+
# unfrozen literal will autocorrect every nested mutable literal as well.
|
|
12
|
+
# When the outer literal already has `.freeze` appended, the cop descends
|
|
13
|
+
# into it and reports each outermost unfrozen literal underneath. The
|
|
14
|
+
# option is disabled by default to preserve existing behavior; opt in to
|
|
15
|
+
# get strict nested freezing.
|
|
16
|
+
#
|
|
9
17
|
# Strict mode can be used to freeze all constants, rather than
|
|
10
18
|
# just literals.
|
|
11
19
|
# Strict mode is considered an experimental feature. It has not been
|
|
@@ -49,6 +57,17 @@ module RuboCop
|
|
|
49
57
|
# CONST = Something.new
|
|
50
58
|
#
|
|
51
59
|
#
|
|
60
|
+
# @example Recursive: false (default)
|
|
61
|
+
# # good - only the outer container needs to be frozen
|
|
62
|
+
# CONST = [{ a: [], b: 'foo' }].freeze
|
|
63
|
+
#
|
|
64
|
+
# @example Recursive: true
|
|
65
|
+
# # bad - nested mutable literals must be frozen too
|
|
66
|
+
# CONST = [{ a: [], b: 'foo' }].freeze
|
|
67
|
+
#
|
|
68
|
+
# # good
|
|
69
|
+
# CONST = [{ a: [].freeze, b: 'foo'.freeze }.freeze].freeze
|
|
70
|
+
#
|
|
52
71
|
# @example EnforcedStyle: strict
|
|
53
72
|
# # bad
|
|
54
73
|
# CONST = Something.new
|
|
@@ -70,6 +89,9 @@ module RuboCop
|
|
|
70
89
|
# end
|
|
71
90
|
# end.freeze
|
|
72
91
|
#
|
|
92
|
+
# # good - `Data.define` declares an immutable value type
|
|
93
|
+
# CONST = Data.define(:foo, :bar)
|
|
94
|
+
#
|
|
73
95
|
# @example
|
|
74
96
|
# # Magic comment - shareable_constant_value: literal
|
|
75
97
|
#
|
|
@@ -124,8 +146,15 @@ module RuboCop
|
|
|
124
146
|
|
|
125
147
|
MSG = 'Freeze mutable objects assigned to constants.'
|
|
126
148
|
|
|
149
|
+
# With `Recursive: true`, `.freeze` is appended to a nested literal. When the literal
|
|
150
|
+
# is the last element and spans multiple lines, the trailing comma lands between the literal
|
|
151
|
+
# and the `.freeze` appended in the same pass.
|
|
152
|
+
def self.autocorrect_incompatible_with
|
|
153
|
+
[Style::HashAsLastArrayItem, Style::TrailingCommaInArrayLiteral, Style::TrailingCommaInHashLiteral]
|
|
154
|
+
end
|
|
155
|
+
|
|
127
156
|
def on_casgn(node)
|
|
128
|
-
if node.expression.nil? # This is only the case for `CONST += ...` or
|
|
157
|
+
if node.expression.nil? # This is only the case for `CONST += ...` or similar
|
|
129
158
|
parent = node.parent
|
|
130
159
|
return unless parent.or_asgn_type? # We only care about `CONST ||= ...`
|
|
131
160
|
|
|
@@ -138,31 +167,55 @@ module RuboCop
|
|
|
138
167
|
private
|
|
139
168
|
|
|
140
169
|
def on_assignment(value)
|
|
141
|
-
|
|
142
|
-
|
|
170
|
+
nodes = mutable_nodes(value) do |node|
|
|
171
|
+
if style == :strict
|
|
172
|
+
strict_check(node)
|
|
173
|
+
else
|
|
174
|
+
literal_check(node)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
nodes.each do |node|
|
|
179
|
+
add_offense(node) { |corrector| autocorrect(corrector, node) }
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def mutable_nodes(value, &block)
|
|
184
|
+
if recursive? && explicitly_frozen_literal?(value)
|
|
185
|
+
literal_children(value.receiver).flat_map { |c| mutable_nodes(c, &block) }
|
|
143
186
|
else
|
|
144
|
-
|
|
187
|
+
node_offending = yield(value)
|
|
188
|
+
|
|
189
|
+
if node_offending
|
|
190
|
+
[value]
|
|
191
|
+
else
|
|
192
|
+
[]
|
|
193
|
+
end
|
|
145
194
|
end
|
|
146
195
|
end
|
|
147
196
|
|
|
148
197
|
def strict_check(value)
|
|
198
|
+
return if value.assignment?
|
|
149
199
|
return if immutable_literal?(value)
|
|
150
200
|
return if operation_produces_immutable_object?(value)
|
|
151
201
|
return if frozen_string_literal?(value)
|
|
152
202
|
return if shareable_constant_value?(value)
|
|
203
|
+
return if parenthesized_immutable_value?(value)
|
|
153
204
|
|
|
154
|
-
|
|
205
|
+
true
|
|
155
206
|
end
|
|
156
207
|
|
|
157
|
-
def
|
|
158
|
-
|
|
159
|
-
return unless mutable_literal?(value) ||
|
|
160
|
-
(target_ruby_version <= 2.7 && range_enclosed_in_parentheses)
|
|
161
|
-
|
|
208
|
+
def literal_check(value)
|
|
209
|
+
return unless mutable_or_unfrozen_range?(value)
|
|
162
210
|
return if frozen_string_literal?(value)
|
|
163
211
|
return if shareable_constant_value?(value)
|
|
164
212
|
|
|
165
|
-
|
|
213
|
+
true
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def mutable_or_unfrozen_range?(value)
|
|
217
|
+
mutable_literal?(value) ||
|
|
218
|
+
(target_ruby_version <= 2.7 && range_enclosed_in_parentheses?(value))
|
|
166
219
|
end
|
|
167
220
|
|
|
168
221
|
def autocorrect(corrector, node)
|
|
@@ -171,13 +224,84 @@ module RuboCop
|
|
|
171
224
|
splat_value = splat_value(node)
|
|
172
225
|
if splat_value
|
|
173
226
|
correct_splat_expansion(corrector, expr, splat_value)
|
|
174
|
-
|
|
227
|
+
corrector.insert_after(expr, '.freeze')
|
|
228
|
+
return
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
return expand_omitted_hash_value(corrector, node.parent) if omitted_hash_value?(node)
|
|
232
|
+
|
|
233
|
+
wrap_for_freeze(corrector, node, expr)
|
|
234
|
+
corrector.insert_after(expr, '.freeze')
|
|
235
|
+
|
|
236
|
+
freeze_nested_literals(corrector, node) if recursive?
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def omitted_hash_value?(node)
|
|
240
|
+
node.parent&.pair_type? && node.parent.value_omission?
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def expand_omitted_hash_value(corrector, pair)
|
|
244
|
+
key = pair.key.value
|
|
245
|
+
|
|
246
|
+
corrector.replace(pair, "#{key}: #{key}.freeze")
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def wrap_for_freeze(corrector, node, expr)
|
|
250
|
+
if node.array_type? && !node.bracketed?
|
|
175
251
|
corrector.wrap(expr, '[', ']')
|
|
252
|
+
elsif node.hash_type? && !node.braces?
|
|
253
|
+
corrector.wrap(expr, '{ ', ' }')
|
|
176
254
|
elsif requires_parentheses?(node)
|
|
177
255
|
corrector.wrap(expr, '(', ')')
|
|
178
256
|
end
|
|
257
|
+
end
|
|
179
258
|
|
|
180
|
-
|
|
259
|
+
# Recursively freezes every nested mutable literal inside an array or
|
|
260
|
+
# hash literal. Already-frozen subtrees are not re-frozen, but their
|
|
261
|
+
# children are still inspected for unfrozen literals deeper down.
|
|
262
|
+
def freeze_nested_literals(corrector, node)
|
|
263
|
+
literal_children(node).each do |child|
|
|
264
|
+
if explicitly_frozen_literal?(child)
|
|
265
|
+
freeze_nested_literals(corrector, child.receiver)
|
|
266
|
+
elsif freezable_nested_literal?(child)
|
|
267
|
+
autocorrect(corrector, child)
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def freezable_nested_literal?(node)
|
|
273
|
+
return false if frozen_string_literal?(node)
|
|
274
|
+
return false if shareable_constant_value?(node)
|
|
275
|
+
|
|
276
|
+
mutable_literal?(node)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Returns the child literals of an array or hash node that may
|
|
280
|
+
# themselves need freezing. For hashes, both keys and values are
|
|
281
|
+
# included. Percent-literal arrays (e.g. `%w(a b)`) are skipped because
|
|
282
|
+
# `.freeze` cannot be appended to their contents. Splat elements are
|
|
283
|
+
# skipped because the splatted object is not stored in the array.
|
|
284
|
+
def literal_children(node)
|
|
285
|
+
case node.type
|
|
286
|
+
when :array
|
|
287
|
+
return [] if node.percent_literal?
|
|
288
|
+
|
|
289
|
+
node.children.reject(&:splat_type?)
|
|
290
|
+
when :hash
|
|
291
|
+
node.children.flat_map { |child| child.pair_type? ? child.children : [] }
|
|
292
|
+
else
|
|
293
|
+
[]
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def explicitly_frozen_literal?(node)
|
|
298
|
+
return false unless node.send_type? && node.method?(:freeze)
|
|
299
|
+
|
|
300
|
+
node.receiver && mutable_literal?(node.receiver)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def recursive?
|
|
304
|
+
cop_config.fetch('Recursive', false)
|
|
181
305
|
end
|
|
182
306
|
|
|
183
307
|
def mutable_literal?(value)
|
|
@@ -196,12 +320,30 @@ module RuboCop
|
|
|
196
320
|
recent_shareable_value? node
|
|
197
321
|
end
|
|
198
322
|
|
|
323
|
+
def parenthesized_immutable_value?(value)
|
|
324
|
+
return false if !value.begin_type? || !value.children.one?
|
|
325
|
+
|
|
326
|
+
inner = value.children.first
|
|
327
|
+
|
|
328
|
+
!inner.assignment? && !strict_check(inner)
|
|
329
|
+
end
|
|
330
|
+
|
|
199
331
|
def frozen_regexp_or_range_literals?(node)
|
|
200
332
|
target_ruby_version >= 3.0 && node.type?(:regexp, :range)
|
|
201
333
|
end
|
|
202
334
|
|
|
203
335
|
def requires_parentheses?(node)
|
|
204
|
-
node.range_type? ||
|
|
336
|
+
if node.range_type? || node.operator_keyword? || unparenthesized_method_call?(node)
|
|
337
|
+
return true
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
node.if_type? && node.ternary?
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def unparenthesized_method_call?(node)
|
|
344
|
+
return false unless node.call_type?
|
|
345
|
+
|
|
346
|
+
node.loc.dot.nil? || (node.arguments.any? && !node.parenthesized?)
|
|
205
347
|
end
|
|
206
348
|
|
|
207
349
|
def correct_splat_expansion(corrector, expr, splat_value)
|
|
@@ -225,6 +367,8 @@ module RuboCop
|
|
|
225
367
|
(const _ _)
|
|
226
368
|
(send (const {nil? cbase} :Struct) :new ...)
|
|
227
369
|
(block (send (const {nil? cbase} :Struct) :new ...) ...)
|
|
370
|
+
(send (const {nil? cbase} :Data) :define ...)
|
|
371
|
+
(block (send (const {nil? cbase} :Data) :define ...) ...)
|
|
228
372
|
(send _ :freeze)
|
|
229
373
|
(send {float int} {:+ :- :* :** :/ :% :<<} _)
|
|
230
374
|
(send _ {:+ :- :* :** :/ :%} {float int})
|
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
|
46
46
|
@corrected_nodes = nil
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
# rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
|
|
49
|
+
# rubocop:disable-next Metrics/AbcSize,Metrics/CyclomaticComplexity
|
|
50
50
|
def on_if(node)
|
|
51
51
|
return unless if_else?(node)
|
|
52
52
|
return unless (condition = unwrap_begin_nodes(node.condition))
|
|
@@ -64,7 +64,6 @@ module RuboCop
|
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
|
-
# rubocop:enable Metrics/AbcSize,Metrics/CyclomaticComplexity
|
|
68
67
|
|
|
69
68
|
private
|
|
70
69
|
|
|
@@ -119,7 +118,8 @@ module RuboCop
|
|
|
119
118
|
if node.ternary?
|
|
120
119
|
node.if_branch
|
|
121
120
|
else
|
|
122
|
-
|
|
121
|
+
if_start = node.loc.begin || node.condition.source_range
|
|
122
|
+
range_between(if_start.end_pos, node.loc.else.begin_pos)
|
|
123
123
|
end
|
|
124
124
|
end
|
|
125
125
|
|