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
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Checks for uses of if/then/else/end constructs on a single line.
|
|
7
|
-
#
|
|
8
|
-
#
|
|
6
|
+
# Checks for uses of `if/then/else/end` constructs on a single line.
|
|
7
|
+
# A ternary operator (`?:`) or multi-line `if` is more readable.
|
|
8
|
+
# `AlwaysCorrectToMultiline` config option can be set to `true` to autocorrect all offenses to
|
|
9
|
+
# multi-line constructs. When `AlwaysCorrectToMultiline` is `false` (default case) the
|
|
9
10
|
# autocorrect will first try converting them to ternary operators.
|
|
10
11
|
#
|
|
11
12
|
# @example
|
|
@@ -55,19 +56,21 @@ module RuboCop
|
|
|
55
56
|
include OnNormalIfUnless
|
|
56
57
|
extend AutoCorrector
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
MSG_SUFFIX = 'over single-line `%<keyword>s/then/else/end` constructs.'
|
|
60
|
+
MSG_TERNARY = "Favor the ternary operator (`?:`) #{MSG_SUFFIX}"
|
|
61
|
+
MSG_MULTILINE = "Favor multi-line `%<keyword>s` #{MSG_SUFFIX}"
|
|
60
62
|
|
|
61
63
|
def on_normal_if_unless(node)
|
|
62
64
|
return unless node.single_line?
|
|
63
65
|
return unless node.else_branch
|
|
64
66
|
return if node.elsif? || node.if_branch&.begin_type?
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
multiline = multiline?(node)
|
|
69
|
+
|
|
70
|
+
add_offense(node, message: message(node, multiline)) do |corrector|
|
|
68
71
|
next if part_of_ignored_node?(node)
|
|
69
72
|
|
|
70
|
-
autocorrect(corrector, node)
|
|
73
|
+
autocorrect(corrector, node, multiline)
|
|
71
74
|
|
|
72
75
|
ignore_node(node)
|
|
73
76
|
end
|
|
@@ -75,12 +78,18 @@ module RuboCop
|
|
|
75
78
|
|
|
76
79
|
private
|
|
77
80
|
|
|
78
|
-
def
|
|
79
|
-
|
|
81
|
+
def multiline?(node)
|
|
82
|
+
always_multiline? || cannot_replace_to_ternary?(node)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def message(node, multiline)
|
|
86
|
+
template = multiline ? MSG_MULTILINE : MSG_TERNARY
|
|
87
|
+
|
|
88
|
+
format(template, keyword: node.keyword)
|
|
80
89
|
end
|
|
81
90
|
|
|
82
|
-
def autocorrect(corrector, node)
|
|
83
|
-
if
|
|
91
|
+
def autocorrect(corrector, node, multiline)
|
|
92
|
+
if multiline
|
|
84
93
|
IfThenCorrector.new(node, indentation: configured_indentation_width).call(corrector)
|
|
85
94
|
else
|
|
86
95
|
corrector.replace(node, ternary_correction(node))
|
|
@@ -108,7 +117,7 @@ module RuboCop
|
|
|
108
117
|
end
|
|
109
118
|
|
|
110
119
|
def ternary_replacement(node)
|
|
111
|
-
condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
|
120
|
+
condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring -- takes all three branches in one step
|
|
112
121
|
|
|
113
122
|
"#{expr_replacement(condition)} ? " \
|
|
114
123
|
"#{expr_replacement(if_branch)} : " \
|
|
@@ -26,9 +26,10 @@ module RuboCop
|
|
|
26
26
|
splat kwsplat forwarded_args forwarded_restarg forwarded_kwrestarg block_pass
|
|
27
27
|
].freeze
|
|
28
28
|
|
|
29
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
29
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
30
30
|
def on_send(node)
|
|
31
31
|
return unless (dot = node.loc.dot)
|
|
32
|
+
return if unary_method_no_operator?(node)
|
|
32
33
|
return if node.receiver.const_type? || !node.arguments.one?
|
|
33
34
|
|
|
34
35
|
return unless (rhs = node.first_argument)
|
|
@@ -43,10 +44,17 @@ module RuboCop
|
|
|
43
44
|
corrector.insert_after(selector, ' ') if insert_space_after?(node)
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
47
47
|
|
|
48
48
|
private
|
|
49
49
|
|
|
50
|
+
# `foo.~@` and `foo.!@` call the method `~` and `!` respectively. While those
|
|
51
|
+
# are operator methods, we don't want to actually consider them as such.
|
|
52
|
+
def unary_method_no_operator?(node)
|
|
53
|
+
return false unless node.nonmutating_unary_operator_method?
|
|
54
|
+
|
|
55
|
+
node.method_name.to_s != node.selector.source
|
|
56
|
+
end
|
|
57
|
+
|
|
50
58
|
# Checks for an acceptable case of `foo.+(bar).baz`.
|
|
51
59
|
def method_call_with_parenthesized_arg?(argument)
|
|
52
60
|
return false unless argument.parent.parent&.send_type?
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'tsort'
|
|
4
|
-
|
|
5
3
|
module RuboCop
|
|
6
4
|
module Cop
|
|
7
5
|
module Style
|
|
8
6
|
# Checks for simple usages of parallel assignment.
|
|
7
|
+
# Parallel assignment is less readable than individual
|
|
8
|
+
# assignments and makes it harder to follow what each
|
|
9
|
+
# variable is being set to.
|
|
10
|
+
#
|
|
9
11
|
# This will only complain when the number of variables
|
|
10
12
|
# being assigned matched the number of assigning variables.
|
|
11
13
|
#
|
|
@@ -16,7 +18,7 @@ module RuboCop
|
|
|
16
18
|
#
|
|
17
19
|
# # good
|
|
18
20
|
# one, two = *foo
|
|
19
|
-
# a, b = foo
|
|
21
|
+
# a, b = foo
|
|
20
22
|
# a, b = b, a
|
|
21
23
|
#
|
|
22
24
|
# a = 1
|
|
@@ -29,18 +31,21 @@ module RuboCop
|
|
|
29
31
|
MSG = 'Do not use parallel assignment.'
|
|
30
32
|
|
|
31
33
|
def on_masgn(node) # rubocop:disable Metrics/AbcSize
|
|
34
|
+
return if part_of_ignored_node?(node)
|
|
35
|
+
|
|
32
36
|
rhs = node.rhs
|
|
33
37
|
rhs = rhs.body if rhs.rescue_type?
|
|
34
38
|
rhs_elements = Array(rhs).compact # edge case for one constant
|
|
35
39
|
|
|
36
40
|
return if allowed_lhs?(node.assignments) || allowed_rhs?(rhs) ||
|
|
37
|
-
allowed_masign?(node.assignments, rhs_elements)
|
|
41
|
+
allowed_masign?(node.assignments, rhs_elements) || contains_heredoc?(rhs)
|
|
38
42
|
|
|
39
43
|
range = node.source_range.begin.join(rhs.source_range.end)
|
|
40
44
|
|
|
41
45
|
add_offense(range) do |corrector|
|
|
42
46
|
autocorrect(corrector, node, rhs)
|
|
43
47
|
end
|
|
48
|
+
ignore_node(node)
|
|
44
49
|
end
|
|
45
50
|
|
|
46
51
|
private
|
|
@@ -72,6 +77,13 @@ module RuboCop
|
|
|
72
77
|
!node.array_type? || elements.any?(&:splat_type?)
|
|
73
78
|
end
|
|
74
79
|
|
|
80
|
+
# Autocorrection splits the assignment into single assignments on
|
|
81
|
+
# consecutive lines, which would put following assignments into the
|
|
82
|
+
# heredoc body unless the heredoc bodies were moved along.
|
|
83
|
+
def contains_heredoc?(node)
|
|
84
|
+
node.each_descendant(:any_str).any?(&:heredoc?)
|
|
85
|
+
end
|
|
86
|
+
|
|
75
87
|
def assignment_corrector(node, rhs, order)
|
|
76
88
|
if node.parent&.rescue_type?
|
|
77
89
|
_assignment, modifier = *node.parent
|
|
@@ -91,15 +103,9 @@ module RuboCop
|
|
|
91
103
|
def find_valid_order(left_elements, right_elements)
|
|
92
104
|
# arrange left_elements in an order such that no corresponding right
|
|
93
105
|
# element refers to a left element earlier in the sequence
|
|
94
|
-
# this can be done using an algorithm called a "topological sort"
|
|
95
|
-
# fortunately for us, Ruby's stdlib contains an implementation
|
|
96
106
|
assignments = left_elements.zip(right_elements)
|
|
97
107
|
|
|
98
|
-
|
|
99
|
-
AssignmentSorter.new(assignments).tsort
|
|
100
|
-
rescue TSort::Cyclic
|
|
101
|
-
nil
|
|
102
|
-
end
|
|
108
|
+
AssignmentSorter.new(assignments).tsort
|
|
103
109
|
end
|
|
104
110
|
|
|
105
111
|
# Converts (send nil :something) nodes to (send (:self) :something).
|
|
@@ -114,10 +120,9 @@ module RuboCop
|
|
|
114
120
|
# @!method implicit_self_getter?(node)
|
|
115
121
|
def_node_matcher :implicit_self_getter?, '(send nil? $_)'
|
|
116
122
|
|
|
117
|
-
#
|
|
118
|
-
#
|
|
123
|
+
# Topologically sorts the assignments with Kahn's algorithm.
|
|
124
|
+
# https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm
|
|
119
125
|
class AssignmentSorter
|
|
120
|
-
include TSort
|
|
121
126
|
extend RuboCop::NodePattern::Macros
|
|
122
127
|
|
|
123
128
|
# @!method var_name(node)
|
|
@@ -133,21 +138,39 @@ module RuboCop
|
|
|
133
138
|
@assignments = assignments
|
|
134
139
|
end
|
|
135
140
|
|
|
136
|
-
def
|
|
137
|
-
@assignments.
|
|
141
|
+
def tsort
|
|
142
|
+
dependencies = @assignments.to_h do |assignment|
|
|
143
|
+
[assignment, dependencies_for_assignment(assignment)]
|
|
144
|
+
end
|
|
145
|
+
result = []
|
|
146
|
+
|
|
147
|
+
while (matched_node, = dependencies.find { |_node, edges| edges.empty? })
|
|
148
|
+
dependencies.delete(matched_node)
|
|
149
|
+
result.push(matched_node)
|
|
150
|
+
|
|
151
|
+
dependencies.each do |node, edges|
|
|
152
|
+
dependencies[node].delete(matched_node) if edges.include?(matched_node)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
# Cyclic dependency
|
|
156
|
+
return nil if dependencies.any?
|
|
157
|
+
|
|
158
|
+
result
|
|
138
159
|
end
|
|
139
160
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
161
|
+
# Returns all the assignments which must come after `assignment`
|
|
162
|
+
# (due to dependencies on the previous value of the assigned var)
|
|
163
|
+
def dependencies_for_assignment(assignment)
|
|
143
164
|
my_lhs, _my_rhs = *assignment
|
|
144
165
|
|
|
145
|
-
@assignments.
|
|
146
|
-
|
|
166
|
+
@assignments.filter_map do |other|
|
|
167
|
+
# Exclude self, there are no dependencies in cases such as `a, b = a, b`.
|
|
168
|
+
next if other == assignment
|
|
147
169
|
|
|
170
|
+
_other_lhs, other_rhs = *other
|
|
148
171
|
next unless dependency?(my_lhs, other_rhs)
|
|
149
172
|
|
|
150
|
-
|
|
173
|
+
other
|
|
151
174
|
end
|
|
152
175
|
end
|
|
153
176
|
|
|
@@ -161,9 +184,8 @@ module RuboCop
|
|
|
161
184
|
def accesses?(rhs, lhs)
|
|
162
185
|
if lhs.method?(:[]=)
|
|
163
186
|
# FIXME: Workaround `rubocop:disable` comment for JRuby.
|
|
164
|
-
# rubocop:disable Performance/RedundantEqualityComparisonBlock
|
|
187
|
+
# rubocop:disable-next Performance/RedundantEqualityComparisonBlock -- a JRuby workaround, as the comment above says
|
|
165
188
|
matching_calls(rhs, lhs.receiver, :[]).any? { |args| args == lhs.arguments }
|
|
166
|
-
# rubocop:enable Performance/RedundantEqualityComparisonBlock
|
|
167
189
|
else
|
|
168
190
|
access_method = lhs.method_name.to_s.chop.to_sym
|
|
169
191
|
matching_calls(rhs, lhs.receiver, access_method).any?
|
|
@@ -210,14 +232,23 @@ module RuboCop
|
|
|
210
232
|
def source(node, loc)
|
|
211
233
|
# __FILE__ is treated as a StrNode but has no begin
|
|
212
234
|
if node.str_type? && loc.respond_to?(:begin) && loc.begin.nil?
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
235
|
+
# `%w` elements have no per-element delimiter, so the value must be
|
|
236
|
+
# quoted and escaped to stay valid (e.g. `%w(it's)` -> `'it\'s'`).
|
|
237
|
+
quote(node.value)
|
|
238
|
+
elsif node.sym_type? && !node.loc?(:begin)
|
|
239
|
+
# `%i` elements have no per-element delimiter, so a symbol that needs
|
|
240
|
+
# quoting must be emitted as `:"..."` (e.g. `%i(foo-bar)` -> `:"foo-bar"`),
|
|
241
|
+
# otherwise `:foo-bar` would parse as `:foo.-(bar)`.
|
|
242
|
+
node.value.inspect
|
|
216
243
|
else
|
|
217
244
|
node.source
|
|
218
245
|
end
|
|
219
246
|
end
|
|
220
247
|
|
|
248
|
+
def quote(string)
|
|
249
|
+
"'#{string.gsub(/[\\']/) { |char| "\\#{char}" }}'"
|
|
250
|
+
end
|
|
251
|
+
|
|
221
252
|
def extract_sources(node)
|
|
222
253
|
node.children.map(&:source)
|
|
223
254
|
end
|
|
@@ -123,10 +123,15 @@ module RuboCop
|
|
|
123
123
|
|
|
124
124
|
def parens_allowed?(node)
|
|
125
125
|
parens_required?(node) ||
|
|
126
|
-
(safe_assignment?(node) &&
|
|
126
|
+
(safe_assignment?(node) && safe_assignment_kept?) ||
|
|
127
127
|
(node.multiline? && allow_multiline_conditions?)
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
+
def safe_assignment_kept?
|
|
131
|
+
safe_assignment_allowed? ||
|
|
132
|
+
config.for_enabled_cop('Lint/AssignmentInCondition')['AllowSafeAssignment']
|
|
133
|
+
end
|
|
134
|
+
|
|
130
135
|
def allow_multiline_conditions?
|
|
131
136
|
cop_config['AllowInMultilineConditions']
|
|
132
137
|
end
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for consecutive calls to `select`/`filter`/`find_all` and `reject`
|
|
7
|
+
# on the same receiver with the same block body, where `partition` could be
|
|
8
|
+
# used instead. Also detects two `select` or two `reject` calls where one
|
|
9
|
+
# block negates the other with `!`. Using `partition` reduces two collection
|
|
10
|
+
# traversals to one.
|
|
11
|
+
#
|
|
12
|
+
# @safety
|
|
13
|
+
# This cop is unsafe because:
|
|
14
|
+
#
|
|
15
|
+
# * `Hash#select` and `Hash#reject` return hashes, but `Hash#partition`
|
|
16
|
+
# returns nested arrays.
|
|
17
|
+
# * When the receiver has side effects, calling it once (with `partition`)
|
|
18
|
+
# versus twice (with `select` + `reject`) may produce different results.
|
|
19
|
+
# * Custom classes may override `select`/`reject` without providing a
|
|
20
|
+
# compatible `partition` method.
|
|
21
|
+
#
|
|
22
|
+
# @example
|
|
23
|
+
# # bad
|
|
24
|
+
# positives = array.select { |x| x > 0 }
|
|
25
|
+
# negatives = array.reject { |x| x > 0 }
|
|
26
|
+
#
|
|
27
|
+
# # bad
|
|
28
|
+
# positives = array.filter { |x| x > 0 }
|
|
29
|
+
# negatives = array.reject { |x| x > 0 }
|
|
30
|
+
#
|
|
31
|
+
# # bad
|
|
32
|
+
# negatives = array.reject { |x| x > 0 }
|
|
33
|
+
# positives = array.select { |x| x > 0 }
|
|
34
|
+
#
|
|
35
|
+
# # bad
|
|
36
|
+
# positives = array.select(&:positive?)
|
|
37
|
+
# negatives = array.reject(&:positive?)
|
|
38
|
+
#
|
|
39
|
+
# # bad
|
|
40
|
+
# positives = array.select(&:positive?)
|
|
41
|
+
# negatives = array.reject { |x| x.positive? }
|
|
42
|
+
#
|
|
43
|
+
# # bad
|
|
44
|
+
# positives = array.select { |x| x.positive? }
|
|
45
|
+
# non_positives = array.select { |x| !x.positive? }
|
|
46
|
+
#
|
|
47
|
+
# # good
|
|
48
|
+
# positives, negatives = array.partition { |x| x > 0 }
|
|
49
|
+
#
|
|
50
|
+
# # good
|
|
51
|
+
# positives, non_positives = array.partition { |x| x.positive? }
|
|
52
|
+
#
|
|
53
|
+
# # good
|
|
54
|
+
# positives, negatives = array.partition(&:positive?)
|
|
55
|
+
#
|
|
56
|
+
class PartitionInsteadOfDoubleSelect < Base
|
|
57
|
+
include RangeHelp
|
|
58
|
+
extend AutoCorrector
|
|
59
|
+
|
|
60
|
+
MSG = 'Use `partition` instead of consecutive `%<first>s` and `%<second>s` calls.'
|
|
61
|
+
|
|
62
|
+
SELECT_METHODS = %i[select filter find_all].freeze
|
|
63
|
+
CANDIDATE_METHODS = (SELECT_METHODS + %i[reject]).to_set.freeze
|
|
64
|
+
RESTRICT_ON_SEND = (SELECT_METHODS + %i[reject]).freeze
|
|
65
|
+
|
|
66
|
+
# @!method symbol_proc_method?(node)
|
|
67
|
+
def_node_matcher :symbol_proc_method?, <<~PATTERN
|
|
68
|
+
(block _ (args (arg _name)) (send (lvar _name) $_method_name))
|
|
69
|
+
PATTERN
|
|
70
|
+
|
|
71
|
+
def on_block(node)
|
|
72
|
+
return unless CANDIDATE_METHODS.include?(node.method_name)
|
|
73
|
+
|
|
74
|
+
find_and_register_offense(node)
|
|
75
|
+
end
|
|
76
|
+
alias on_numblock on_block
|
|
77
|
+
alias on_itblock on_block
|
|
78
|
+
|
|
79
|
+
def on_send(node)
|
|
80
|
+
return unless node.last_argument&.block_pass_type?
|
|
81
|
+
|
|
82
|
+
find_and_register_offense(node)
|
|
83
|
+
end
|
|
84
|
+
alias on_csend on_send
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def find_and_register_offense(node)
|
|
89
|
+
container = node_container(node)
|
|
90
|
+
return unless container
|
|
91
|
+
|
|
92
|
+
sibling_container = container.left_sibling
|
|
93
|
+
sibling = find_matching_candidate(node, sibling_container)
|
|
94
|
+
return unless sibling
|
|
95
|
+
|
|
96
|
+
register_offense(node, sibling, container, sibling_container)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def node_container(node)
|
|
100
|
+
parent = node.parent
|
|
101
|
+
if parent&.begin_type?
|
|
102
|
+
node
|
|
103
|
+
elsif parent&.assignment? && parent.parent&.begin_type?
|
|
104
|
+
parent
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def find_matching_candidate(node, sibling_container)
|
|
109
|
+
return unless sibling_container
|
|
110
|
+
|
|
111
|
+
sibling = extract_candidate(sibling_container)
|
|
112
|
+
return unless sibling
|
|
113
|
+
return unless node.receiver == sibling.receiver
|
|
114
|
+
return unless matching_pair?(node, sibling)
|
|
115
|
+
|
|
116
|
+
sibling
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def matching_pair?(node, sibling)
|
|
120
|
+
(complementary_pair?(node, sibling) && equivalent_predicate?(node, sibling)) ||
|
|
121
|
+
(node.method?(sibling.method_name) && negated_predicate?(node, sibling))
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def extract_candidate(container)
|
|
125
|
+
extract_block(container) || extract_block_pass_send(container)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def extract_block(container)
|
|
129
|
+
if container.any_block_type?
|
|
130
|
+
container
|
|
131
|
+
elsif container.assignment?
|
|
132
|
+
rhs = container.children.last
|
|
133
|
+
rhs if rhs&.any_block_type?
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def extract_block_pass_send(container)
|
|
138
|
+
node = container.assignment? ? container.children.last : container
|
|
139
|
+
return unless node&.type?(:call)
|
|
140
|
+
return unless node.last_argument&.block_pass_type?
|
|
141
|
+
|
|
142
|
+
node
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def complementary_pair?(node1, node2)
|
|
146
|
+
m1 = node1.method_name
|
|
147
|
+
m2 = node2.method_name
|
|
148
|
+
(SELECT_METHODS.include?(m1) && m2 == :reject) ||
|
|
149
|
+
(m1 == :reject && SELECT_METHODS.include?(m2))
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def equivalent_predicate?(node1, node2)
|
|
153
|
+
if node1.any_block_type? && node2.any_block_type?
|
|
154
|
+
same_block_contents?(node1, node2)
|
|
155
|
+
elsif node1.any_block_type?
|
|
156
|
+
block_matches_block_pass?(node1, node2)
|
|
157
|
+
elsif node2.any_block_type?
|
|
158
|
+
block_matches_block_pass?(node2, node1)
|
|
159
|
+
else
|
|
160
|
+
node1.last_argument == node2.last_argument
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def same_block_contents?(block1, block2)
|
|
165
|
+
return false unless block1.type == block2.type
|
|
166
|
+
|
|
167
|
+
if block1.block_type?
|
|
168
|
+
block1.arguments == block2.arguments &&
|
|
169
|
+
block1.body == block2.body
|
|
170
|
+
else
|
|
171
|
+
block1.body == block2.body
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def block_matches_block_pass?(block_node, send_node)
|
|
176
|
+
method_name = symbol_proc_method?(block_node)
|
|
177
|
+
return false unless method_name
|
|
178
|
+
|
|
179
|
+
sym_node = send_node.last_argument.children.first
|
|
180
|
+
sym_node.sym_type? && sym_node.children.first == method_name
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def negated_predicate?(node1, node2)
|
|
184
|
+
return false unless node1.any_block_type? && node2.any_block_type?
|
|
185
|
+
return false unless node1.type == node2.type
|
|
186
|
+
return false if node1.block_type? && node1.arguments != node2.arguments
|
|
187
|
+
|
|
188
|
+
negated_body?(node1.body, node2.body) || negated_body?(node2.body, node1.body)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def negated_body?(body1, body2)
|
|
192
|
+
body1&.send_type? && body1.method?(:!) && body1.receiver == body2
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def register_offense(node, sibling, container, sibling_container)
|
|
196
|
+
message = format(MSG, first: sibling.method_name, second: node.method_name)
|
|
197
|
+
|
|
198
|
+
add_offense(container, message: message) do |corrector|
|
|
199
|
+
next unless both_lvasgn?(container, sibling_container)
|
|
200
|
+
|
|
201
|
+
autocorrect(corrector, node, sibling, container, sibling_container)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def both_lvasgn?(container, sibling_container)
|
|
206
|
+
container.lvasgn_type? && sibling_container.lvasgn_type?
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def autocorrect(corrector, node, sibling, container, sibling_container)
|
|
210
|
+
if complementary_pair?(node, sibling)
|
|
211
|
+
select_var, reject_var =
|
|
212
|
+
complementary_variable_order(sibling, container, sibling_container)
|
|
213
|
+
partition_node = select_node_for(sibling, container)
|
|
214
|
+
else
|
|
215
|
+
select_var, reject_var, partition_node =
|
|
216
|
+
negation_partition_args(node, sibling, container, sibling_container)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
partition_call = build_partition_call(partition_node)
|
|
220
|
+
replacement = "#{select_var}, #{reject_var} = #{partition_call}"
|
|
221
|
+
|
|
222
|
+
corrector.replace(sibling_container, replacement)
|
|
223
|
+
range = range_by_whole_lines(container.source_range, include_final_newline: true)
|
|
224
|
+
corrector.remove(range)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def complementary_variable_order(sibling, container, sibling_container)
|
|
228
|
+
if SELECT_METHODS.include?(sibling.method_name)
|
|
229
|
+
[sibling_container.children.first, container.children.first]
|
|
230
|
+
else
|
|
231
|
+
[container.children.first, sibling_container.children.first]
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def negation_partition_args(node, sibling, container, sibling_container)
|
|
236
|
+
node_is_negated = negated_body?(node.body, sibling.body)
|
|
237
|
+
is_select = SELECT_METHODS.include?(node.method_name)
|
|
238
|
+
# For select: non-negated is truthy (first). For reject: negated is truthy (first).
|
|
239
|
+
node_is_truthy = is_select != node_is_negated
|
|
240
|
+
partition_node = node_is_negated ? sibling : node
|
|
241
|
+
|
|
242
|
+
if node_is_truthy
|
|
243
|
+
[container.children.first, sibling_container.children.first, partition_node]
|
|
244
|
+
else
|
|
245
|
+
[sibling_container.children.first, container.children.first, partition_node]
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def select_node_for(sibling, container)
|
|
250
|
+
if SELECT_METHODS.include?(sibling.method_name)
|
|
251
|
+
sibling
|
|
252
|
+
else
|
|
253
|
+
container.children.last
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def build_partition_call(node)
|
|
258
|
+
source = node.source
|
|
259
|
+
send_node = node.any_block_type? ? node.send_node : node
|
|
260
|
+
selector = send_node.loc.selector
|
|
261
|
+
offset = node.source_range.begin_pos
|
|
262
|
+
method_start = selector.begin_pos - offset
|
|
263
|
+
method_end = selector.end_pos - offset
|
|
264
|
+
|
|
265
|
+
"#{source[0...method_start]}partition#{source[method_end..]}"
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
end
|
|
@@ -4,6 +4,8 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
6
|
# Enforces the consistent usage of `%`-literal delimiters.
|
|
7
|
+
# Using consistent delimiters across the codebase reduces
|
|
8
|
+
# cognitive load when reading `%`-literals.
|
|
7
9
|
#
|
|
8
10
|
# Specify the 'default' key to set all preferred delimiters at once. You
|
|
9
11
|
# can continue to specify individual preferred delimiters to override the
|
|
@@ -99,6 +101,8 @@ module RuboCop
|
|
|
99
101
|
def string_source(node)
|
|
100
102
|
if node.is_a?(String)
|
|
101
103
|
node.scrub
|
|
104
|
+
elsif node.is_a?(Symbol)
|
|
105
|
+
node.to_s
|
|
102
106
|
elsif node.respond_to?(:type) && node.type?(:str, :sym)
|
|
103
107
|
node.source
|
|
104
108
|
end
|
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
|
45
45
|
# Report offense only if changing case doesn't change semantics,
|
|
46
46
|
# i.e., if the string would become dynamic or has special characters.
|
|
47
47
|
ast = parse(corrected(node.source)).ast
|
|
48
|
-
return if node.children != ast
|
|
48
|
+
return if node.children != ast&.children
|
|
49
49
|
|
|
50
50
|
add_offense(node.loc.begin) do |corrector|
|
|
51
51
|
corrector.replace(node, corrected(node.source))
|
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
|
5
5
|
module Style
|
|
6
6
|
# Looks for uses of Perl-style regexp match
|
|
7
7
|
# backreferences and their English versions like
|
|
8
|
-
# $1, $2, $&,
|
|
8
|
+
# $1, $2, $&, $MATCH, $PREMATCH, etc.
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
11
|
# # bad
|
|
@@ -69,6 +69,10 @@ module RuboCop
|
|
|
69
69
|
# @return [String, nil]
|
|
70
70
|
def preferred_expression_to(node)
|
|
71
71
|
first = node.to_a.first
|
|
72
|
+
# NOTE: `$+` / `$LAST_PAREN_MATCH` is deliberately not converted. It
|
|
73
|
+
# refers to the last group that actually matched, which has no concise
|
|
74
|
+
# `Regexp.last_match` equivalent (`Regexp.last_match(-1)` is the last
|
|
75
|
+
# group in the pattern, which may be `nil`).
|
|
72
76
|
case first
|
|
73
77
|
when ::Integer
|
|
74
78
|
"Regexp.last_match(#{first})"
|
|
@@ -78,8 +82,6 @@ module RuboCop
|
|
|
78
82
|
'Regexp.last_match.pre_match'
|
|
79
83
|
when :$', :$POSTMATCH
|
|
80
84
|
'Regexp.last_match.post_match'
|
|
81
|
-
when :$+, :$LAST_PAREN_MATCH
|
|
82
|
-
'Regexp.last_match(-1)'
|
|
83
85
|
end
|
|
84
86
|
end
|
|
85
87
|
|