rubocop 1.71.1 → 1.91.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/LICENSE.txt +1 -1
- data/README.md +23 -19
- data/config/default.yml +883 -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 +7 -2
- data/lib/rubocop/changed_files.rb +112 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
- data/lib/rubocop/cli/command/execute_runner.rb +52 -1
- 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 +2 -2
- data/lib/rubocop/cli/command/show_docs_url.rb +4 -8
- data/lib/rubocop/cli/command/suggest_extensions.rb +8 -2
- data/lib/rubocop/cli.rb +58 -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 +92 -48
- data/lib/rubocop/config.rb +137 -19
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader.rb +72 -49
- data/lib/rubocop/config_loader_resolver.rb +94 -28
- 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 +8 -0
- 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 +64 -12
- data/lib/rubocop/cop/autocorrect_logic.rb +35 -14
- data/lib/rubocop/cop/badge.rb +9 -1
- data/lib/rubocop/cop/base.rb +93 -21
- data/lib/rubocop/cop/bundler/gem_comment.rb +5 -3
- data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
- data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -3
- data/lib/rubocop/cop/bundler.rb +19 -0
- data/lib/rubocop/cop/commissioner.rb +13 -11
- data/lib/rubocop/cop/corrector.rb +4 -4
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +79 -10
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/each_to_for_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 +7 -1
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +36 -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 +2 -3
- data/lib/rubocop/cop/exclude_limit.rb +31 -5
- data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
- 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 -3
- 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 +14 -15
- 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 +92 -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_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/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 +4 -2
- 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 +59 -4
- data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
- data/lib/rubocop/cop/layout/class_structure.rb +163 -35
- 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 +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +2 -2
- 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_between_defs.rb +46 -21
- 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 +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +13 -2
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +17 -3
- 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 +9 -3
- data/lib/rubocop/cop/layout/extra_spacing.rb +105 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +56 -3
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +18 -5
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +20 -15
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +11 -13
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +3 -3
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +157 -10
- data/lib/rubocop/cop/layout/leading_comment_space.rb +40 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +2 -3
- data/lib/rubocop/cop/layout/line_length.rb +160 -23
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +8 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -0
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +245 -40
- 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 +89 -6
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +14 -7
- data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +14 -3
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -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 +1 -0
- 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 +42 -36
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
- 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_precedence.rb +1 -10
- data/lib/rubocop/cop/lint/ambiguous_range.rb +6 -2
- 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 +20 -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/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 +137 -11
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +13 -19
- data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +185 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +44 -22
- 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 +19 -10
- 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 +149 -39
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +53 -19
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +15 -4
- 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 +9 -5
- 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 +21 -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 +36 -10
- 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 +56 -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 +4 -1
- 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 +60 -21
- 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/collection_literal_length.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +3 -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 +3 -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 +27 -9
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -7
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- 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 +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- 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 +44 -16
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +29 -26
- 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/multiline_expression_indentation.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +62 -6
- data/lib/rubocop/cop/mixin/project_index_help.rb +188 -0
- data/lib/rubocop/cop/mixin/range_help.rb +16 -5
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +171 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +47 -11
- 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.rb +91 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +24 -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/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} +80 -8
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -6
- 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 +52 -9
- data/lib/rubocop/cop/registry.rb +233 -64
- 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 +33 -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 +47 -13
- data/lib/rubocop/cop/style/accessor_grouping.rb +47 -10
- data/lib/rubocop/cop/style/alias.rb +15 -3
- data/lib/rubocop/cop/style/and_or.rb +2 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +49 -37
- 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 +5 -2
- 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 +7 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +43 -38
- data/lib/rubocop/cop/style/case_equality.rb +29 -15
- data/lib/rubocop/cop/style/case_like_if.rb +6 -8
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +135 -21
- data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -14
- data/lib/rubocop/cop/style/class_methods_definitions.rb +11 -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 +167 -0
- data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
- data/lib/rubocop/cop/style/combinable_loops.rb +7 -2
- 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 +8 -3
- data/lib/rubocop/cop/style/conditional_assignment.rb +54 -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 +122 -14
- 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 +3 -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 +11 -2
- data/lib/rubocop/cop/style/empty_method.rb +12 -8
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +110 -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 +191 -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 +8 -1
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
- data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
- 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 +25 -17
- data/lib/rubocop/cop/style/for.rb +9 -0
- data/lib/rubocop/cop/style/format_string.rb +17 -4
- data/lib/rubocop/cop/style/format_string_token.rb +86 -16
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
- 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 +32 -23
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -12
- 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 +105 -0
- data/lib/rubocop/cop/style/hash_slice.rb +16 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +7 -3
- 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 +18 -9
- data/lib/rubocop/cop/style/if_inside_else.rb +25 -20
- data/lib/rubocop/cop/style/if_unless_modifier.rb +71 -46
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +15 -19
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -2
- data/lib/rubocop/cop/style/if_with_semicolon.rb +16 -6
- 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 +10 -6
- 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 +121 -0
- data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +20 -10
- data/lib/rubocop/cop/style/lambda.rb +12 -1
- data/lib/rubocop/cop/style/lambda_call.rb +26 -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 +5 -2
- 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 +31 -15
- 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 +34 -5
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +12 -7
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +7 -5
- data/lib/rubocop/cop/style/min_max_comparison.rb +17 -6
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +40 -7
- 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 +2 -0
- data/lib/rubocop/cop/style/multiline_if_then.rb +10 -4
- data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +14 -18
- data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
- data/lib/rubocop/cop/style/mutable_constant.rb +111 -12
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -2
- data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
- data/lib/rubocop/cop/style/nested_modifier.rb +9 -4
- data/lib/rubocop/cop/style/next.rb +44 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +41 -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 +5 -1
- 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 +1 -1
- 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 +22 -13
- 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 +6 -1
- data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +4 -0
- 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 +9 -9
- data/lib/rubocop/cop/style/reduce_to_hash.rb +200 -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 +38 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +63 -5
- 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 +11 -3
- data/lib/rubocop/cop/style/redundant_each.rb +4 -5
- data/lib/rubocop/cop/style/redundant_exception.rb +7 -1
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +2 -10
- 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 +2 -2
- 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 +26 -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 +164 -82
- data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +8 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +8 -8
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +12 -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 +0 -5
- data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
- 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 +32 -3
- data/lib/rubocop/cop/style/rescue_modifier.rb +5 -3
- data/lib/rubocop/cop/style/return_nil.rb +2 -2
- 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 +11 -6
- 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 +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +45 -14
- 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 +13 -8
- 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 +3 -1
- data/lib/rubocop/cop/style/static_class.rb +21 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +31 -15
- data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +38 -2
- data/lib/rubocop/cop/style/super_arguments.rb +4 -6
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +11 -9
- data/lib/rubocop/cop/style/tally_method.rb +181 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +11 -0
- 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 +18 -19
- 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 +2 -3
- data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
- 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 +163 -45
- 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 +7 -3
- 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 +28 -10
- 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/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 +3 -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 +11 -6
- 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 +2 -3
- data/lib/rubocop/formatter/pacman_formatter.rb +2 -1
- data/lib/rubocop/formatter/sarif_formatter.rb +181 -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 +2 -3
- 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 +136 -33
- data/lib/rubocop/lsp/runtime.rb +23 -8
- data/lib/rubocop/lsp/server.rb +4 -2
- data/lib/rubocop/lsp/stdin_runner.rb +31 -18
- data/lib/rubocop/magic_comment.rb +55 -0
- data/lib/rubocop/mcp/server.rb +199 -0
- data/lib/rubocop/options.rb +129 -21
- data/lib/rubocop/path_util.rb +20 -5
- data/lib/rubocop/pending_cops_reporter.rb +51 -0
- data/lib/rubocop/plugin/configuration_integrator.rb +146 -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 +14 -12
- data/lib/rubocop/result_cache.rb +90 -52
- 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 +294 -100
- 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 +31 -14
- data/lib/rubocop/todo_audit.rb +111 -0
- data/lib/rubocop/unified_diff.rb +257 -0
- data/lib/rubocop/version.rb +48 -10
- data/lib/rubocop.rb +30 -682
- data/lib/ruby_lsp/rubocop/addon.rb +28 -17
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
- metadata +116 -19
- 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
|
@@ -45,17 +45,6 @@ module RuboCop
|
|
|
45
45
|
# ok
|
|
46
46
|
#
|
|
47
47
|
# # bad
|
|
48
|
-
# if something
|
|
49
|
-
# foo || raise('exception')
|
|
50
|
-
# else
|
|
51
|
-
# ok
|
|
52
|
-
# end
|
|
53
|
-
#
|
|
54
|
-
# # good
|
|
55
|
-
# foo || raise('exception') if something
|
|
56
|
-
# ok
|
|
57
|
-
#
|
|
58
|
-
# # bad
|
|
59
48
|
# define_method(:test) do
|
|
60
49
|
# if something
|
|
61
50
|
# work
|
|
@@ -120,6 +109,10 @@ module RuboCop
|
|
|
120
109
|
MSG = 'Use a guard clause (`%<example>s`) instead of wrapping the ' \
|
|
121
110
|
'code inside a conditional expression.'
|
|
122
111
|
|
|
112
|
+
def self.autocorrect_incompatible_with
|
|
113
|
+
[Style::MissingElse]
|
|
114
|
+
end
|
|
115
|
+
|
|
123
116
|
def on_def(node)
|
|
124
117
|
body = node.body
|
|
125
118
|
|
|
@@ -135,6 +128,7 @@ module RuboCop
|
|
|
135
128
|
on_def(node)
|
|
136
129
|
end
|
|
137
130
|
alias on_numblock on_block
|
|
131
|
+
alias on_itblock on_block
|
|
138
132
|
|
|
139
133
|
def on_if(node)
|
|
140
134
|
return if accepted_form?(node)
|
|
@@ -206,19 +200,19 @@ module RuboCop
|
|
|
206
200
|
end
|
|
207
201
|
end
|
|
208
202
|
|
|
209
|
-
# rubocop:disable Metrics/AbcSize
|
|
203
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
210
204
|
def autocorrect(corrector, node, condition, replacement, guard)
|
|
211
205
|
corrector.replace(node.loc.keyword.join(condition.source_range), replacement)
|
|
212
206
|
|
|
213
207
|
if_branch = node.if_branch
|
|
214
208
|
else_branch = node.else_branch
|
|
215
209
|
|
|
216
|
-
corrector.replace(node.loc.begin, "\n") if node.
|
|
210
|
+
corrector.replace(node.loc.begin, "\n") if node.then?
|
|
217
211
|
|
|
218
|
-
if
|
|
219
|
-
autocorrect_heredoc_argument(corrector, node,
|
|
220
|
-
elsif
|
|
221
|
-
autocorrect_heredoc_argument(corrector, node,
|
|
212
|
+
if (if_heredoc = find_heredoc_argument(if_branch))
|
|
213
|
+
autocorrect_heredoc_argument(corrector, node, if_heredoc, else_branch, guard)
|
|
214
|
+
elsif (else_heredoc = find_heredoc_argument(else_branch))
|
|
215
|
+
autocorrect_heredoc_argument(corrector, node, else_heredoc, if_branch, guard)
|
|
222
216
|
else
|
|
223
217
|
corrector.remove(node.loc.end)
|
|
224
218
|
return unless node.else?
|
|
@@ -227,22 +221,37 @@ module RuboCop
|
|
|
227
221
|
corrector.remove(range_of_branch_to_remove(node, guard))
|
|
228
222
|
end
|
|
229
223
|
end
|
|
230
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
231
224
|
|
|
232
225
|
def heredoc?(argument)
|
|
233
226
|
argument.respond_to?(:heredoc?) && argument.heredoc?
|
|
234
227
|
end
|
|
235
228
|
|
|
236
|
-
def
|
|
229
|
+
def find_heredoc_argument(node)
|
|
230
|
+
return unless node
|
|
231
|
+
|
|
232
|
+
node = node.children.first while node.begin_type?
|
|
233
|
+
return node if heredoc?(node)
|
|
234
|
+
return unless node.call_type?
|
|
235
|
+
|
|
236
|
+
node.arguments.reverse_each do |argument|
|
|
237
|
+
heredoc_argument = find_heredoc_argument(argument)
|
|
238
|
+
return heredoc_argument if heredoc_argument
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
find_heredoc_argument(node.receiver)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def autocorrect_heredoc_argument(corrector, node, heredoc_node, leave_branch, guard)
|
|
237
245
|
remove_whole_lines(corrector, node.loc.end)
|
|
238
246
|
return unless node.else?
|
|
239
247
|
|
|
240
|
-
|
|
248
|
+
if leave_branch
|
|
249
|
+
remove_whole_lines(corrector, leave_branch.source_range)
|
|
250
|
+
corrector.insert_after(heredoc_node.loc.heredoc_end, "\n#{leave_branch.source}")
|
|
251
|
+
end
|
|
252
|
+
|
|
241
253
|
remove_whole_lines(corrector, node.loc.else)
|
|
242
254
|
remove_whole_lines(corrector, range_of_branch_to_remove(node, guard))
|
|
243
|
-
corrector.insert_after(
|
|
244
|
-
heredoc_branch.last_argument.loc.heredoc_end, "\n#{leave_branch.source}"
|
|
245
|
-
)
|
|
246
255
|
end
|
|
247
256
|
|
|
248
257
|
def range_of_branch_to_remove(node, guard)
|
|
@@ -6,8 +6,13 @@ module RuboCop
|
|
|
6
6
|
# Checks for presence or absence of braces around hash literal as a last
|
|
7
7
|
# array item depending on configuration.
|
|
8
8
|
#
|
|
9
|
-
# NOTE: This cop will ignore arrays where
|
|
10
|
-
# EnforcedStyle
|
|
9
|
+
# NOTE: This cop will ignore arrays where multiple items are all hashes,
|
|
10
|
+
# regardless of `EnforcedStyle`.
|
|
11
|
+
#
|
|
12
|
+
# [source,ruby]
|
|
13
|
+
# ----
|
|
14
|
+
# [{ one: 1 }, { two: 2 }]
|
|
15
|
+
# ----
|
|
11
16
|
#
|
|
12
17
|
# @example EnforcedStyle: braces (default)
|
|
13
18
|
# # bad
|
|
@@ -16,8 +21,11 @@ module RuboCop
|
|
|
16
21
|
# # good
|
|
17
22
|
# [1, 2, { one: 1, two: 2 }]
|
|
18
23
|
#
|
|
24
|
+
# # bad
|
|
25
|
+
# [one: 1, two: 2]
|
|
26
|
+
#
|
|
19
27
|
# # good
|
|
20
|
-
# [{ one: 1
|
|
28
|
+
# [{ one: 1, two: 2 }]
|
|
21
29
|
#
|
|
22
30
|
# @example EnforcedStyle: no_braces
|
|
23
31
|
# # bad
|
|
@@ -26,8 +34,11 @@ module RuboCop
|
|
|
26
34
|
# # good
|
|
27
35
|
# [1, 2, one: 1, two: 2]
|
|
28
36
|
#
|
|
37
|
+
# # bad
|
|
38
|
+
# [{ one: 1, two: 2 }]
|
|
39
|
+
#
|
|
29
40
|
# # good
|
|
30
|
-
# [
|
|
41
|
+
# [one: 1, two: 2]
|
|
31
42
|
class HashAsLastArrayItem < Base
|
|
32
43
|
include RangeHelp
|
|
33
44
|
include ConfigurableEnforcedStyle
|
|
@@ -36,7 +47,7 @@ module RuboCop
|
|
|
36
47
|
def on_hash(node)
|
|
37
48
|
return if node.children.first&.kwsplat_type?
|
|
38
49
|
return unless (array = containing_array(node))
|
|
39
|
-
return unless
|
|
50
|
+
return unless expected_braced_last_array_item?(array, node) && explicit_array?(array)
|
|
40
51
|
|
|
41
52
|
if braces_style?
|
|
42
53
|
check_braces(node)
|
|
@@ -52,10 +63,12 @@ module RuboCop
|
|
|
52
63
|
parent if parent&.array_type?
|
|
53
64
|
end
|
|
54
65
|
|
|
55
|
-
def
|
|
56
|
-
return false if array.
|
|
66
|
+
def expected_braced_last_array_item?(array, node)
|
|
67
|
+
return false if array.each_value.all? do |node|
|
|
68
|
+
node.hash_type? && (braces_style? ? node.braces? : !node.braces?)
|
|
69
|
+
end
|
|
57
70
|
|
|
58
|
-
array.
|
|
71
|
+
!array.values[-2]&.hash_type? && array.values.last.equal?(node)
|
|
59
72
|
end
|
|
60
73
|
|
|
61
74
|
def explicit_array?(array)
|
|
@@ -67,7 +80,12 @@ module RuboCop
|
|
|
67
80
|
return if node.braces?
|
|
68
81
|
|
|
69
82
|
add_offense(node, message: 'Wrap hash in `{` and `}`.') do |corrector|
|
|
70
|
-
|
|
83
|
+
if node.single_line? || same_line?(node, node.parent)
|
|
84
|
+
corrector.wrap(node, '{', '}')
|
|
85
|
+
else
|
|
86
|
+
indent = indent(node)
|
|
87
|
+
corrector.wrap(node, "{\n#{indent}", "\n#{indent}}")
|
|
88
|
+
end
|
|
71
89
|
end
|
|
72
90
|
end
|
|
73
91
|
|
|
@@ -44,17 +44,17 @@ module RuboCop
|
|
|
44
44
|
class HashConversion < Base
|
|
45
45
|
extend AutoCorrector
|
|
46
46
|
|
|
47
|
-
MSG_TO_H = 'Prefer ary.to_h to Hash[ary]
|
|
48
|
-
MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to Hash[arg1, arg2, ...]
|
|
49
|
-
MSG_LITERAL_HASH_ARG = 'Prefer literal hash to Hash[key: value, ...]
|
|
50
|
-
MSG_SPLAT = 'Prefer array_of_pairs.to_h to Hash[*array]
|
|
47
|
+
MSG_TO_H = 'Prefer `ary.to_h` to `Hash[ary]`.'
|
|
48
|
+
MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to `Hash[arg1, arg2, ...]`.'
|
|
49
|
+
MSG_LITERAL_HASH_ARG = 'Prefer literal hash to `Hash[key: value, ...]`.'
|
|
50
|
+
MSG_SPLAT = 'Prefer `array_of_pairs.to_h` to `Hash[*array]`.'
|
|
51
51
|
RESTRICT_ON_SEND = %i[[]].freeze
|
|
52
52
|
|
|
53
53
|
# @!method hash_from_array?(node)
|
|
54
54
|
def_node_matcher :hash_from_array?, '(send (const {nil? cbase} :Hash) :[] ...)'
|
|
55
55
|
|
|
56
56
|
def on_send(node)
|
|
57
|
-
return
|
|
57
|
+
return if part_of_ignored_node?(node) || !hash_from_array?(node)
|
|
58
58
|
|
|
59
59
|
# There are several cases:
|
|
60
60
|
# If there is one argument:
|
|
@@ -63,7 +63,8 @@ module RuboCop
|
|
|
63
63
|
# If there is 0 or 2+ arguments:
|
|
64
64
|
# Hash[a1, a2, a3, a4] => {a1 => a2, a3 => a4}
|
|
65
65
|
# ...but don't suggest correction if there is odd number of them (it is a bug)
|
|
66
|
-
node.arguments.
|
|
66
|
+
node.arguments.one? ? single_argument(node) : multi_argument(node)
|
|
67
|
+
ignore_node(node)
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
private
|
|
@@ -72,7 +73,7 @@ module RuboCop
|
|
|
72
73
|
first_argument = node.first_argument
|
|
73
74
|
if first_argument.hash_type?
|
|
74
75
|
register_offense_for_hash(node, first_argument)
|
|
75
|
-
elsif first_argument.
|
|
76
|
+
elsif first_argument.type?(:splat, :forwarded_restarg)
|
|
76
77
|
add_offense(node, message: MSG_SPLAT) unless allowed_splat_argument?
|
|
77
78
|
elsif use_zip_method_without_argument?(first_argument)
|
|
78
79
|
register_offense_for_zip_method(node, first_argument)
|
|
@@ -111,18 +112,33 @@ module RuboCop
|
|
|
111
112
|
end
|
|
112
113
|
|
|
113
114
|
def requires_parens?(node)
|
|
114
|
-
|
|
115
|
+
if node.call_type?
|
|
116
|
+
return false if node.method?(:[])
|
|
117
|
+
return true if node.arguments.any? && !node.parenthesized?
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
node.operator_keyword?
|
|
115
121
|
end
|
|
116
122
|
|
|
117
123
|
def multi_argument(node)
|
|
124
|
+
# A splat argument can expand to any number of elements, so the pairs
|
|
125
|
+
# can't be built statically and there is no literal hash to suggest.
|
|
126
|
+
return if node.arguments.any?(&:splat_type?)
|
|
127
|
+
|
|
118
128
|
if node.arguments.count.odd?
|
|
119
129
|
add_offense(node, message: MSG_LITERAL_MULTI_ARG)
|
|
120
130
|
else
|
|
121
|
-
|
|
122
|
-
|
|
131
|
+
correct_multi_argument(node)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def correct_multi_argument(node)
|
|
136
|
+
add_offense(node, message: MSG_LITERAL_MULTI_ARG) do |corrector|
|
|
137
|
+
corrector.replace(node, args_to_hash(node.arguments))
|
|
123
138
|
|
|
124
|
-
|
|
125
|
-
|
|
139
|
+
parent = node.parent
|
|
140
|
+
if parent&.send_type? && !parent.method?(:to_h) && !parent.parenthesized?
|
|
141
|
+
add_parentheses(parent, corrector)
|
|
126
142
|
end
|
|
127
143
|
end
|
|
128
144
|
end
|
|
@@ -74,8 +74,9 @@ module RuboCop
|
|
|
74
74
|
check_unused_block_args(node, key, value)
|
|
75
75
|
end
|
|
76
76
|
alias on_numblock on_block
|
|
77
|
+
alias on_itblock on_block
|
|
77
78
|
|
|
78
|
-
# rubocop:disable Metrics/AbcSize
|
|
79
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
79
80
|
def check_unused_block_args(node, key, value)
|
|
80
81
|
return if node.body.nil?
|
|
81
82
|
|
|
@@ -95,7 +96,6 @@ module RuboCop
|
|
|
95
96
|
register_each_args_offense(node, message, 'each_value', unused_range)
|
|
96
97
|
end
|
|
97
98
|
end
|
|
98
|
-
# rubocop:enable Metrics/AbcSize
|
|
99
99
|
|
|
100
100
|
def on_block_pass(node)
|
|
101
101
|
kv_each_with_block_pass(node.parent) do |target, method|
|
|
@@ -128,8 +128,8 @@ module RuboCop
|
|
|
128
128
|
lvar_sources = node.body.each_descendant(:lvar).map(&:source)
|
|
129
129
|
|
|
130
130
|
if block_arg.mlhs_type?
|
|
131
|
-
block_arg.each_descendant(:arg, :restarg).all? do |
|
|
132
|
-
lvar_sources.none?(
|
|
131
|
+
block_arg.each_descendant(:arg, :restarg).all? do |descendant|
|
|
132
|
+
lvar_sources.none?(descendant.source.delete_prefix('*'))
|
|
133
133
|
end
|
|
134
134
|
else
|
|
135
135
|
lvar_sources.none?(block_arg.source.delete_prefix('*'))
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Use `Hash#dig` instead of chaining potentially null `fetch` calls.
|
|
7
|
+
#
|
|
8
|
+
# When `fetch(identifier, nil)` calls are chained on a hash, the expectation
|
|
9
|
+
# is that each step in the chain returns either `nil` or another hash,
|
|
10
|
+
# and in both cases, these can be simplified with a single call to `dig` with
|
|
11
|
+
# multiple arguments.
|
|
12
|
+
#
|
|
13
|
+
# If the 2nd parameter is `{}` or `Hash.new`, an offense will also be registered,
|
|
14
|
+
# as long as the final call in the chain is a nil value. If a non-nil value is given,
|
|
15
|
+
# the chain will not be registered as an offense, as the default value cannot be safely
|
|
16
|
+
# given with `dig`.
|
|
17
|
+
#
|
|
18
|
+
# NOTE: See `Style/DigChain` for replacing chains of `dig` calls with
|
|
19
|
+
# a single method call.
|
|
20
|
+
#
|
|
21
|
+
# @safety
|
|
22
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
|
23
|
+
# is a `Hash` or that `fetch` or `dig` have the expected standard implementation.
|
|
24
|
+
#
|
|
25
|
+
# @example
|
|
26
|
+
# # bad
|
|
27
|
+
# hash.fetch('foo', nil)&.fetch('bar', nil)
|
|
28
|
+
#
|
|
29
|
+
# # bad
|
|
30
|
+
# # earlier members of the chain can return `{}` as long as the final `fetch`
|
|
31
|
+
# # has `nil` as a default value
|
|
32
|
+
# hash.fetch('foo', {}).fetch('bar', nil)
|
|
33
|
+
#
|
|
34
|
+
# # good
|
|
35
|
+
# hash.dig('foo', 'bar')
|
|
36
|
+
#
|
|
37
|
+
# # ok - not handled by the cop since the final `fetch` value is non-nil
|
|
38
|
+
# hash.fetch('foo', {}).fetch('bar', {})
|
|
39
|
+
#
|
|
40
|
+
class HashFetchChain < Base
|
|
41
|
+
extend AutoCorrector
|
|
42
|
+
extend TargetRubyVersion
|
|
43
|
+
|
|
44
|
+
MSG = 'Use `%<replacement>s` instead.'
|
|
45
|
+
RESTRICT_ON_SEND = %i[fetch].freeze
|
|
46
|
+
|
|
47
|
+
minimum_target_ruby_version 2.3
|
|
48
|
+
|
|
49
|
+
# @!method diggable?(node)
|
|
50
|
+
def_node_matcher :diggable?, <<~PATTERN
|
|
51
|
+
(call _ :fetch $_arg {nil (hash) (send (const {nil? cbase} :Hash) :new)})
|
|
52
|
+
PATTERN
|
|
53
|
+
|
|
54
|
+
def on_send(node)
|
|
55
|
+
return if ignored_node?(node)
|
|
56
|
+
return if last_fetch_non_nil?(node)
|
|
57
|
+
|
|
58
|
+
last_replaceable_node, arguments = inspect_chain(node)
|
|
59
|
+
return unless last_replaceable_node
|
|
60
|
+
return unless arguments.size > 1
|
|
61
|
+
|
|
62
|
+
range = last_replaceable_node.selector.join(node.loc.end)
|
|
63
|
+
replacement = replacement(arguments)
|
|
64
|
+
message = format(MSG, replacement: replacement)
|
|
65
|
+
|
|
66
|
+
add_offense(range, message: message) do |corrector|
|
|
67
|
+
corrector.replace(range, replacement)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
alias on_csend on_send
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def last_fetch_non_nil?(node)
|
|
75
|
+
# When chaining `fetch` methods, `fetch(x, {})` is acceptable within
|
|
76
|
+
# the chain, as long as the last method in the chain has a `nil`
|
|
77
|
+
# default value.
|
|
78
|
+
|
|
79
|
+
return false unless node.method?(:fetch)
|
|
80
|
+
|
|
81
|
+
!node.last_argument&.nil_type?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def inspect_chain(node)
|
|
85
|
+
arguments = []
|
|
86
|
+
|
|
87
|
+
while (arg = diggable?(node))
|
|
88
|
+
arguments.unshift(arg)
|
|
89
|
+
ignore_node(node)
|
|
90
|
+
last_replaceable_node = node
|
|
91
|
+
node = node.receiver
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
[last_replaceable_node, arguments]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def replacement(arguments)
|
|
98
|
+
values = arguments.map(&:source).join(', ')
|
|
99
|
+
"dig(#{values})"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Enforces the use of either `Hash#[]` or `Hash#fetch` for hash lookup.
|
|
7
|
+
#
|
|
8
|
+
# This cop can be configured to prefer either bracket-style (`[]`)
|
|
9
|
+
# or fetch-style lookup. It is disabled by default.
|
|
10
|
+
#
|
|
11
|
+
# When enforcing `fetch` style, only single-argument bracket access is flagged.
|
|
12
|
+
# When enforcing `brackets` style, only `fetch` calls with a single key
|
|
13
|
+
# argument are flagged (not those with default values or blocks).
|
|
14
|
+
#
|
|
15
|
+
# @safety
|
|
16
|
+
# This cop is unsafe because `Hash#[]` and `Hash#fetch` have different
|
|
17
|
+
# semantics. `Hash#[]` returns `nil` for missing keys, while `Hash#fetch`
|
|
18
|
+
# raises a `KeyError`. Replacing one with the other can change program
|
|
19
|
+
# behavior in cases where the key is missing.
|
|
20
|
+
#
|
|
21
|
+
# Additionally, it cannot be guaranteed that the receiver is a `Hash`
|
|
22
|
+
# or responds to the replacement method.
|
|
23
|
+
#
|
|
24
|
+
# @example EnforcedStyle: brackets (default)
|
|
25
|
+
# # bad
|
|
26
|
+
# hash.fetch(key)
|
|
27
|
+
#
|
|
28
|
+
# # good
|
|
29
|
+
# hash[key]
|
|
30
|
+
#
|
|
31
|
+
# # good - fetch with default value is allowed
|
|
32
|
+
# hash.fetch(key, default)
|
|
33
|
+
#
|
|
34
|
+
# # good - fetch with block is allowed
|
|
35
|
+
# hash.fetch(key) { default }
|
|
36
|
+
#
|
|
37
|
+
# @example EnforcedStyle: fetch
|
|
38
|
+
# # bad
|
|
39
|
+
# hash[key]
|
|
40
|
+
#
|
|
41
|
+
# # good
|
|
42
|
+
# hash.fetch(key)
|
|
43
|
+
#
|
|
44
|
+
# @example AllowedReceivers: ['Rails.cache']
|
|
45
|
+
# # good
|
|
46
|
+
# Rails.cache.fetch(name, options) { block }
|
|
47
|
+
#
|
|
48
|
+
class HashLookupMethod < Base
|
|
49
|
+
include ConfigurableEnforcedStyle
|
|
50
|
+
include AllowedReceivers
|
|
51
|
+
extend AutoCorrector
|
|
52
|
+
|
|
53
|
+
BRACKET_MSG = 'Use `Hash#[]` instead of `Hash#fetch`.'
|
|
54
|
+
FETCH_MSG = 'Use `Hash#fetch` instead of `Hash#[]`.'
|
|
55
|
+
|
|
56
|
+
RESTRICT_ON_SEND = %i[[] fetch].freeze
|
|
57
|
+
|
|
58
|
+
def on_send(node)
|
|
59
|
+
return if (receiver = node.receiver) && allowed_receiver?(receiver)
|
|
60
|
+
return if part_of_ignored_node?(node)
|
|
61
|
+
|
|
62
|
+
if offense_for_brackets?(node)
|
|
63
|
+
ignore_node(node.first_argument)
|
|
64
|
+
add_offense(node.loc.selector, message: BRACKET_MSG) do |corrector|
|
|
65
|
+
correct_fetch_to_brackets(corrector, node)
|
|
66
|
+
end
|
|
67
|
+
elsif offense_for_fetch?(node)
|
|
68
|
+
ignore_node(node.first_argument)
|
|
69
|
+
add_offense(node, message: FETCH_MSG) do |corrector|
|
|
70
|
+
correct_brackets_to_fetch(corrector, node)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
alias on_csend on_send
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def offense_for_brackets?(node)
|
|
79
|
+
style == :brackets && node.receiver && node.method?(:fetch) && node.arguments.one? &&
|
|
80
|
+
!node.block_literal? && !node.csend_type?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def offense_for_fetch?(node)
|
|
84
|
+
style == :fetch && node.method?(:[]) && node.arguments.one?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def correct_fetch_to_brackets(corrector, node)
|
|
88
|
+
key = node.first_argument.source
|
|
89
|
+
|
|
90
|
+
corrector.replace(node.loc.dot.join(node.source_range.end), "[#{key}]")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def correct_brackets_to_fetch(corrector, node)
|
|
94
|
+
key = node.first_argument.source
|
|
95
|
+
|
|
96
|
+
if node.csend_type?
|
|
97
|
+
corrector.replace(node.loc.dot.join(node.source_range.end), "&.fetch(#{key})")
|
|
98
|
+
else
|
|
99
|
+
corrector.replace(node.loc.selector.join(node.source_range.end), ".fetch(#{key})")
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -19,6 +19,22 @@ module RuboCop
|
|
|
19
19
|
# This cop is unsafe because it cannot be guaranteed that the receiver
|
|
20
20
|
# is a `Hash` or responds to the replacement method.
|
|
21
21
|
#
|
|
22
|
+
# Additionally, the replacement may change the order of the resulting
|
|
23
|
+
# hash: `Hash#slice` returns entries in the order the keys are given,
|
|
24
|
+
# whereas `select`, `filter`, and `reject` preserve the entry order of
|
|
25
|
+
# the receiver.
|
|
26
|
+
#
|
|
27
|
+
# For example:
|
|
28
|
+
#
|
|
29
|
+
# [source,ruby]
|
|
30
|
+
# ----
|
|
31
|
+
# hash = {foo: 1, bar: 2, baz: 3}
|
|
32
|
+
# keys = %i[baz foo]
|
|
33
|
+
#
|
|
34
|
+
# hash.select { |k, _v| keys.include?(k) } # => {foo: 1, baz: 3}
|
|
35
|
+
# hash.slice(*keys) # => {baz: 3, foo: 1}
|
|
36
|
+
# ----
|
|
37
|
+
#
|
|
22
38
|
# @example
|
|
23
39
|
#
|
|
24
40
|
# # bad
|
|
@@ -76,6 +76,9 @@ module RuboCop
|
|
|
76
76
|
# # good
|
|
77
77
|
# {foo:, bar:}
|
|
78
78
|
#
|
|
79
|
+
# # good - allowed to mix syntaxes
|
|
80
|
+
# {foo:, bar: baz}
|
|
81
|
+
#
|
|
79
82
|
# @example EnforcedShorthandSyntax: never
|
|
80
83
|
#
|
|
81
84
|
# # bad
|
|
@@ -209,12 +212,12 @@ module RuboCop
|
|
|
209
212
|
end
|
|
210
213
|
|
|
211
214
|
def word_symbol_pair?(pair)
|
|
212
|
-
return false unless pair.key.
|
|
215
|
+
return false unless pair.key.any_sym_type?
|
|
213
216
|
|
|
214
217
|
acceptable_19_syntax_symbol?(pair.key.source)
|
|
215
218
|
end
|
|
216
219
|
|
|
217
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
220
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity
|
|
218
221
|
def acceptable_19_syntax_symbol?(sym_name)
|
|
219
222
|
sym_name.delete_prefix!(':')
|
|
220
223
|
|
|
@@ -234,7 +237,6 @@ module RuboCop
|
|
|
234
237
|
(sym_name.start_with?("'") && sym_name.end_with?("'")) ||
|
|
235
238
|
(sym_name.start_with?('"') && sym_name.end_with?('"'))
|
|
236
239
|
end
|
|
237
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
238
240
|
|
|
239
241
|
def check(pairs, delim, msg)
|
|
240
242
|
pairs.each do |pair|
|
|
@@ -260,6 +262,8 @@ module RuboCop
|
|
|
260
262
|
|
|
261
263
|
hash_node = pair_node.parent
|
|
262
264
|
return unless hash_node.parent&.return_type? && !hash_node.braces?
|
|
265
|
+
# This runs once per pair, but the hash must only be wrapped once.
|
|
266
|
+
return unless pair_node.equal?(hash_node.pairs.first)
|
|
263
267
|
|
|
264
268
|
corrector.wrap(hash_node, '{', '}')
|
|
265
269
|
end
|
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Looks for uses of
|
|
7
|
-
#
|
|
6
|
+
# Looks for uses of `+_.each_with_object({}) {...}+`,
|
|
7
|
+
# `+_.map {...}.to_h+`, and `+Hash[_.map {...}]+` that are actually just
|
|
8
8
|
# transforming the keys of a hash, and tries to use a simpler & faster
|
|
9
9
|
# call to `transform_keys` instead.
|
|
10
10
|
# It should only be enabled on Ruby version 2.5 or newer.
|
|
11
11
|
# (`transform_keys` was added in Ruby 2.5.)
|
|
12
12
|
#
|
|
13
13
|
# @safety
|
|
14
|
-
# This cop
|
|
15
|
-
#
|
|
16
|
-
#
|
|
14
|
+
# This cop identifies the receiver as a hash by checking for literal hash
|
|
15
|
+
# syntax and common methods that are known to return hashes (e.g. `to_h`,
|
|
16
|
+
# `merge`, `invert`, `group_by`, etc.). However, it is unsafe because it
|
|
17
|
+
# is possible for a custom class to define one of these methods and return
|
|
18
|
+
# something other than a hash.
|
|
17
19
|
#
|
|
18
20
|
# @example
|
|
19
21
|
# # bad
|
|
@@ -21,10 +23,18 @@ module RuboCop
|
|
|
21
23
|
# Hash[{a: 1, b: 2}.collect { |k, v| [foo(k), v] }]
|
|
22
24
|
# {a: 1, b: 2}.map { |k, v| [k.to_s, v] }.to_h
|
|
23
25
|
# {a: 1, b: 2}.to_h { |k, v| [k.to_s, v] }
|
|
26
|
+
# foo.to_h.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
|
27
|
+
# foo.merge(bar).map { |k, v| [k.to_s, v] }.to_h
|
|
24
28
|
#
|
|
25
29
|
# # good
|
|
26
30
|
# {a: 1, b: 2}.transform_keys { |k| foo(k) }
|
|
27
31
|
# {a: 1, b: 2}.transform_keys { |k| k.to_s }
|
|
32
|
+
# foo.to_h.transform_keys { |k| k.to_sym }
|
|
33
|
+
# foo.merge(bar).transform_keys { |k| k.to_s }
|
|
34
|
+
#
|
|
35
|
+
# # Won't register an offense - receiver is not known to be a hash
|
|
36
|
+
# foo.bar.each_with_object({}) { |(k, v), h| h[k.to_s] = v }
|
|
37
|
+
# baz.map { |k, v| [k.to_s, v] }.to_h
|
|
28
38
|
class HashTransformKeys < Base
|
|
29
39
|
include HashTransformMethod
|
|
30
40
|
extend AutoCorrector
|
|
@@ -35,7 +45,7 @@ module RuboCop
|
|
|
35
45
|
# @!method on_bad_each_with_object(node)
|
|
36
46
|
def_node_matcher :on_bad_each_with_object, <<~PATTERN
|
|
37
47
|
(block
|
|
38
|
-
(call
|
|
48
|
+
(call #hash_receiver? :each_with_object (hash))
|
|
39
49
|
(args
|
|
40
50
|
(mlhs
|
|
41
51
|
(arg $_)
|
|
@@ -50,7 +60,7 @@ module RuboCop
|
|
|
50
60
|
(const _ :Hash)
|
|
51
61
|
:[]
|
|
52
62
|
(block
|
|
53
|
-
(call
|
|
63
|
+
(call #hash_receiver? {:map :collect})
|
|
54
64
|
(args
|
|
55
65
|
(arg $_)
|
|
56
66
|
(arg _val))
|
|
@@ -61,7 +71,7 @@ module RuboCop
|
|
|
61
71
|
def_node_matcher :on_bad_map_to_h, <<~PATTERN
|
|
62
72
|
(call
|
|
63
73
|
(block
|
|
64
|
-
(call
|
|
74
|
+
(call #hash_receiver? {:map :collect})
|
|
65
75
|
(args
|
|
66
76
|
(arg $_)
|
|
67
77
|
(arg _val))
|
|
@@ -72,7 +82,7 @@ module RuboCop
|
|
|
72
82
|
# @!method on_bad_to_h(node)
|
|
73
83
|
def_node_matcher :on_bad_to_h, <<~PATTERN
|
|
74
84
|
(block
|
|
75
|
-
(call
|
|
85
|
+
(call #hash_receiver? :to_h)
|
|
76
86
|
(args
|
|
77
87
|
(arg $_)
|
|
78
88
|
(arg _val))
|