rubocop 1.79.2 → 1.88.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 +2 -2
- data/config/default.yml +259 -90
- data/config/obsoletion.yml +30 -1
- data/exe/rubocop +1 -8
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
- 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 +1 -1
- data/lib/rubocop/cli.rb +35 -9
- data/lib/rubocop/comment_config.rb +59 -17
- data/lib/rubocop/config.rb +14 -10
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader.rb +37 -23
- data/lib/rubocop/config_loader_resolver.rb +20 -10
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
- data/lib/rubocop/config_store.rb +7 -2
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/base.rb +25 -4
- data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
- data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +26 -7
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -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/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
- data/lib/rubocop/cop/gemspec/require_mfa.rb +5 -5
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
- 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 +28 -2
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +9 -9
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -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 +41 -4
- data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
- data/lib/rubocop/cop/layout/class_structure.rb +14 -7
- data/lib/rubocop/cop/layout/dot_position.rb +2 -2
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +26 -7
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +31 -13
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +2 -2
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
- data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
- data/lib/rubocop/cop/layout/end_alignment.rb +10 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +34 -1
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
- data/lib/rubocop/cop/layout/hash_alignment.rb +3 -6
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- 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 +123 -7
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +26 -9
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -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 +229 -39
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
- data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
- data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +4 -2
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_assignment.rb +1 -11
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +1 -10
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +45 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
- data/lib/rubocop/cop/lint/constant_reassignment.rb +93 -11
- data/lib/rubocop/cop/lint/constant_resolution.rb +6 -6
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
- data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
- data/lib/rubocop/cop/lint/debugger.rb +0 -3
- data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -12
- 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 +6 -1
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
- 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 -2
- data/lib/rubocop/cop/lint/float_comparison.rb +2 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +25 -5
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +9 -12
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -10
- data/lib/rubocop/cop/lint/multiple_comparison.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 +1 -1
- 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 +3 -0
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
- data/lib/rubocop/cop/lint/raise_exception.rb +1 -1
- data/lib/rubocop/cop/lint/rand_one.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +27 -10
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -12
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +15 -4
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +36 -12
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +12 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +10 -3
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_object.rb +5 -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 +2 -1
- 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 +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +18 -0
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
- 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 +39 -7
- 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 +14 -0
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +12 -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 +28 -1
- data/lib/rubocop/cop/lint/to_json.rb +12 -16
- 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 +4 -2
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +7 -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/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/useless_assignment.rb +53 -25
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
- data/lib/rubocop/cop/lint/useless_or.rb +15 -2
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +8 -4
- 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 +37 -11
- data/lib/rubocop/cop/lint/void.rb +39 -12
- data/lib/rubocop/cop/message_annotator.rb +1 -1
- data/lib/rubocop/cop/metrics/block_length.rb +1 -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 +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
- data/lib/rubocop/cop/migration/department_name.rb +12 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +4 -6
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +5 -5
- data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
- data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
- data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
- data/lib/rubocop/cop/mixin.rb +86 -0
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_method.rb +32 -8
- data/lib/rubocop/cop/naming/predicate_prefix.rb +12 -12
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/offense.rb +17 -1
- data/lib/rubocop/cop/registry.rb +62 -38
- data/lib/rubocop/cop/security/eval.rb +15 -2
- data/lib/rubocop/cop/security/io_methods.rb +1 -1
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +15 -4
- data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
- 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 +25 -7
- data/lib/rubocop/cop/style/array_first_last.rb +12 -1
- data/lib/rubocop/cop/style/array_intersect.rb +50 -12
- 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 +8 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +39 -32
- data/lib/rubocop/cop/style/case_equality.rb +29 -15
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +19 -2
- data/lib/rubocop/cop/style/class_equality_comparison.rb +21 -13
- data/lib/rubocop/cop/style/class_methods_definitions.rb +11 -5
- data/lib/rubocop/cop/style/collection_compact.rb +36 -16
- data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
- data/lib/rubocop/cop/style/combinable_loops.rb +5 -0
- data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +7 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +14 -19
- data/lib/rubocop/cop/style/constant_visibility.rb +20 -12
- data/lib/rubocop/cop/style/copyright.rb +22 -11
- data/lib/rubocop/cop/style/date_time.rb +4 -4
- data/lib/rubocop/cop/style/dig_chain.rb +5 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
- data/lib/rubocop/cop/style/documentation.rb +6 -6
- data/lib/rubocop/cop/style/documentation_method.rb +8 -8
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +2 -0
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_class_definition.rb +119 -0
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +0 -6
- 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 +23 -5
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
- 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 +15 -1
- data/lib/rubocop/cop/style/for.rb +3 -0
- data/lib/rubocop/cop/style/format_string.rb +4 -3
- data/lib/rubocop/cop/style/format_string_token.rb +49 -5
- data/lib/rubocop/cop/style/global_vars.rb +5 -2
- data/lib/rubocop/cop/style/guard_clause.rb +27 -22
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
- data/lib/rubocop/cop/style/hash_lookup_method.rb +106 -0
- data/lib/rubocop/cop/style/hash_slice.rb +16 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
- data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
- data/lib/rubocop/cop/style/if_inside_else.rb +16 -7
- data/lib/rubocop/cop/style/if_unless_modifier.rb +58 -18
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -12
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inline_comment.rb +4 -1
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
- data/lib/rubocop/cop/style/lambda_call.rb +8 -8
- data/lib/rubocop/cop/style/magic_comment_format.rb +3 -3
- data/lib/rubocop/cop/style/map_join.rb +123 -0
- 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 +17 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/min_max_comparison.rb +1 -1
- data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
- data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
- data/lib/rubocop/cop/style/mutable_constant.rb +106 -12
- data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
- data/lib/rubocop/cop/style/not.rb +2 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
- data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
- data/lib/rubocop/cop/style/one_line_conditional.rb +21 -12
- data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +14 -3
- data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
- 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 +3 -2
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- 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_begin.rb +37 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +6 -3
- data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
- data/lib/rubocop/cop/style/redundant_each.rb +3 -3
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +27 -5
- data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
- data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +36 -30
- data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/redundant_return.rb +3 -1
- data/lib/rubocop/cop/style/redundant_self.rb +2 -2
- 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_struct_keyword_init.rb +114 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +31 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
- data/lib/rubocop/cop/style/reverse_find.rb +51 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +25 -8
- 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 +51 -21
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +41 -8
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +12 -3
- data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
- data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
- data/lib/rubocop/cop/style/super_arguments.rb +2 -2
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +7 -6
- data/lib/rubocop/cop/style/tally_method.rb +181 -0
- data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
- 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 -0
- data/lib/rubocop/cop/style/word_array.rb +1 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
- 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/team.rb +87 -36
- data/lib/rubocop/cop/util.rb +2 -3
- data/lib/rubocop/cop/utils/format_string.rb +10 -0
- data/lib/rubocop/cop/variable_force/branch.rb +30 -6
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +9 -7
- data/lib/rubocop/cops_documentation_generator.rb +4 -4
- data/lib/rubocop/directive_comment.rb +48 -4
- 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 +38 -14
- data/lib/rubocop/formatter/formatter_set.rb +2 -2
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
- data/lib/rubocop/formatter/tap_formatter.rb +5 -2
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +22 -21
- data/lib/rubocop/lsp/diagnostic.rb +18 -33
- data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
- data/lib/rubocop/lsp/routes.rb +43 -7
- data/lib/rubocop/lsp/runtime.rb +13 -4
- data/lib/rubocop/lsp/stdin_runner.rb +8 -17
- data/lib/rubocop/magic_comment.rb +20 -0
- data/lib/rubocop/mcp/server.rb +200 -0
- data/lib/rubocop/options.rb +35 -4
- data/lib/rubocop/path_util.rb +14 -2
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/project_index_loader.rb +66 -0
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +10 -8
- data/lib/rubocop/result_cache.rb +61 -38
- data/lib/rubocop/rspec/cop_helper.rb +8 -0
- data/lib/rubocop/rspec/shared_contexts.rb +39 -5
- data/lib/rubocop/rspec/support.rb +2 -1
- data/lib/rubocop/runner.rb +134 -57
- data/lib/rubocop/server/cache.rb +6 -29
- data/lib/rubocop/server/core.rb +8 -0
- data/lib/rubocop/target_finder.rb +17 -10
- data/lib/rubocop/target_ruby.rb +31 -14
- data/lib/rubocop/version.rb +21 -3
- data/lib/rubocop.rb +28 -96
- data/lib/ruby_lsp/rubocop/addon.rb +23 -8
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
- metadata +38 -9
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'mcp'
|
|
5
|
+
|
|
6
|
+
required_mcp_version = '0.6.0'
|
|
7
|
+
|
|
8
|
+
if Gem::Version.new(required_mcp_version) > Gem::Version.new(MCP::VERSION)
|
|
9
|
+
# While `mcp` is not a runtime dependency, users may have an outdated version installed.
|
|
10
|
+
warn <<~MESSAGE
|
|
11
|
+
Error: `mcp` gem version #{MCP::VERSION} was loaded, but `rubocop --mcp` requires #{required_mcp_version}.
|
|
12
|
+
- If you're using Bundler and don't yet have `gem 'mcp'` as a dependency, add it now.
|
|
13
|
+
- If you're using Bundler and already have `gem 'mcp'` as a dependency, update it to the most recent version.
|
|
14
|
+
- If you don't use Bundler, run `gem update mcp`.
|
|
15
|
+
MESSAGE
|
|
16
|
+
exit!
|
|
17
|
+
end
|
|
18
|
+
rescue LoadError => e
|
|
19
|
+
raise unless e.path == 'mcp'
|
|
20
|
+
|
|
21
|
+
warn <<~MESSAGE
|
|
22
|
+
Error: Unable to load `mcp` gem. Add `gem 'mcp', '~> 0.6'` to your Gemfile, or run `gem install mcp`.
|
|
23
|
+
MESSAGE
|
|
24
|
+
|
|
25
|
+
exit!
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
require_relative '../lsp'
|
|
29
|
+
require_relative '../lsp/runtime'
|
|
30
|
+
|
|
31
|
+
module RuboCop
|
|
32
|
+
module MCP
|
|
33
|
+
# RuboCop MCP Server.
|
|
34
|
+
# @api private
|
|
35
|
+
class Server
|
|
36
|
+
def initialize(config_store)
|
|
37
|
+
@config_store = config_store
|
|
38
|
+
@runtime = RuboCop::LSP::Runtime.new(@config_store)
|
|
39
|
+
@options = {}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def start
|
|
43
|
+
# No `protocol_version` is specified because draft feature by default can be used.
|
|
44
|
+
server = ::MCP::Server.new(
|
|
45
|
+
name: 'rubocop_mcp_server',
|
|
46
|
+
version: RuboCop::Version::STRING,
|
|
47
|
+
tools: [inspection_tool, autocorrection_tool]
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
::MCP::Server::Transports::StdioTransport.new(server).open
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def inspection_tool
|
|
56
|
+
build_tool(
|
|
57
|
+
name: 'rubocop_inspection',
|
|
58
|
+
description: 'Inspect Ruby code for offenses. ' \
|
|
59
|
+
'Provide `source_code` to check inline code or `path` to check files.',
|
|
60
|
+
title: "RuboCop's inspection",
|
|
61
|
+
destructive_hint: false,
|
|
62
|
+
idempotent_hint: true,
|
|
63
|
+
read_only_hint: true,
|
|
64
|
+
safety_required: false
|
|
65
|
+
) do |path, source_code|
|
|
66
|
+
run_inspection(path, source_code)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def autocorrection_tool
|
|
71
|
+
build_tool(
|
|
72
|
+
name: 'rubocop_autocorrection',
|
|
73
|
+
description: 'Autocorrect RuboCop offenses in Ruby code. ' \
|
|
74
|
+
'Provide `source_code` to correct inline code or `path` to correct files. ' \
|
|
75
|
+
'Set `safety` to false to include unsafe corrections.',
|
|
76
|
+
title: "RuboCop's autocorrection",
|
|
77
|
+
destructive_hint: true,
|
|
78
|
+
idempotent_hint: false,
|
|
79
|
+
read_only_hint: false,
|
|
80
|
+
safety_required: true
|
|
81
|
+
) do |path, source_code, safety|
|
|
82
|
+
run_autocorrection(path, source_code, safety)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def run_inspection(path, source_code)
|
|
87
|
+
if source_code
|
|
88
|
+
offenses = @runtime.offenses(path || 'example.rb', source_code, source_code.encoding)
|
|
89
|
+
offenses.to_json
|
|
90
|
+
else
|
|
91
|
+
process_files(path, filter_empty: true) do |file, source|
|
|
92
|
+
offenses = @runtime.offenses(file, source, source.encoding)
|
|
93
|
+
|
|
94
|
+
{ path: PathUtil.relative_path(file), offenses: offenses }
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def run_autocorrection(path, source_code, safety)
|
|
100
|
+
command = safety ? 'rubocop.formatAutocorrects' : 'rubocop.formatAutocorrectsAll'
|
|
101
|
+
|
|
102
|
+
if source_code
|
|
103
|
+
@runtime.format(path || 'example.rb', source_code, command: command).tap do |corrected|
|
|
104
|
+
write_file(path, corrected) if path
|
|
105
|
+
end
|
|
106
|
+
else
|
|
107
|
+
process_files(path) do |file, source|
|
|
108
|
+
@runtime.format(file, source, command: command).then do |corrected|
|
|
109
|
+
write_file(file, corrected)
|
|
110
|
+
|
|
111
|
+
{ path: PathUtil.relative_path(file), corrected: source != corrected }
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def process_files(path, filter_empty: false)
|
|
118
|
+
target_finder = RuboCop::TargetFinder.new(@config_store, @options)
|
|
119
|
+
target_files = target_finder.find(path ? [path] : [], :only_recognized_file_types)
|
|
120
|
+
all_files = target_files.map { |file| yield(file, read_file(file)) }
|
|
121
|
+
files = filter_empty ? all_files.reject { |f| f[:offenses]&.empty? } : all_files
|
|
122
|
+
|
|
123
|
+
{ files: files, summary: build_summary(target_files, all_files) }.to_json
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def read_file(file)
|
|
127
|
+
config = @config_store.for_file(file)
|
|
128
|
+
RuboCop::ProcessedSource.from_file(
|
|
129
|
+
file, config.target_ruby_version, parser_engine: config.parser_engine
|
|
130
|
+
).raw_source
|
|
131
|
+
rescue Errno::ENOENT
|
|
132
|
+
raise RuboCop::Error, "No such file or directory: #{file}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def write_file(file, content)
|
|
136
|
+
File.write(file, content)
|
|
137
|
+
rescue Errno::EACCES
|
|
138
|
+
raise RuboCop::Error, "Permission denied: #{file}"
|
|
139
|
+
rescue Errno::ENOSPC
|
|
140
|
+
raise RuboCop::Error, "No space left on device: #{file}"
|
|
141
|
+
rescue Errno::EROFS
|
|
142
|
+
raise RuboCop::Error, "Read-only file system: #{file}"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# NOTE: It is useful for RuboCop's result summary to be shown in the LLM's responses
|
|
146
|
+
# during interactions, so the summary is returned in a form that is easy for the LLM
|
|
147
|
+
# to reason about. Since LLM execution is non-deterministic, it is also sensible to
|
|
148
|
+
# compute the summary deterministically at this stage.
|
|
149
|
+
def build_summary(target_files, files)
|
|
150
|
+
summary = { target_file_count: target_files.count }
|
|
151
|
+
if files.first&.key?(:offenses)
|
|
152
|
+
summary[:offense_count] = files.sum { |f| f[:offenses].size }
|
|
153
|
+
else
|
|
154
|
+
summary[:corrected_file_count] = files.count { |f| f[:corrected] }
|
|
155
|
+
end
|
|
156
|
+
summary
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
|
|
160
|
+
def build_tool(
|
|
161
|
+
name:, description:,
|
|
162
|
+
title:, destructive_hint:, idempotent_hint:, read_only_hint:, safety_required:
|
|
163
|
+
)
|
|
164
|
+
if safety_required
|
|
165
|
+
safety_property = { safety: { type: 'boolean' } }
|
|
166
|
+
required = ['safety']
|
|
167
|
+
else
|
|
168
|
+
safety_property = {}
|
|
169
|
+
required = nil
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
::MCP::Tool.define(
|
|
173
|
+
name: name,
|
|
174
|
+
description: description,
|
|
175
|
+
input_schema: {
|
|
176
|
+
properties: {
|
|
177
|
+
path: { type: 'string' },
|
|
178
|
+
source_code: { type: 'string' }
|
|
179
|
+
}.merge(safety_property),
|
|
180
|
+
required: required
|
|
181
|
+
}.compact,
|
|
182
|
+
annotations: {
|
|
183
|
+
title: title,
|
|
184
|
+
destructive_hint: destructive_hint,
|
|
185
|
+
idempotent_hint: idempotent_hint,
|
|
186
|
+
open_world_hint: false,
|
|
187
|
+
read_only_hint: read_only_hint
|
|
188
|
+
}
|
|
189
|
+
) do |path: nil, source_code: nil, safety: true|
|
|
190
|
+
result = yield(path, source_code, safety)
|
|
191
|
+
|
|
192
|
+
::MCP::Tool::Response.new([{ type: 'text', text: result }])
|
|
193
|
+
rescue RuboCop::Error => e
|
|
194
|
+
::MCP::Tool::Response.new([{ type: 'text', text: e.message }], error: true)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
# rubocop:enable Metrics/MethodLength, Metrics/ParameterLists
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
data/lib/rubocop/options.rb
CHANGED
|
@@ -16,7 +16,9 @@ module RuboCop
|
|
|
16
16
|
'root of the project. RuboCop will use this path to determine which ' \
|
|
17
17
|
'cops are enabled (via eg. Include/Exclude), and so that certain cops ' \
|
|
18
18
|
'like Naming/FileName can be checked.'
|
|
19
|
-
EXITING_OPTIONS = %i[
|
|
19
|
+
EXITING_OPTIONS = %i[
|
|
20
|
+
version verbose_version show_cops list_enabled_cops_for show_docs_url lsp mcp
|
|
21
|
+
].freeze
|
|
20
22
|
DEFAULT_MAXIMUM_EXCLUSION_ITEMS = 15
|
|
21
23
|
|
|
22
24
|
def initialize
|
|
@@ -57,6 +59,7 @@ module RuboCop
|
|
|
57
59
|
add_check_options(opts)
|
|
58
60
|
add_cache_options(opts)
|
|
59
61
|
add_lsp_option(opts)
|
|
62
|
+
add_mcp_option(opts)
|
|
60
63
|
add_server_options(opts)
|
|
61
64
|
add_output_options(opts)
|
|
62
65
|
add_autocorrection_options(opts)
|
|
@@ -88,6 +91,8 @@ module RuboCop
|
|
|
88
91
|
option(opts, '-F', '--fail-fast')
|
|
89
92
|
option(opts, '--disable-pending-cops')
|
|
90
93
|
option(opts, '--enable-pending-cops')
|
|
94
|
+
option(opts, '--disable-all-cops')
|
|
95
|
+
option(opts, '--enable-all-cops')
|
|
91
96
|
option(opts, '--ignore-disable-comments')
|
|
92
97
|
option(opts, '--force-exclusion')
|
|
93
98
|
option(opts, '--only-recognized-file-types')
|
|
@@ -215,6 +220,12 @@ module RuboCop
|
|
|
215
220
|
end
|
|
216
221
|
end
|
|
217
222
|
|
|
223
|
+
def add_mcp_option(opts)
|
|
224
|
+
section(opts, 'MCP Option') do
|
|
225
|
+
option(opts, '--mcp')
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
218
229
|
def add_server_options(opts)
|
|
219
230
|
section(opts, 'Server Options') do
|
|
220
231
|
option(opts, '--[no-]server')
|
|
@@ -229,6 +240,7 @@ module RuboCop
|
|
|
229
240
|
def add_additional_modes(opts)
|
|
230
241
|
section(opts, 'Additional Modes') do
|
|
231
242
|
option(opts, '-L', '--list-target-files')
|
|
243
|
+
option(opts, '--list-enabled-cops-for PATH')
|
|
232
244
|
option(opts, '--show-cops [COP1,COP2,...]') do |list|
|
|
233
245
|
@options[:show_cops] = list.nil? ? [] : list.split(',')
|
|
234
246
|
end
|
|
@@ -386,6 +398,7 @@ module RuboCop
|
|
|
386
398
|
validate_display_only_failed_and_display_only_correctable
|
|
387
399
|
validate_display_only_correctable_and_autocorrect
|
|
388
400
|
validate_lsp_and_editor_mode
|
|
401
|
+
validate_enable_all_cops_and_disable_all_cops
|
|
389
402
|
disable_parallel_when_invalid_option_combo
|
|
390
403
|
|
|
391
404
|
return if incompatible_options.size <= 1
|
|
@@ -439,6 +452,13 @@ module RuboCop
|
|
|
439
452
|
raise OptionArgumentError, 'Do not specify `--editor-mode` as it is redundant in `--lsp`.'
|
|
440
453
|
end
|
|
441
454
|
|
|
455
|
+
def validate_enable_all_cops_and_disable_all_cops
|
|
456
|
+
return if !@options.key?(:enable_all_cops) || !@options.key?(:disable_all_cops)
|
|
457
|
+
|
|
458
|
+
raise OptionArgumentError,
|
|
459
|
+
'--enable-all-cops cannot be used together with --disable-all-cops.'
|
|
460
|
+
end
|
|
461
|
+
|
|
442
462
|
def validate_autocorrect
|
|
443
463
|
if @options.key?(:safe_autocorrect) && @options.key?(:autocorrect_all)
|
|
444
464
|
message = Rainbow(<<~MESSAGE).red
|
|
@@ -467,8 +487,7 @@ module RuboCop
|
|
|
467
487
|
end
|
|
468
488
|
|
|
469
489
|
def invalid_arguments_for_parallel
|
|
470
|
-
[('
|
|
471
|
-
('-F/--fail-fast' if @options.key?(:fail_fast)),
|
|
490
|
+
[('-F/--fail-fast' if @options.key?(:fail_fast)),
|
|
472
491
|
('--profile' if @options[:profile]),
|
|
473
492
|
('--memory' if @options[:memory]),
|
|
474
493
|
('--cache false' if @options > { cache: 'false' })].compact
|
|
@@ -592,7 +611,7 @@ module RuboCop
|
|
|
592
611
|
display_only_correctable: ['Only output correctable offense messages.'],
|
|
593
612
|
display_only_safe_correctable: ['Only output safe-correctable offense messages',
|
|
594
613
|
'when combined with --display-only-correctable.'],
|
|
595
|
-
show_cops: ['
|
|
614
|
+
show_cops: ['Show the given cops, or all cops by',
|
|
596
615
|
'default, and their configurations for the',
|
|
597
616
|
'current directory.',
|
|
598
617
|
'You can use `*` as a wildcard.'],
|
|
@@ -612,8 +631,16 @@ module RuboCop
|
|
|
612
631
|
display_cop_names: ['Display cop names in offense messages.',
|
|
613
632
|
'Default is true.'],
|
|
614
633
|
disable_pending_cops: 'Run without pending cops.',
|
|
634
|
+
disable_all_cops: ['Run with all cops disabled by default,',
|
|
635
|
+
'except `Lint/Syntax`. Overrides',
|
|
636
|
+
'`AllCops/EnabledByDefault` and',
|
|
637
|
+
'`AllCops/DisabledByDefault` in config files.'],
|
|
615
638
|
display_style_guide: 'Display style guide URLs in offense messages.',
|
|
616
639
|
enable_pending_cops: 'Run with pending cops.',
|
|
640
|
+
enable_all_cops: ['Run with all cops enabled, including those',
|
|
641
|
+
'disabled by default. Overrides',
|
|
642
|
+
'`AllCops/EnabledByDefault` and',
|
|
643
|
+
'`AllCops/DisabledByDefault` in config files.'],
|
|
617
644
|
extra_details: 'Display extra details in offense messages.',
|
|
618
645
|
lint: 'Run only lint cops.',
|
|
619
646
|
safe: 'Run only safe cops.',
|
|
@@ -621,6 +648,8 @@ module RuboCop
|
|
|
621
648
|
'autocorrected source. This is especially useful',
|
|
622
649
|
'when combined with --autocorrect and --stdin.'],
|
|
623
650
|
list_target_files: 'List all files RuboCop will inspect.',
|
|
651
|
+
list_enabled_cops_for: ['List which cops will inspect a given file or',
|
|
652
|
+
'directory.'],
|
|
624
653
|
autocorrect: 'Autocorrect offenses (only when it\'s safe).',
|
|
625
654
|
auto_correct: '(same, deprecated)',
|
|
626
655
|
safe_auto_correct: '(same, deprecated)',
|
|
@@ -651,6 +680,8 @@ module RuboCop
|
|
|
651
680
|
server_status: 'Show server status.',
|
|
652
681
|
no_detach: 'Run the server process in the foreground.',
|
|
653
682
|
lsp: 'Start a language server listening on STDIN.',
|
|
683
|
+
mcp: ['Start an MCP (Model Context Protocol) server that',
|
|
684
|
+
'communicates over stdio.'],
|
|
654
685
|
raise_cop_error: ['Raise cop-related errors with cause and location.',
|
|
655
686
|
'This is used to prevent cops from failing silently.',
|
|
656
687
|
'Default is false.'],
|
data/lib/rubocop/path_util.rb
CHANGED
|
@@ -10,7 +10,19 @@ module RuboCop
|
|
|
10
10
|
|
|
11
11
|
module_function
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
# Returns the current working directory, cached for the duration of a run.
|
|
14
|
+
# Dir.pwd is a syscall; caching it avoids repeated overhead since RuboCop
|
|
15
|
+
# never changes the working directory during a run.
|
|
16
|
+
def pwd
|
|
17
|
+
@pwd ||= Dir.pwd
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Reset the cached pwd. Only needed in tests that use Dir.chdir.
|
|
21
|
+
def reset_pwd
|
|
22
|
+
@pwd = nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def relative_path(path, base_dir = PathUtil.pwd)
|
|
14
26
|
PathUtil.relative_paths_cache[base_dir][path] ||=
|
|
15
27
|
# Optimization for the common case where path begins with the base
|
|
16
28
|
# dir. Just cut off the first part.
|
|
@@ -41,7 +53,7 @@ module RuboCop
|
|
|
41
53
|
path.uri.to_s
|
|
42
54
|
else
|
|
43
55
|
# Ideally, we calculate this relative to the project root.
|
|
44
|
-
base_dir =
|
|
56
|
+
base_dir = PathUtil.pwd
|
|
45
57
|
|
|
46
58
|
if path.start_with? base_dir
|
|
47
59
|
relative_path(path, base_dir)
|
|
@@ -84,7 +84,7 @@ module RuboCop
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def require_plugin(require_path)
|
|
87
|
-
FeatureLoader.load(config_directory_path:
|
|
87
|
+
FeatureLoader.load(config_directory_path: PathUtil.pwd, feature: require_path)
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
def constantize_plugin_from_gemspec_metadata(plugin_name)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
# Defensive loader for the optional `rubydex` gem.
|
|
5
|
+
#
|
|
6
|
+
# When `AllCops/UseProjectIndex` is enabled in the user's configuration, RuboCop builds
|
|
7
|
+
# a project-wide index using `Rubydex::Graph` and exposes it to cops that opt in.
|
|
8
|
+
# The gem is intentionally not a runtime dependency; if it is not installed,
|
|
9
|
+
# or if the running Ruby is older than what `rubydex` supports, RuboCop falls back to
|
|
10
|
+
# its standard file-local behavior.
|
|
11
|
+
module ProjectIndexLoader
|
|
12
|
+
MINIMUM_RUBY_VERSION = '3.2'
|
|
13
|
+
|
|
14
|
+
module_function
|
|
15
|
+
|
|
16
|
+
# Returns whether the `rubydex` gem can be loaded. The result is memoized
|
|
17
|
+
# for the lifetime of the process.
|
|
18
|
+
def available?
|
|
19
|
+
return @available if defined?(@available)
|
|
20
|
+
|
|
21
|
+
@available = supported_ruby? && try_require
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def supported_ruby?
|
|
25
|
+
RUBY_VERSION >= MINIMUM_RUBY_VERSION
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def warn_unavailable
|
|
29
|
+
return if @warned
|
|
30
|
+
|
|
31
|
+
@warned = true
|
|
32
|
+
|
|
33
|
+
if supported_ruby?
|
|
34
|
+
warn Rainbow(<<~MSG).yellow
|
|
35
|
+
`AllCops/UseProjectIndex` is enabled but the `rubydex` gem is not installed.
|
|
36
|
+
Analyses that use the project index will be skipped. Add `gem 'rubydex'` to your Gemfile.
|
|
37
|
+
MSG
|
|
38
|
+
else
|
|
39
|
+
warn Rainbow(<<~MSG).yellow
|
|
40
|
+
`AllCops/UseProjectIndex` is enabled but `rubydex` requires Ruby #{MINIMUM_RUBY_VERSION} or later (current: #{RUBY_VERSION}).
|
|
41
|
+
Analyses that use the project index will be skipped.
|
|
42
|
+
MSG
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def try_require
|
|
47
|
+
require 'rubydex'
|
|
48
|
+
true
|
|
49
|
+
rescue LoadError
|
|
50
|
+
false
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Builds and resolves a `Rubydex::Graph` for the given file paths. Returns the resolved graph,
|
|
54
|
+
# or `nil` if the build fails. This is the only place in RuboCop that depends on the concrete
|
|
55
|
+
# `Rubydex::Graph` API, so callers (e.g. `Runner`) do not need to know which Rubydex classes
|
|
56
|
+
# or methods are involved.
|
|
57
|
+
def build_index(paths)
|
|
58
|
+
graph = Rubydex::Graph.new
|
|
59
|
+
graph.index_all(paths.map(&:to_s))
|
|
60
|
+
graph.resolve
|
|
61
|
+
graph
|
|
62
|
+
rescue StandardError => e
|
|
63
|
+
warn Rainbow("rubydex index build failed: #{e.message}. Continuing without it.").yellow
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/lib/rubocop/rake_task.rb
CHANGED
|
@@ -75,7 +75,7 @@ module RuboCop
|
|
|
75
75
|
def setup_subtasks(name, *args, &task_block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
76
76
|
namespace(name) do
|
|
77
77
|
# rubocop:todo Naming/InclusiveLanguage
|
|
78
|
-
task(:auto_correct, *args) do
|
|
78
|
+
task(:auto_correct, *args) do |_, task_args|
|
|
79
79
|
require 'rainbow'
|
|
80
80
|
warn Rainbow(
|
|
81
81
|
'rubocop:auto_correct task is deprecated; ' \
|
|
@@ -11,13 +11,13 @@ module RuboCop
|
|
|
11
11
|
|
|
12
12
|
CACHE_LIFETIME = 24 * 60 * 60
|
|
13
13
|
|
|
14
|
-
def initialize(url,
|
|
14
|
+
def initialize(url, cache_root)
|
|
15
15
|
begin
|
|
16
16
|
@uri = URI.parse(url)
|
|
17
17
|
rescue URI::InvalidURIError
|
|
18
18
|
raise ConfigNotFoundError, "Failed to resolve configuration: '#{url}' is not a valid URI"
|
|
19
19
|
end
|
|
20
|
-
@
|
|
20
|
+
@cache_root = cache_root
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def file
|
|
@@ -27,16 +27,17 @@ module RuboCop
|
|
|
27
27
|
next if response.is_a?(Net::HTTPNotModified)
|
|
28
28
|
next if response.is_a?(SocketError)
|
|
29
29
|
|
|
30
|
+
FileUtils.mkdir_p(File.dirname(cache_path))
|
|
30
31
|
File.write(cache_path, response.body)
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
cache_path
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
def inherit_from_remote(file
|
|
37
|
+
def inherit_from_remote(file)
|
|
37
38
|
new_uri = @uri.dup
|
|
38
39
|
new_uri.path.gsub!(%r{/[^/]*$}, "/#{file.delete_prefix('./')}")
|
|
39
|
-
RemoteConfig.new(new_uri.to_s,
|
|
40
|
+
RemoteConfig.new(new_uri.to_s, @cache_root)
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
private
|
|
@@ -80,7 +81,7 @@ module RuboCop
|
|
|
80
81
|
end
|
|
81
82
|
|
|
82
83
|
def cache_path
|
|
83
|
-
File.expand_path(
|
|
84
|
+
@cache_path ||= File.expand_path(cache_name_from_uri, @cache_root)
|
|
84
85
|
end
|
|
85
86
|
|
|
86
87
|
def cache_path_exists?
|
|
@@ -97,9 +98,10 @@ module RuboCop
|
|
|
97
98
|
end
|
|
98
99
|
|
|
99
100
|
def cache_name_from_uri
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
uri.
|
|
101
|
+
# The md5 checksum suffix is 37 bytes, so we play it save and
|
|
102
|
+
# allow 254 bytes total - this should be safe on Linux/macOS/Windows
|
|
103
|
+
filename = File.basename(@uri.path).gsub(/\.ya?ml\z/i, '').byteslice(0, 217).scrub('')
|
|
104
|
+
"#{filename}-#{Digest::MD5.hexdigest(@uri.to_s)}.yml"
|
|
103
105
|
end
|
|
104
106
|
|
|
105
107
|
def cloned_url
|