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
data/lib/rubocop/cop/offense.rb
CHANGED
|
@@ -66,6 +66,13 @@ module RuboCop
|
|
|
66
66
|
alias_method :last_line, :line
|
|
67
67
|
alias_method :last_column, :column
|
|
68
68
|
|
|
69
|
+
attr_reader :source_buffer
|
|
70
|
+
|
|
71
|
+
def initialize(line, column, source_line, begin_pos, end_pos)
|
|
72
|
+
super
|
|
73
|
+
@source_buffer = Parser::Source::Buffer.new('(pseudo)', source: source_line)
|
|
74
|
+
end
|
|
75
|
+
|
|
69
76
|
def column_range
|
|
70
77
|
column...last_column
|
|
71
78
|
end
|
|
@@ -79,18 +86,45 @@ module RuboCop
|
|
|
79
86
|
|
|
80
87
|
NO_LOCATION = PseudoSourceRange.new(1, 0, '', 0, 0).freeze
|
|
81
88
|
|
|
89
|
+
# @api public
|
|
90
|
+
#
|
|
91
|
+
# @!attribute [r] justification
|
|
92
|
+
#
|
|
93
|
+
# @return [String, nil]
|
|
94
|
+
# the reason given on the directive that suppressed this offense
|
|
95
|
+
# (the text after `--`), or `nil` when the offense is not suppressed
|
|
96
|
+
# or the directive carries no reason
|
|
97
|
+
attr_reader :justification
|
|
98
|
+
|
|
82
99
|
# @api private
|
|
83
100
|
def initialize(severity, location, message, cop_name, # rubocop:disable Metrics/ParameterLists
|
|
84
|
-
status = :uncorrected, corrector = nil)
|
|
101
|
+
status = :uncorrected, corrector = nil, justification: nil)
|
|
85
102
|
@severity = RuboCop::Cop::Severity.new(severity)
|
|
86
103
|
@location = location
|
|
104
|
+
|
|
105
|
+
# Pre-compute the position eagerly because the offense is frozen and
|
|
106
|
+
# `location.line` / `location.column` are expensive to compute; sorting
|
|
107
|
+
# many offenses calls them repeatedly through `#<=>`.
|
|
108
|
+
@line = location.line
|
|
109
|
+
@column = location.column
|
|
87
110
|
@message = message.freeze
|
|
88
111
|
@cop_name = cop_name.freeze
|
|
89
112
|
@status = status
|
|
90
113
|
@corrector = corrector
|
|
114
|
+
@justification = justification.freeze
|
|
91
115
|
freeze
|
|
92
116
|
end
|
|
93
117
|
|
|
118
|
+
def marshal_dump
|
|
119
|
+
[@severity, @location, @message, @cop_name, @status, @justification]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def marshal_load(array)
|
|
123
|
+
@severity, @location, @message, @cop_name, @status, @justification = array
|
|
124
|
+
@line = @location.line
|
|
125
|
+
@column = @location.column
|
|
126
|
+
end
|
|
127
|
+
|
|
94
128
|
# @api public
|
|
95
129
|
#
|
|
96
130
|
# @!attribute [r] correctable?
|
|
@@ -98,8 +132,10 @@ module RuboCop
|
|
|
98
132
|
# @return [Boolean]
|
|
99
133
|
# whether this offense can be automatically corrected via autocorrect.
|
|
100
134
|
# This includes todo comments, for example when requested with `--disable-uncorrectable`.
|
|
135
|
+
# An offense suppressed by a directive comment is not correctable -
|
|
136
|
+
# autocorrect will not touch it.
|
|
101
137
|
def correctable?
|
|
102
|
-
@status != :unsupported
|
|
138
|
+
@status != :unsupported && @status != :disabled
|
|
103
139
|
end
|
|
104
140
|
|
|
105
141
|
# @api public
|
|
@@ -139,7 +175,8 @@ module RuboCop
|
|
|
139
175
|
# @return [Parser::Source::Range]
|
|
140
176
|
# the range of the code that is highlighted
|
|
141
177
|
def highlighted_area
|
|
142
|
-
Parser::Source::
|
|
178
|
+
source_buffer = Parser::Source::Buffer.new(location.source_buffer.name, source: source_line)
|
|
179
|
+
Parser::Source::Range.new(source_buffer, column, column + column_length)
|
|
143
180
|
end
|
|
144
181
|
|
|
145
182
|
# @api private
|
|
@@ -151,14 +188,10 @@ module RuboCop
|
|
|
151
188
|
end
|
|
152
189
|
|
|
153
190
|
# @api private
|
|
154
|
-
|
|
155
|
-
location.line
|
|
156
|
-
end
|
|
191
|
+
attr_reader :line
|
|
157
192
|
|
|
158
193
|
# @api private
|
|
159
|
-
|
|
160
|
-
location.column
|
|
161
|
-
end
|
|
194
|
+
attr_reader :column
|
|
162
195
|
|
|
163
196
|
# @api private
|
|
164
197
|
def source_line
|
|
@@ -203,6 +236,16 @@ module RuboCop
|
|
|
203
236
|
column + 1
|
|
204
237
|
end
|
|
205
238
|
|
|
239
|
+
# @api private
|
|
240
|
+
#
|
|
241
|
+
# The minimum value of `real_column` is 1, so the minimum value of
|
|
242
|
+
# `real_last_column` is also 1. A non-zero `last_column` is used as is,
|
|
243
|
+
# because the 0-based end-exclusive column is the same as the 1-based
|
|
244
|
+
# column of the last character.
|
|
245
|
+
def real_last_column
|
|
246
|
+
last_column.zero? ? 1 : last_column
|
|
247
|
+
end
|
|
248
|
+
|
|
206
249
|
# @api public
|
|
207
250
|
#
|
|
208
251
|
# @return [Boolean]
|
data/lib/rubocop/cop/registry.rb
CHANGED
|
@@ -16,15 +16,15 @@ module RuboCop
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# Registry that tracks all cops by their badge and department.
|
|
19
|
-
class Registry
|
|
19
|
+
class Registry # rubocop:disable Metrics/ClassLength
|
|
20
20
|
include Enumerable
|
|
21
21
|
|
|
22
22
|
def self.all
|
|
23
23
|
global.without_department(:Test).cops
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def self.qualified_cop_name(name, origin)
|
|
27
|
-
global.qualified_cop_name(name, origin)
|
|
26
|
+
def self.qualified_cop_name(name, origin, warn: true, correct_namespace: true)
|
|
27
|
+
global.qualified_cop_name(name, origin, warn: warn, correct_namespace: correct_namespace)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Changes momentarily the global registry
|
|
@@ -46,18 +46,41 @@ module RuboCop
|
|
|
46
46
|
global.qualify_badge(badge).first == badge
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
attr_reader :options
|
|
49
|
+
attr_reader :options, :warnings
|
|
50
50
|
|
|
51
51
|
def initialize(cops = [], options = {})
|
|
52
|
-
@
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
@departments = Set.new
|
|
53
|
+
# Maps each badge to its cop class, or to the fully qualified constant name (a `String`)
|
|
54
|
+
# when the cop is registered for lazy loading and its file is not loaded yet.
|
|
55
|
+
# A single insertion-ordered map keeps the registration order stable no matter when
|
|
56
|
+
# a lazy-loaded cop's file gets loaded, because reassigning an existing key preserves
|
|
57
|
+
# its position; the cop execution order depends on this order.
|
|
58
|
+
@cops_by_badge = {}
|
|
55
59
|
|
|
56
60
|
@enrollment_queue = cops
|
|
57
61
|
@options = options
|
|
58
62
|
|
|
59
63
|
@enabled_cache = {}.compare_by_identity
|
|
60
64
|
@disabled_cache = {}.compare_by_identity
|
|
65
|
+
@disabled_names_cache = {}.compare_by_identity
|
|
66
|
+
@warnings = {}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Registers a cop by its badge and constant name without loading the class.
|
|
70
|
+
# The constant is resolved (loading the cop's file through `autoload`) only
|
|
71
|
+
# when the cop class itself is needed.
|
|
72
|
+
#
|
|
73
|
+
# @param badge [Badge, String] the badge, or the qualified cop name
|
|
74
|
+
# @param constant_name [String] the fully qualified constant name
|
|
75
|
+
def lazy_load(badge, constant_name)
|
|
76
|
+
badge = Badge.parse(badge) if badge.is_a?(String)
|
|
77
|
+
|
|
78
|
+
# File any cops enlisted earlier first, so that the registration
|
|
79
|
+
# order follows the call order.
|
|
80
|
+
clear_enrollment_queue
|
|
81
|
+
|
|
82
|
+
@departments << badge.department
|
|
83
|
+
@cops_by_badge[badge] = constant_name unless @cops_by_badge[badge].is_a?(Class)
|
|
61
84
|
end
|
|
62
85
|
|
|
63
86
|
def enlist(cop)
|
|
@@ -65,28 +88,46 @@ module RuboCop
|
|
|
65
88
|
end
|
|
66
89
|
|
|
67
90
|
def dismiss(cop)
|
|
68
|
-
|
|
91
|
+
dismissed = !@enrollment_queue.delete(cop).nil?
|
|
92
|
+
|
|
93
|
+
# A lazy-loaded cop that was not enlisted yet is dismissed by removing its registration.
|
|
94
|
+
# Anonymous cop classes cannot have a badge.
|
|
95
|
+
if !cop.name.nil? && @cops_by_badge[cop.badge].is_a?(String)
|
|
96
|
+
@cops_by_badge.delete(cop.badge)
|
|
97
|
+
dismissed = true
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
raise "Cop #{cop} could not be dismissed" unless dismissed
|
|
69
101
|
end
|
|
70
102
|
|
|
71
103
|
# @return [Array<Symbol>] list of departments for current cops.
|
|
72
104
|
def departments
|
|
73
105
|
clear_enrollment_queue
|
|
74
|
-
@departments.
|
|
106
|
+
@departments.to_a
|
|
75
107
|
end
|
|
76
108
|
|
|
77
109
|
# @return [Registry] Cops for that specific department.
|
|
78
110
|
def with_department(department)
|
|
79
|
-
|
|
80
|
-
with(@departments.fetch(department, []))
|
|
111
|
+
filter_by_badge { |badge| badge.department == department }
|
|
81
112
|
end
|
|
82
113
|
|
|
83
114
|
# @return [Registry] Cops not for a specific department.
|
|
84
115
|
def without_department(department)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
without_department.delete(department)
|
|
116
|
+
filter_by_badge { |badge| badge.department != department }
|
|
117
|
+
end
|
|
88
118
|
|
|
89
|
-
|
|
119
|
+
# Returns a new registry containing the cops whose badge satisfies the given block,
|
|
120
|
+
# keeping lazy-loaded cops unloaded.
|
|
121
|
+
#
|
|
122
|
+
# @api private
|
|
123
|
+
# @return [Registry]
|
|
124
|
+
def filter_by_badge(options = {})
|
|
125
|
+
clear_enrollment_queue
|
|
126
|
+
copy = self.class.new([], options)
|
|
127
|
+
@cops_by_badge.each do |badge, cop_or_name|
|
|
128
|
+
copy.add_entry(badge, cop_or_name) if yield(badge)
|
|
129
|
+
end
|
|
130
|
+
copy
|
|
90
131
|
end
|
|
91
132
|
|
|
92
133
|
# @return [Boolean] Checks if given name is department
|
|
@@ -95,7 +136,7 @@ module RuboCop
|
|
|
95
136
|
end
|
|
96
137
|
|
|
97
138
|
def contains_cop_matching?(names)
|
|
98
|
-
|
|
139
|
+
registered_badges.any? { |badge| badge.match_name?(names) }
|
|
99
140
|
end
|
|
100
141
|
|
|
101
142
|
# Convert a user provided cop name into a properly namespaced name
|
|
@@ -130,16 +171,24 @@ module RuboCop
|
|
|
130
171
|
# @note Emits a warning if the provided name has an incorrect namespace
|
|
131
172
|
#
|
|
132
173
|
# @return [String] Qualified cop name
|
|
133
|
-
def qualified_cop_name(name, path, warn: true)
|
|
174
|
+
def qualified_cop_name(name, path, warn: true, correct_namespace: true)
|
|
134
175
|
badge = Badge.parse(name)
|
|
135
|
-
|
|
176
|
+
print_department_missing_warning(name, path) if warn && department_missing?(badge, name)
|
|
136
177
|
return name if registered?(badge)
|
|
178
|
+
# A name qualified with the wrong department is returned as is when
|
|
179
|
+
# namespace correction is not wanted, so the caller can surface the
|
|
180
|
+
# mistake instead of silently acting on the corrected name.
|
|
181
|
+
return name if badge.qualified? && !correct_namespace
|
|
182
|
+
|
|
183
|
+
resolve_cop_name(badge, name, path, warn)
|
|
184
|
+
end
|
|
137
185
|
|
|
186
|
+
def resolve_cop_name(badge, name, path, warn)
|
|
138
187
|
potential_badges = qualify_badge(badge)
|
|
139
188
|
|
|
140
189
|
case potential_badges.size
|
|
141
190
|
when 0 then name # No namespace found. Deal with it later in caller.
|
|
142
|
-
when 1 then resolve_badge(badge, potential_badges.first, path)
|
|
191
|
+
when 1 then resolve_badge(badge, potential_badges.first, path, warn: warn)
|
|
143
192
|
else raise AmbiguousCopName.new(badge, path, potential_badges)
|
|
144
193
|
end
|
|
145
194
|
end
|
|
@@ -148,85 +197,108 @@ module RuboCop
|
|
|
148
197
|
!badge.qualified? && unqualified_cop_names.include?(name)
|
|
149
198
|
end
|
|
150
199
|
|
|
151
|
-
def
|
|
152
|
-
message = "
|
|
200
|
+
def print_department_missing_warning(name, path)
|
|
201
|
+
message = "no department given for #{name}."
|
|
153
202
|
if path.end_with?('.rb')
|
|
154
203
|
message += ' Run `rubocop -a --only Migration/DepartmentName` to fix.'
|
|
155
204
|
end
|
|
156
|
-
|
|
205
|
+
emit_warning(path, message)
|
|
157
206
|
end
|
|
158
207
|
|
|
159
208
|
def unqualified_cop_names
|
|
160
209
|
clear_enrollment_queue
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
210
|
+
|
|
211
|
+
@unqualified_cop_names ||= @cops_by_badge.keys.to_set do |badge|
|
|
212
|
+
File.basename(badge.to_s)
|
|
213
|
+
end << 'RedundantCopDisableDirective'
|
|
164
214
|
end
|
|
165
215
|
|
|
166
216
|
def qualify_badge(badge)
|
|
167
217
|
clear_enrollment_queue
|
|
168
218
|
@departments
|
|
169
|
-
.map { |department
|
|
219
|
+
.map { |department| badge.with_department(department) }
|
|
170
220
|
.select { |potential_badge| registered?(potential_badge) }
|
|
171
221
|
end
|
|
172
222
|
|
|
173
223
|
# @return [Hash{String => Array<Class>}]
|
|
174
224
|
def to_h
|
|
175
225
|
clear_enrollment_queue
|
|
176
|
-
|
|
226
|
+
load_all_lazy_cops
|
|
227
|
+
@cops_by_badge.to_h { |_badge, cop| [cop.cop_name, [cop]] }
|
|
177
228
|
end
|
|
178
229
|
|
|
179
230
|
def cops
|
|
180
231
|
clear_enrollment_queue
|
|
181
|
-
|
|
232
|
+
load_all_lazy_cops
|
|
233
|
+
@cops_by_badge.values
|
|
182
234
|
end
|
|
183
235
|
|
|
184
236
|
def length
|
|
185
237
|
clear_enrollment_queue
|
|
186
|
-
@
|
|
238
|
+
@cops_by_badge.size
|
|
187
239
|
end
|
|
188
240
|
|
|
241
|
+
# Returns the enabled cop classes, loading lazy-loaded cops only when they are enabled.
|
|
242
|
+
#
|
|
243
|
+
# @return [Array<Class>]
|
|
189
244
|
def enabled(config)
|
|
190
|
-
@enabled_cache[config] ||=
|
|
245
|
+
@enabled_cache[config] ||= registered_badges.filter_map do |badge|
|
|
246
|
+
next unless enabled_cop_name?(badge.to_s, config)
|
|
247
|
+
|
|
248
|
+
cop_or_name = @cops_by_badge[badge]
|
|
249
|
+
cop_or_name.is_a?(String) ? load_lazy_cop(badge) : cop_or_name
|
|
250
|
+
end
|
|
191
251
|
end
|
|
192
252
|
|
|
193
253
|
def disabled(config)
|
|
194
254
|
@disabled_cache[config] ||= reject { |cop| enabled?(cop, config) }
|
|
195
255
|
end
|
|
196
256
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if options.fetch(:safe, false)
|
|
207
|
-
cop_enabled && cfg.fetch('Safe', true)
|
|
208
|
-
else
|
|
209
|
-
cop_enabled
|
|
257
|
+
# Returns the names of the disabled cops without loading any of them.
|
|
258
|
+
#
|
|
259
|
+
# @api private
|
|
260
|
+
# @return [Array<String>]
|
|
261
|
+
def disabled_names(config)
|
|
262
|
+
@disabled_names_cache[config] ||= registered_badges.filter_map do |badge|
|
|
263
|
+
name = badge.to_s
|
|
264
|
+
name unless enabled_cop_name?(name, config)
|
|
210
265
|
end
|
|
211
266
|
end
|
|
212
267
|
|
|
213
|
-
def
|
|
268
|
+
def enabled?(cop, config)
|
|
269
|
+
enabled_cop_name?(cop.cop_name, config)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# @param cop [Class, String, nil] the cop class or the qualified cop name
|
|
273
|
+
def enabled_pending_cop?(cop_cfg, config, cop = nil)
|
|
214
274
|
return false if @options[:disable_pending_cops]
|
|
275
|
+
return false unless cop_cfg.fetch('Enabled') == 'pending'
|
|
276
|
+
return true if @options[:enable_pending_cops]
|
|
277
|
+
return config.enabled_new_cops? unless cop
|
|
278
|
+
|
|
279
|
+
cop_name = cop.is_a?(String) ? cop : cop.cop_name
|
|
280
|
+
config.enabled_new_cop?(cop_name)
|
|
281
|
+
end
|
|
215
282
|
|
|
216
|
-
|
|
217
|
-
|
|
283
|
+
# Preview cops are opt-in and stay silent otherwise, so unlike pending cops
|
|
284
|
+
# they are never reported as needing a decision.
|
|
285
|
+
def enabled_preview_cop?(cop_cfg, config)
|
|
286
|
+
cop_cfg.fetch('Enabled') == 'preview' && config.preview?(@options)
|
|
218
287
|
end
|
|
219
288
|
|
|
220
289
|
def names
|
|
221
|
-
|
|
290
|
+
clear_enrollment_queue
|
|
291
|
+
@cops_by_badge.keys.map(&:to_s)
|
|
222
292
|
end
|
|
223
293
|
|
|
224
294
|
def cops_for_department(department)
|
|
225
|
-
|
|
295
|
+
with_department(department.to_sym).cops
|
|
226
296
|
end
|
|
227
297
|
|
|
228
298
|
def names_for_department(department)
|
|
229
|
-
|
|
299
|
+
department = department.to_sym
|
|
300
|
+
|
|
301
|
+
registered_badges.filter_map { |badge| badge.to_s if badge.department == department }
|
|
230
302
|
end
|
|
231
303
|
|
|
232
304
|
def ==(other)
|
|
@@ -235,7 +307,8 @@ module RuboCop
|
|
|
235
307
|
|
|
236
308
|
def sort!
|
|
237
309
|
clear_enrollment_queue
|
|
238
|
-
|
|
310
|
+
load_all_lazy_cops
|
|
311
|
+
@cops_by_badge = @cops_by_badge.sort_by { |badge, _cop| badge.cop_name }.to_h
|
|
239
312
|
|
|
240
313
|
self
|
|
241
314
|
end
|
|
@@ -251,7 +324,11 @@ module RuboCop
|
|
|
251
324
|
# @param [String] cop_name
|
|
252
325
|
# @return [Class, nil]
|
|
253
326
|
def find_by_cop_name(cop_name)
|
|
254
|
-
|
|
327
|
+
clear_enrollment_queue
|
|
328
|
+
badge = Badge.parse(cop_name)
|
|
329
|
+
cop_or_name = @cops_by_badge[badge]
|
|
330
|
+
|
|
331
|
+
cop_or_name.is_a?(String) ? load_lazy_cop(badge) : cop_or_name
|
|
255
332
|
end
|
|
256
333
|
|
|
257
334
|
# When a cop name is given returns a single-element array with the cop class.
|
|
@@ -262,9 +339,33 @@ module RuboCop
|
|
|
262
339
|
cop ? [cop] : cops_for_department(directive)
|
|
263
340
|
end
|
|
264
341
|
|
|
342
|
+
# Loads all cops that are registered for lazy loading. Useful when lazily registered cops
|
|
343
|
+
# must not outlive the current global registry, e.g. before a temporary global registry is
|
|
344
|
+
# discarded in tests.
|
|
345
|
+
#
|
|
346
|
+
# @api private
|
|
347
|
+
def load_all_lazy_cops
|
|
348
|
+
# Take a snapshot because loading a cop can load (and thereby register)
|
|
349
|
+
# another lazy-loaded cop, e.g. its superclass.
|
|
350
|
+
badges = @cops_by_badge.keys
|
|
351
|
+
|
|
352
|
+
badges.each do |badge|
|
|
353
|
+
load_lazy_cop(badge) if @cops_by_badge[badge].is_a?(String)
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
265
357
|
def freeze
|
|
266
358
|
clear_enrollment_queue
|
|
359
|
+
load_all_lazy_cops
|
|
267
360
|
unqualified_cop_names # build cache
|
|
361
|
+
|
|
362
|
+
# Freeze the structural collections as well, so that a cop class defined after
|
|
363
|
+
# the freeze fails fast at its `enlist`/`lazy_load` call site instead of corrupting
|
|
364
|
+
# the registry and failing much later.
|
|
365
|
+
@cops_by_badge.freeze
|
|
366
|
+
@departments.freeze
|
|
367
|
+
@enrollment_queue.freeze
|
|
368
|
+
|
|
268
369
|
super
|
|
269
370
|
end
|
|
270
371
|
|
|
@@ -274,41 +375,109 @@ module RuboCop
|
|
|
274
375
|
attr_reader :global
|
|
275
376
|
end
|
|
276
377
|
|
|
378
|
+
def warnings?(path)
|
|
379
|
+
@warnings[path]
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
protected
|
|
383
|
+
|
|
384
|
+
# Adds an already-loaded cop class or a lazy-load constant name under the given badge,
|
|
385
|
+
# used to build filtered copies.
|
|
386
|
+
def add_entry(badge, cop_or_name)
|
|
387
|
+
@departments << badge.department
|
|
388
|
+
@cops_by_badge[badge] = cop_or_name
|
|
389
|
+
end
|
|
390
|
+
|
|
277
391
|
private
|
|
278
392
|
|
|
279
393
|
def initialize_copy(reg)
|
|
280
|
-
|
|
394
|
+
super
|
|
395
|
+
@cops_by_badge = @cops_by_badge.dup
|
|
396
|
+
@enrollment_queue = @enrollment_queue.dup
|
|
397
|
+
@departments = @departments.dup
|
|
398
|
+
@enabled_cache = {}.compare_by_identity
|
|
399
|
+
@disabled_cache = {}.compare_by_identity
|
|
400
|
+
@disabled_names_cache = {}.compare_by_identity
|
|
401
|
+
@warnings = {}
|
|
402
|
+
@unqualified_cop_names = nil
|
|
281
403
|
end
|
|
282
404
|
|
|
283
405
|
def clear_enrollment_queue
|
|
284
406
|
return if @enrollment_queue.empty?
|
|
285
407
|
|
|
286
408
|
@enrollment_queue.each do |cop|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
@
|
|
290
|
-
@
|
|
409
|
+
# Reassigning a badge that was registered for lazy loading keeps
|
|
410
|
+
# its original position in the insertion-ordered map.
|
|
411
|
+
@cops_by_badge[cop.badge] = cop
|
|
412
|
+
@departments << cop.department
|
|
291
413
|
end
|
|
292
414
|
@enrollment_queue = []
|
|
293
415
|
end
|
|
294
416
|
|
|
295
|
-
def
|
|
296
|
-
|
|
417
|
+
def registered_badges
|
|
418
|
+
clear_enrollment_queue
|
|
419
|
+
@cops_by_badge.keys
|
|
297
420
|
end
|
|
298
421
|
|
|
299
|
-
def
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
422
|
+
def enabled_cop_name?(cop_name, config)
|
|
423
|
+
return true if options[:only]&.include?(cop_name)
|
|
424
|
+
|
|
425
|
+
# We need to use the cop name in this case, because `for_cop` uses
|
|
426
|
+
# caching which expects cop names or cop classes as keys.
|
|
427
|
+
cfg = config.for_cop(cop_name)
|
|
428
|
+
|
|
429
|
+
cop_enabled = cfg.fetch('Enabled') == true ||
|
|
430
|
+
enabled_pending_cop?(cfg, config, cop_name) ||
|
|
431
|
+
enabled_preview_cop?(cfg, config)
|
|
432
|
+
|
|
433
|
+
if options.fetch(:safe, false)
|
|
434
|
+
cop_enabled && cfg.fetch('Safe', true)
|
|
435
|
+
else
|
|
436
|
+
cop_enabled
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
# @return [Class, nil] the loaded cop class, or nil if the cop excluded
|
|
441
|
+
# itself from the registry while being loaded
|
|
442
|
+
def load_lazy_cop(badge)
|
|
443
|
+
constant_name = @cops_by_badge[badge]
|
|
444
|
+
return constant_name unless constant_name.is_a?(String)
|
|
445
|
+
|
|
446
|
+
cop = Kernel.const_get(constant_name)
|
|
447
|
+
if equal?(self.class.global)
|
|
448
|
+
# Resolving the constant fires the autoload, which makes
|
|
449
|
+
# `Base.inherited` enlist the class into the global registry.
|
|
450
|
+
# Enrolling through the queue keeps `exclude_from_registry` honored:
|
|
451
|
+
# a cop that dismissed itself leaves a dangling constant name behind
|
|
452
|
+
# and is removed from the registry.
|
|
453
|
+
clear_enrollment_queue
|
|
454
|
+
cop_or_name = @cops_by_badge[badge]
|
|
455
|
+
@cops_by_badge.delete(badge) if cop_or_name.is_a?(String)
|
|
456
|
+
cop_or_name.is_a?(Class) ? cop_or_name : nil
|
|
457
|
+
else
|
|
458
|
+
# `Base.inherited` enlists into the global registry, not this copy.
|
|
459
|
+
@cops_by_badge[badge] = cop
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
def resolve_badge(given_badge, real_badge, source_path, warn: true)
|
|
464
|
+
if warn && !given_badge.match?(real_badge)
|
|
465
|
+
emit_warning(source_path,
|
|
466
|
+
"#{given_badge} has the wrong namespace - " \
|
|
467
|
+
"replace it with #{given_badge.with_department(real_badge.department)}")
|
|
304
468
|
end
|
|
305
469
|
|
|
306
470
|
real_badge.to_s
|
|
307
471
|
end
|
|
308
472
|
|
|
473
|
+
def emit_warning(path, message)
|
|
474
|
+
Registry.global.warnings[path] = true
|
|
475
|
+
warn "#{PathUtil.smart_path(path)}: Warning: #{message}"
|
|
476
|
+
end
|
|
477
|
+
|
|
309
478
|
def registered?(badge)
|
|
310
479
|
clear_enrollment_queue
|
|
311
|
-
@
|
|
480
|
+
@cops_by_badge.key?(badge)
|
|
312
481
|
end
|
|
313
482
|
end
|
|
314
483
|
end
|
|
@@ -3,21 +3,35 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Security
|
|
6
|
-
# Checks for the use of `Kernel#eval` and `Binding#eval
|
|
6
|
+
# Checks for the use of `Kernel#eval` and `Binding#eval` with
|
|
7
|
+
# dynamic strings as arguments. Evaluating non-literal strings
|
|
8
|
+
# can enable code injection attacks and makes it difficult to
|
|
9
|
+
# reason about what code will actually be executed.
|
|
10
|
+
#
|
|
11
|
+
# Calls to `eval` with literal strings are not flagged by this cop,
|
|
12
|
+
# as they do not pose the same injection risk.
|
|
7
13
|
#
|
|
8
14
|
# @example
|
|
9
15
|
#
|
|
10
16
|
# # bad
|
|
11
|
-
#
|
|
12
17
|
# eval(something)
|
|
13
18
|
# binding.eval(something)
|
|
19
|
+
# Kernel.eval(something)
|
|
20
|
+
#
|
|
21
|
+
# # good - use safer alternatives
|
|
22
|
+
# obj.public_send(method_name)
|
|
23
|
+
# obj.send(method_name, *args)
|
|
24
|
+
#
|
|
25
|
+
# # good - literal strings are allowed
|
|
26
|
+
# eval("1 + 1")
|
|
27
|
+
# binding.eval("foo")
|
|
14
28
|
class Eval < Base
|
|
15
29
|
MSG = 'The use of `eval` is a serious security risk.'
|
|
16
30
|
RESTRICT_ON_SEND = %i[eval].freeze
|
|
17
31
|
|
|
18
32
|
# @!method eval?(node)
|
|
19
33
|
def_node_matcher :eval?, <<~PATTERN
|
|
20
|
-
(send {nil? (send nil? :binding)} :eval $!str ...)
|
|
34
|
+
(send {nil? (send nil? :binding) (const {cbase nil?} :Kernel)} :eval $!str ...)
|
|
21
35
|
PATTERN
|
|
22
36
|
|
|
23
37
|
def on_send(node)
|
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
|
10
10
|
# a subprocess is created in the same way as `Kernel#open`, and its output is returned.
|
|
11
11
|
# `Kernel#open` may allow unintentional command injection, which is the reason these
|
|
12
12
|
# `IO` methods are a security risk.
|
|
13
|
-
# Consider
|
|
13
|
+
# Consider using `File.read` to disable the behavior of subprocess invocation.
|
|
14
14
|
#
|
|
15
15
|
# @safety
|
|
16
16
|
# This cop is unsafe because false positive will occur if the variable passed as
|
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
|
37
37
|
return unless (receiver = node.receiver) && receiver.source == 'IO'
|
|
38
38
|
|
|
39
39
|
argument = node.first_argument
|
|
40
|
-
return if argument
|
|
40
|
+
return if argument&.str_type? && argument.value.strip.start_with?('|')
|
|
41
41
|
|
|
42
42
|
add_offense(node, message: format(MSG, method_name: node.method_name)) do |corrector|
|
|
43
43
|
corrector.replace(receiver, 'File')
|