rubocop 1.79.2 → 1.87.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 +185 -20
- data/config/obsoletion.yml +9 -0
- data/exe/rubocop +1 -8
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +30 -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 +8 -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/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/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_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -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 -2
- data/lib/rubocop/cop/lint/deprecated_constants.rb +1 -1
- 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 +1 -1
- 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/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
- data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -9
- 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 +4 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +4 -2
- data/lib/rubocop/cop/lint/number_conversion.rb +6 -6
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +2 -11
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +23 -6
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +3 -3
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +3 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -0
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
- data/lib/rubocop/cop/lint/self_assignment.rb +15 -6
- 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/struct_new_override.rb +17 -1
- data/lib/rubocop/cop/lint/syntax.rb +25 -1
- data/lib/rubocop/cop/lint/to_json.rb +12 -16
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -0
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -1
- 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 +48 -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 +1 -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/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 +14 -2
- data/lib/rubocop/cop/style/and_or.rb +1 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
- data/lib/rubocop/cop/style/array_intersect.rb +46 -12
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -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 +27 -34
- data/lib/rubocop/cop/style/case_equality.rb +15 -13
- 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/collection_compact.rb +36 -16
- data/lib/rubocop/cop/style/colon_method_call.rb +3 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +2 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +8 -18
- data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
- data/lib/rubocop/cop/style/copyright.rb +22 -11
- data/lib/rubocop/cop/style/date_time.rb +2 -2
- 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/file_open.rb +84 -0
- data/lib/rubocop/cop/style/file_write.rb +18 -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_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 +57 -17
- 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 +1 -1
- 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 +6 -2
- 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 +26 -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 +25 -7
- 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_modifier.rb +16 -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/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 +24 -7
- 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 +2 -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
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
|
data/lib/rubocop/result_cache.rb
CHANGED
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
|
9
9
|
# Provides functionality for caching RuboCop runs.
|
|
10
10
|
# @api private
|
|
11
11
|
class ResultCache
|
|
12
|
-
NON_CHANGING = %i[color format formatters out debug fail_level
|
|
12
|
+
NON_CHANGING = %i[color format formatters out debug display_time fail_level
|
|
13
13
|
fix_layout autocorrect safe_autocorrect autocorrect_all
|
|
14
14
|
cache fail_fast stdin parallel].freeze
|
|
15
15
|
|
|
@@ -22,19 +22,22 @@ module RuboCop
|
|
|
22
22
|
# Remove old files so that the cache doesn't grow too big. When the
|
|
23
23
|
# threshold MaxFilesInCache has been exceeded, the oldest 50% of all the
|
|
24
24
|
# files in the cache are removed. The reason for removing so much is that
|
|
25
|
-
#
|
|
25
|
+
# removing should be done relatively seldom, since there is a slight risk
|
|
26
26
|
# that some other RuboCop process was just about to read the file, when
|
|
27
27
|
# there's parallel execution and the cache is shared.
|
|
28
28
|
def self.cleanup(config_store, verbose, cache_root_override = nil)
|
|
29
29
|
return if inhibit_cleanup # OPTIMIZE: For faster testing
|
|
30
|
+
return unless config_store.for_pwd.for_all_cops['MaxFilesInCache']
|
|
30
31
|
|
|
31
32
|
rubocop_cache_dir = cache_root(config_store, cache_root_override)
|
|
32
33
|
return unless File.exist?(rubocop_cache_dir)
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
# We know the cache entries are 3 level deep, so globing
|
|
36
|
+
# for `*/*/*` only returns files.
|
|
37
|
+
files = Dir[File.join(rubocop_cache_dir, '*/*/*')]
|
|
35
38
|
return unless requires_file_removal?(files.length, config_store)
|
|
36
39
|
|
|
37
|
-
remove_oldest_files(files,
|
|
40
|
+
remove_oldest_files(files, rubocop_cache_dir, verbose)
|
|
38
41
|
end
|
|
39
42
|
|
|
40
43
|
class << self
|
|
@@ -49,39 +52,57 @@ module RuboCop
|
|
|
49
52
|
file_count > 1 && file_count > config_store.for_pwd.for_all_cops['MaxFilesInCache']
|
|
50
53
|
end
|
|
51
54
|
|
|
52
|
-
def remove_oldest_files(files,
|
|
55
|
+
def remove_oldest_files(files, rubocop_cache_dir, verbose)
|
|
53
56
|
# Add 1 to half the number of files, so that we remove the file if
|
|
54
57
|
# there's only 1 left.
|
|
55
58
|
remove_count = (files.length / 2) + 1
|
|
56
59
|
puts "Removing the #{remove_count} oldest files from #{rubocop_cache_dir}" if verbose
|
|
57
60
|
sorted = files.sort_by { |path| File.mtime(path) }
|
|
58
|
-
remove_files(sorted,
|
|
61
|
+
remove_files(sorted, remove_count)
|
|
59
62
|
rescue Errno::ENOENT
|
|
60
63
|
# This can happen if parallel RuboCop invocations try to remove the
|
|
61
64
|
# same files. No problem.
|
|
62
65
|
puts $ERROR_INFO if verbose
|
|
63
66
|
end
|
|
64
67
|
|
|
65
|
-
def remove_files(files,
|
|
68
|
+
def remove_files(files, remove_count)
|
|
66
69
|
# Batch file deletions, deleting over 130,000+ files will crash
|
|
67
70
|
# File.delete.
|
|
68
71
|
files[0, remove_count].each_slice(10_000).each do |files_slice|
|
|
69
72
|
File.delete(*files_slice)
|
|
70
73
|
end
|
|
71
|
-
|
|
74
|
+
|
|
75
|
+
dirs = files.map { |f| File.dirname(f) }.uniq
|
|
76
|
+
until dirs.empty?
|
|
77
|
+
dirs.select! do |dir|
|
|
78
|
+
Dir.rmdir(dir)
|
|
79
|
+
true
|
|
80
|
+
rescue SystemCallError # ENOTEMPTY etc
|
|
81
|
+
false
|
|
82
|
+
end
|
|
83
|
+
dirs = dirs.map { |f| File.dirname(f) }.uniq
|
|
84
|
+
end
|
|
72
85
|
end
|
|
73
86
|
end
|
|
74
87
|
|
|
75
88
|
def self.cache_root(config_store, cache_root_override = nil)
|
|
76
|
-
|
|
89
|
+
return @cache_root if @cache_root && !cache_root_override
|
|
90
|
+
|
|
91
|
+
result = CacheConfig.root_dir do
|
|
77
92
|
cache_root_override || config_store.for_pwd.for_all_cops['CacheRootDirectory']
|
|
78
93
|
end
|
|
94
|
+
@cache_root = result unless cache_root_override
|
|
95
|
+
result
|
|
79
96
|
end
|
|
80
97
|
|
|
81
98
|
def self.allow_symlinks_in_cache_location?(config_store)
|
|
82
99
|
config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
|
|
83
100
|
end
|
|
84
101
|
|
|
102
|
+
def self.reset_config_cache
|
|
103
|
+
@cache_root = nil
|
|
104
|
+
end
|
|
105
|
+
|
|
85
106
|
attr_reader :path
|
|
86
107
|
|
|
87
108
|
def initialize(file, team, options, config_store, cache_root_override = nil)
|
|
@@ -90,7 +111,7 @@ module RuboCop
|
|
|
90
111
|
@allow_symlinks_in_cache_location =
|
|
91
112
|
ResultCache.allow_symlinks_in_cache_location?(config_store)
|
|
92
113
|
@path = File.join(rubocop_cache_dir,
|
|
93
|
-
|
|
114
|
+
self.class.source_checksum,
|
|
94
115
|
context_checksum(team, options),
|
|
95
116
|
file_checksum(file, config_store))
|
|
96
117
|
@cached_data = CachedData.new(file)
|
|
@@ -167,13 +188,11 @@ module RuboCop
|
|
|
167
188
|
end
|
|
168
189
|
|
|
169
190
|
class << self
|
|
170
|
-
attr_accessor :
|
|
171
|
-
end
|
|
191
|
+
attr_accessor :inhibit_cleanup
|
|
172
192
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
begin
|
|
193
|
+
# The checksum of the RuboCop program running the inspection.
|
|
194
|
+
def source_checksum
|
|
195
|
+
@source_checksum ||= begin
|
|
177
196
|
digest = Digest::SHA1.new
|
|
178
197
|
rubocop_extra_features
|
|
179
198
|
.select { |path| File.file?(path) }
|
|
@@ -184,21 +203,33 @@ module RuboCop
|
|
|
184
203
|
digest << RuboCop::Version::STRING << RuboCop::AST::Version::STRING
|
|
185
204
|
digest.hexdigest
|
|
186
205
|
end
|
|
187
|
-
|
|
206
|
+
end
|
|
188
207
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
208
|
+
# Return a hash of the options given at invocation, minus the ones that have
|
|
209
|
+
# no effect on which offenses and disabled line ranges are found, and thus
|
|
210
|
+
# don't affect caching.
|
|
211
|
+
def relevant_options_digest(options)
|
|
212
|
+
@relevant_options_digest ||= {}
|
|
213
|
+
@relevant_options_digest[options] ||= begin
|
|
214
|
+
options = options.reject { |key, _| NON_CHANGING.include?(key) }
|
|
215
|
+
options.to_s.gsub(/[^a-z]+/i, '_')
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
private
|
|
199
220
|
|
|
200
|
-
|
|
201
|
-
|
|
221
|
+
def digest(path)
|
|
222
|
+
content = if path.end_with?(*DL_EXTENSIONS)
|
|
223
|
+
# Shared libraries often contain timestamps of when
|
|
224
|
+
# they were compiled and other non-stable data.
|
|
225
|
+
File.basename(path)
|
|
226
|
+
else
|
|
227
|
+
File.binread(path) # mtime not reliable
|
|
228
|
+
end
|
|
229
|
+
Zlib.crc32(content).to_s
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def rubocop_extra_features
|
|
202
233
|
lib_root = File.join(File.dirname(__FILE__), '..')
|
|
203
234
|
exe_root = File.join(lib_root, '..', 'exe')
|
|
204
235
|
|
|
@@ -216,20 +247,12 @@ module RuboCop
|
|
|
216
247
|
end
|
|
217
248
|
end
|
|
218
249
|
|
|
219
|
-
# Return a hash of the options given at invocation, minus the ones that have
|
|
220
|
-
# no effect on which offenses and disabled line ranges are found, and thus
|
|
221
|
-
# don't affect caching.
|
|
222
|
-
def relevant_options_digest(options)
|
|
223
|
-
options = options.reject { |key, _| NON_CHANGING.include?(key) }
|
|
224
|
-
options.to_s.gsub(/[^a-z]+/i, '_')
|
|
225
|
-
end
|
|
226
|
-
|
|
227
250
|
# We combine team and options into a single "context" checksum to avoid
|
|
228
251
|
# making file names that are too long for some filesystems to handle.
|
|
229
252
|
# This context is for anything that's not (1) the RuboCop executable
|
|
230
253
|
# checksum or (2) the inspected file checksum.
|
|
231
254
|
def context_checksum(team, options)
|
|
232
|
-
keys = [team.external_dependency_checksum, relevant_options_digest(options)]
|
|
255
|
+
keys = [team.external_dependency_checksum, self.class.relevant_options_digest(options)]
|
|
233
256
|
Digest::SHA1.hexdigest(keys.join)
|
|
234
257
|
end
|
|
235
258
|
end
|
|
@@ -6,6 +6,12 @@ require 'tempfile'
|
|
|
6
6
|
module CopHelper
|
|
7
7
|
extend RSpec::SharedContext
|
|
8
8
|
|
|
9
|
+
@integrated_plugins = false
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
attr_accessor :integrated_plugins
|
|
13
|
+
end
|
|
14
|
+
|
|
9
15
|
let(:ruby_version) do
|
|
10
16
|
# The minimum version Prism can parse is 3.3.
|
|
11
17
|
ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : RuboCop::TargetRuby::DEFAULT_VERSION
|
|
@@ -18,11 +24,13 @@ module CopHelper
|
|
|
18
24
|
|
|
19
25
|
before(:all) do
|
|
20
26
|
next if ENV['RUBOCOP_CORE_DEVELOPMENT']
|
|
27
|
+
next if CopHelper.integrated_plugins
|
|
21
28
|
|
|
22
29
|
plugins = Gem.loaded_specs.filter_map do |feature_name, feature_specification|
|
|
23
30
|
feature_name if feature_specification.metadata['default_lint_roller_plugin']
|
|
24
31
|
end
|
|
25
32
|
RuboCop::Plugin.integrate_plugins(RuboCop::Config.new, plugins)
|
|
33
|
+
CopHelper.integrated_plugins = true
|
|
26
34
|
end
|
|
27
35
|
|
|
28
36
|
def inspect_source(source, file = nil)
|
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
require 'tmpdir'
|
|
4
4
|
|
|
5
|
+
# Reset cached PathUtil.pwd before each example so that tests using Dir.chdir
|
|
6
|
+
# or stubbing Dir.pwd get a fresh value.
|
|
7
|
+
RSpec.configure { |c| c.before { RuboCop::PathUtil.reset_pwd } }
|
|
8
|
+
|
|
5
9
|
RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLength
|
|
6
|
-
around do |example|
|
|
10
|
+
around do |example| # rubocop:disable Metrics/BlockLength
|
|
7
11
|
Dir.mktmpdir do |tmpdir|
|
|
8
12
|
original_home = Dir.home
|
|
9
13
|
original_xdg_config_home = ENV.fetch('XDG_CONFIG_HOME', nil)
|
|
@@ -26,12 +30,17 @@ RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLe
|
|
|
26
30
|
begin
|
|
27
31
|
FileUtils.mkdir_p(working_dir)
|
|
28
32
|
|
|
29
|
-
Dir.chdir(working_dir)
|
|
33
|
+
Dir.chdir(working_dir) do
|
|
34
|
+
RuboCop::PathUtil.reset_pwd
|
|
35
|
+
RuboCop::ResultCache.reset_config_cache
|
|
36
|
+
example.run
|
|
37
|
+
end
|
|
30
38
|
ensure
|
|
31
39
|
ENV['HOME'] = original_home
|
|
32
40
|
ENV['XDG_CONFIG_HOME'] = original_xdg_config_home
|
|
33
41
|
|
|
34
|
-
RuboCop::
|
|
42
|
+
RuboCop::ResultCache.reset_config_cache
|
|
43
|
+
RuboCop::ConfigLoader.clear_options # This also resets RuboCop::FileFinder.root_level
|
|
35
44
|
end
|
|
36
45
|
end
|
|
37
46
|
end
|
|
@@ -203,6 +212,27 @@ RSpec.shared_context 'lsp' do
|
|
|
203
212
|
end
|
|
204
213
|
end
|
|
205
214
|
|
|
215
|
+
RSpec.shared_context 'with exclude limit tracking' do
|
|
216
|
+
around do |example|
|
|
217
|
+
Dir.mktmpdir('rubocop-exclude-limit') do |dir|
|
|
218
|
+
RuboCop::ExcludeLimit.tmp_dir = Pathname.new(dir)
|
|
219
|
+
example.run
|
|
220
|
+
ensure
|
|
221
|
+
RuboCop::ExcludeLimit.tmp_dir = nil
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Reads exclude_limit values from the tmp files written by ExcludeLimit.
|
|
226
|
+
# Returns a hash like { 'Max' => 81 } or nil if no values were written.
|
|
227
|
+
def read_exclude_limit(cop, parameter_name = nil)
|
|
228
|
+
if parameter_name
|
|
229
|
+
read_exclude_limit(cop)[parameter_name]
|
|
230
|
+
else
|
|
231
|
+
RuboCop::ExcludeLimit.read_limits(cop.class.badge.to_s)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
206
236
|
RSpec.shared_context 'ruby 2.0' do
|
|
207
237
|
# Prism supports parsing Ruby 3.3+.
|
|
208
238
|
let(:ruby_version) { ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.3 : 2.0 }
|
|
@@ -266,6 +296,10 @@ RSpec.shared_context 'ruby 3.4' do
|
|
|
266
296
|
let(:ruby_version) { 3.4 }
|
|
267
297
|
end
|
|
268
298
|
|
|
269
|
-
RSpec.shared_context 'ruby
|
|
270
|
-
let(:ruby_version) {
|
|
299
|
+
RSpec.shared_context 'ruby 4.0' do
|
|
300
|
+
let(:ruby_version) { 4.0 }
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
RSpec.shared_context 'ruby 4.1' do
|
|
304
|
+
let(:ruby_version) { 4.1 }
|
|
271
305
|
end
|
|
@@ -30,5 +30,6 @@ RSpec.configure do |config|
|
|
|
30
30
|
config.include_context 'ruby 3.2', :ruby32
|
|
31
31
|
config.include_context 'ruby 3.3', :ruby33
|
|
32
32
|
config.include_context 'ruby 3.4', :ruby34
|
|
33
|
-
config.include_context 'ruby
|
|
33
|
+
config.include_context 'ruby 4.0', :ruby40
|
|
34
|
+
config.include_context 'ruby 4.1', :ruby41
|
|
34
35
|
end
|