rubocop 1.71.1 → 1.92.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 +885 -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 +50 -5
- data/lib/rubocop/changed_files.rb +134 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +54 -3
- data/lib/rubocop/cli/command/explain.rb +34 -0
- 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 +8 -2
- data/lib/rubocop/cli/command/show_docs_url.rb +8 -10
- data/lib/rubocop/cli/command/suggest_extensions.rb +8 -2
- data/lib/rubocop/cli.rb +59 -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 +98 -45
- data/lib/rubocop/config.rb +137 -19
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader.rb +75 -49
- data/lib/rubocop/config_loader_resolver.rb +124 -33
- 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 +9 -1
- 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 +75 -12
- data/lib/rubocop/cop/autocorrect_logic.rb +43 -17
- data/lib/rubocop/cop/badge.rb +9 -1
- data/lib/rubocop/cop/base.rb +128 -35
- data/lib/rubocop/cop/bundler/gem_comment.rb +5 -4
- data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
- data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -11
- data/lib/rubocop/cop/bundler.rb +19 -0
- data/lib/rubocop/cop/commissioner.rb +13 -11
- data/lib/rubocop/cop/cop_documentation.rb +81 -0
- data/lib/rubocop/cop/cop_explanation.rb +140 -0
- data/lib/rubocop/cop/corrector.rb +4 -4
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +92 -11
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
- data/lib/rubocop/cop/correctors/empty_line_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 +29 -2
- 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 +73 -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 +3 -4
- data/lib/rubocop/cop/exclude_limit.rb +31 -5
- data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
- data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
- 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 -9
- 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 +16 -20
- 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 +85 -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_context_config_parameter.rb +1 -7
- 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/style_detected_api_use.rb +1 -7
- 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 +86 -4
- data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +28 -10
- data/lib/rubocop/cop/layout/class_structure.rb +172 -36
- 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 +5 -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_after_multiline_condition.rb +14 -5
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +46 -21
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- 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 +2 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +14 -3
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +17 -3
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- 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 +20 -8
- data/lib/rubocop/cop/layout/extra_spacing.rb +109 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +57 -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 +25 -18
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +20 -18
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +5 -3
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +48 -3
- data/lib/rubocop/cop/layout/indentation_style.rb +5 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +159 -12
- data/lib/rubocop/cop/layout/leading_comment_space.rb +40 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +10 -4
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/line_length.rb +201 -30
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +69 -57
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +8 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +11 -1
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +63 -56
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +7 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +259 -40
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
- 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 +111 -7
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +29 -9
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
- data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
- data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
- data/lib/rubocop/cop/layout/space_around_keyword.rb +20 -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 +5 -1
- 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 +55 -36
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +32 -8
- 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.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +3 -11
- 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 +22 -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 +152 -11
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +75 -37
- data/lib/rubocop/cop/lint/loop.rb +24 -2
- data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +245 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +60 -23
- 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 +20 -11
- 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 +160 -39
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +53 -19
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +28 -6
- 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 +54 -11
- 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 +63 -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 +68 -22
- 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/class_length.rb +4 -2
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
- data/lib/rubocop/cop/metrics/method_length.rb +3 -2
- data/lib/rubocop/cop/metrics/module_length.rb +4 -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 +7 -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 +44 -23
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +10 -8
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- 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 +13 -2
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
- 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 +59 -17
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +52 -25
- 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/min_branches_count.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +10 -1
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +2 -2
- data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +79 -8
- data/lib/rubocop/cop/mixin/project_index_help.rb +203 -0
- data/lib/rubocop/cop/mixin/range_help.rb +16 -5
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +181 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +66 -10
- 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 +93 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +8 -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/heredoc_delimiter_case.rb +9 -2
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
- 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} +65 -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 +108 -9
- data/lib/rubocop/cop/registry.rb +234 -65
- 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 +45 -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 +54 -13
- data/lib/rubocop/cop/style/accessor_grouping.rb +47 -10
- data/lib/rubocop/cop/style/alias.rb +33 -8
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
- data/lib/rubocop/cop/style/and_or.rb +6 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +52 -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 +8 -6
- 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 +13 -5
- data/lib/rubocop/cop/style/block_delimiters.rb +71 -40
- data/lib/rubocop/cop/style/case_equality.rb +29 -15
- data/lib/rubocop/cop/style/case_like_if.rb +12 -11
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +179 -27
- data/lib/rubocop/cop/style/class_equality_comparison.rb +22 -14
- data/lib/rubocop/cop/style/class_methods_definitions.rb +19 -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 +88 -9
- 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 +53 -9
- data/lib/rubocop/cop/style/conditional_assignment.rb +58 -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 +184 -20
- 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 +14 -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 +12 -3
- data/lib/rubocop/cop/style/empty_method.rb +15 -9
- 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 +252 -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 +52 -8
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
- data/lib/rubocop/cop/style/explicit_block_argument.rb +62 -9
- 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 +43 -15
- data/lib/rubocop/cop/style/for.rb +48 -1
- data/lib/rubocop/cop/style/format_string.rb +44 -9
- data/lib/rubocop/cop/style/format_string_token.rb +86 -16
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +5 -3
- 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 +41 -24
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
- data/lib/rubocop/cop/style/hash_conversion.rb +52 -16
- 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 +128 -0
- data/lib/rubocop/cop/style/hash_slice.rb +16 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +23 -6
- 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 +39 -11
- data/lib/rubocop/cop/style/if_inside_else.rb +46 -21
- data/lib/rubocop/cop/style/if_unless_modifier.rb +90 -66
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +19 -19
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -2
- data/lib/rubocop/cop/style/if_with_semicolon.rb +61 -8
- 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 +34 -8
- 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 +150 -0
- data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +23 -11
- data/lib/rubocop/cop/style/lambda.rb +30 -1
- data/lib/rubocop/cop/style/lambda_call.rb +31 -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 +6 -4
- 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 +75 -24
- 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 +58 -6
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +36 -8
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +36 -8
- data/lib/rubocop/cop/style/min_max_comparison.rb +17 -6
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- 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 +47 -5
- data/lib/rubocop/cop/style/multiline_if_then.rb +10 -4
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
- data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +15 -22
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
- data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
- data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
- data/lib/rubocop/cop/style/mutable_constant.rb +139 -13
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +3 -3
- data/lib/rubocop/cop/style/negative_array_index.rb +228 -0
- data/lib/rubocop/cop/style/nested_modifier.rb +36 -12
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
- data/lib/rubocop/cop/style/next.rb +68 -10
- data/lib/rubocop/cop/style/nil_comparison.rb +53 -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 +12 -3
- 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 +22 -6
- 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 +35 -15
- 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 +18 -3
- 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 +216 -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 +58 -6
- data/lib/rubocop/cop/style/redundant_condition.rb +93 -18
- 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 +17 -3
- data/lib/rubocop/cop/style/redundant_each.rb +4 -5
- data/lib/rubocop/cop/style/redundant_exception.rb +22 -4
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +11 -11
- 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 +12 -3
- 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 +176 -83
- data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +15 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +27 -7
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +16 -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 +107 -29
- data/lib/rubocop/cop/style/require_order.rb +9 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +10 -12
- data/lib/rubocop/cop/style/return_nil.rb +19 -4
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
- 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 +19 -13
- 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 +13 -16
- data/lib/rubocop/cop/style/semicolon.rb +56 -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 +28 -11
- 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 +32 -6
- data/lib/rubocop/cop/style/static_class.rb +21 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +38 -16
- 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 +7 -6
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +34 -14
- data/lib/rubocop/cop/style/tally_method.rb +181 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +34 -1
- 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 +35 -32
- 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 +26 -12
- data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
- 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 +172 -49
- 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 +8 -4
- 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 +42 -11
- 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/base_formatter.rb +22 -0
- 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 +7 -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 +82 -7
- 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 +5 -4
- data/lib/rubocop/formatter/pacman_formatter.rb +5 -2
- data/lib/rubocop/formatter/sarif_formatter.rb +186 -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 +5 -4
- 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 +66 -15
- data/lib/rubocop/lsp/server.rb +4 -2
- data/lib/rubocop/lsp/stdin_runner.rb +38 -19
- data/lib/rubocop/lsp.rb +5 -2
- data/lib/rubocop/magic_comment.rb +55 -0
- data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
- data/lib/rubocop/mcp/explain_tool.rb +68 -0
- data/lib/rubocop/mcp/scope.rb +65 -0
- data/lib/rubocop/mcp/server.rb +307 -0
- data/lib/rubocop/mcp/source_files.rb +35 -0
- data/lib/rubocop/offense_limit.rb +30 -0
- data/lib/rubocop/options.rb +166 -23
- data/lib/rubocop/path_util.rb +20 -5
- data/lib/rubocop/pending_cops_reporter.rb +51 -0
- data/lib/rubocop/plugin/configuration_integrator.rb +153 -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 +18 -13
- data/lib/rubocop/result_cache.rb +110 -65
- 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 +368 -106
- 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/util.rb +69 -0
- data/lib/rubocop/version.rb +48 -10
- data/lib/rubocop.rb +35 -682
- data/lib/ruby_lsp/rubocop/addon.rb +28 -17
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
- metadata +129 -21
- 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/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
|
|
@@ -43,21 +43,44 @@ module RuboCop
|
|
|
43
43
|
|
|
44
44
|
def self.qualified_cop?(name)
|
|
45
45
|
badge = Badge.parse(name)
|
|
46
|
-
global.qualify_badge(badge).
|
|
46
|
+
global.qualify_badge(badge).include?(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')
|
|
@@ -6,22 +6,50 @@ module RuboCop
|
|
|
6
6
|
# Checks for the use of JSON class methods which have potential
|
|
7
7
|
# security issues.
|
|
8
8
|
#
|
|
9
|
+
# `JSON.load` and similar methods allow deserialization of arbitrary ruby objects:
|
|
10
|
+
#
|
|
11
|
+
# [source,ruby]
|
|
12
|
+
# ----
|
|
13
|
+
# require 'json/add/string'
|
|
14
|
+
# result = JSON.load('{ "json_class": "String", "raw": [72, 101, 108, 108, 111] }')
|
|
15
|
+
# pp result # => "Hello"
|
|
16
|
+
# ----
|
|
17
|
+
#
|
|
18
|
+
# Never use `JSON.load` for untrusted user input. Prefer `JSON.parse` unless you have
|
|
19
|
+
# a concrete use-case for `JSON.load`.
|
|
20
|
+
#
|
|
21
|
+
# NOTE: Starting with `json` gem version 2.8.0, triggering this behavior without explicitly
|
|
22
|
+
# passing the `create_additions` keyword argument emits a deprecation warning, with the
|
|
23
|
+
# goal of being secure by default in the next major version 3.0.0.
|
|
24
|
+
#
|
|
25
|
+
# NOTE: Before `json` gem version 2.17.0, `JSON.load` only takes options as its third
|
|
26
|
+
# argument. A hash passed as the second argument is taken as the `proc` argument, so
|
|
27
|
+
# its `create_additions` option is ignored. Which `json` version runs can't be told
|
|
28
|
+
# statically (the lockfile may resolve a newer one than the default gem loaded in
|
|
29
|
+
# production), so options passed as the second argument are always reported. Pass
|
|
30
|
+
# `nil` as the second argument instead.
|
|
31
|
+
#
|
|
9
32
|
# @safety
|
|
10
33
|
# This cop's autocorrection is unsafe because it's potentially dangerous.
|
|
11
|
-
# If using a stream, like `JSON.load(open('file'))`,
|
|
34
|
+
# If using a stream, like `JSON.load(open('file'))`, you will need to call
|
|
12
35
|
# `#read` manually, like `JSON.parse(open('file').read)`.
|
|
13
|
-
# If reading single values (rather than proper JSON objects), like
|
|
14
|
-
# `JSON.load('false')`, it will need to pass the `quirks_mode: true`
|
|
15
|
-
# option, like `JSON.parse('false', quirks_mode: true)`.
|
|
16
36
|
# Other similar issues may apply.
|
|
17
37
|
#
|
|
18
38
|
# @example
|
|
19
39
|
# # bad
|
|
20
|
-
# JSON.load(
|
|
21
|
-
# JSON.restore(
|
|
40
|
+
# JSON.load('{}')
|
|
41
|
+
# JSON.restore('{}')
|
|
42
|
+
#
|
|
43
|
+
# # bad - ignored by `json` older than 2.17.0
|
|
44
|
+
# JSON.load('{}', create_additions: false)
|
|
22
45
|
#
|
|
23
46
|
# # good
|
|
24
|
-
# JSON.parse(
|
|
47
|
+
# JSON.parse('{}')
|
|
48
|
+
# JSON.unsafe_load('{}')
|
|
49
|
+
#
|
|
50
|
+
# # good - explicit use of `create_additions` option
|
|
51
|
+
# JSON.load('{}', nil, create_additions: true)
|
|
52
|
+
# JSON.load('{}', nil, create_additions: false)
|
|
25
53
|
#
|
|
26
54
|
class JSONLoad < Base
|
|
27
55
|
extend AutoCorrector
|
|
@@ -29,13 +57,19 @@ module RuboCop
|
|
|
29
57
|
MSG = 'Prefer `JSON.parse` over `JSON.%<method>s`.'
|
|
30
58
|
RESTRICT_ON_SEND = %i[load restore].freeze
|
|
31
59
|
|
|
32
|
-
# @!method
|
|
33
|
-
def_node_matcher :
|
|
34
|
-
(
|
|
60
|
+
# @!method insecure_json_load(node)
|
|
61
|
+
def_node_matcher :insecure_json_load, <<~PATTERN
|
|
62
|
+
(
|
|
63
|
+
send (const {nil? cbase} :JSON) ${:load :restore}
|
|
64
|
+
{
|
|
65
|
+
_ hash
|
|
66
|
+
| ... !`(pair (sym :create_additions) _)
|
|
67
|
+
}
|
|
68
|
+
)
|
|
35
69
|
PATTERN
|
|
36
70
|
|
|
37
71
|
def on_send(node)
|
|
38
|
-
|
|
72
|
+
insecure_json_load(node) do |method|
|
|
39
73
|
add_offense(node.loc.selector, message: format(MSG, method: method)) do |corrector|
|
|
40
74
|
corrector.replace(node.loc.selector, 'parse')
|
|
41
75
|
end
|
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
|
25
25
|
# @!method marshal_load(node)
|
|
26
26
|
def_node_matcher :marshal_load, <<~PATTERN
|
|
27
27
|
(send (const {nil? cbase} :Marshal) ${:load :restore}
|
|
28
|
-
!(send (const {nil? cbase} :Marshal) :dump ...))
|
|
28
|
+
!(send (const {nil? cbase} :Marshal) :dump ...) _?)
|
|
29
29
|
PATTERN
|
|
30
30
|
|
|
31
31
|
def on_send(node)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
# Cops for the `Security` department. The department's cops are registered for lazy loading
|
|
6
|
+
# and their files are loaded on demand.
|
|
7
|
+
module Security
|
|
8
|
+
extend LazyLoader
|
|
9
|
+
|
|
10
|
+
register_cop :CompoundHash, "#{__dir__}/security/compound_hash"
|
|
11
|
+
register_cop :Eval, "#{__dir__}/security/eval"
|
|
12
|
+
register_cop :IoMethods, "#{__dir__}/security/io_methods"
|
|
13
|
+
register_cop :JSONLoad, "#{__dir__}/security/json_load"
|
|
14
|
+
register_cop :MarshalLoad, "#{__dir__}/security/marshal_load"
|
|
15
|
+
register_cop :Open, "#{__dir__}/security/open"
|
|
16
|
+
register_cop :YAMLLoad, "#{__dir__}/security/yaml_load"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/rubocop/cop/severity.rb
CHANGED
|
@@ -21,6 +21,18 @@ module RuboCop
|
|
|
21
21
|
# any of `:info`, `:refactor`, `:convention`, `:warning`, `:error` or `:fatal`.
|
|
22
22
|
attr_reader :name
|
|
23
23
|
|
|
24
|
+
# The lowest severity that makes a run fail: `--fail-level` when given,
|
|
25
|
+
# otherwise `AllCops: FailLevel`. `autocorrect` is a pseudo level on the
|
|
26
|
+
# command line that gates on corrections instead, so it leaves the
|
|
27
|
+
# threshold at the configured one.
|
|
28
|
+
def self.minimum_to_fail(options, config)
|
|
29
|
+
name = options[:fail_level]
|
|
30
|
+
if name.nil? || name == :autocorrect
|
|
31
|
+
name = (config&.for_all_cops&.[]('FailLevel') || :refactor).to_sym
|
|
32
|
+
end
|
|
33
|
+
new(name)
|
|
34
|
+
end
|
|
35
|
+
|
|
24
36
|
def self.name_from_code(code)
|
|
25
37
|
name = code.to_sym
|
|
26
38
|
CODE_TABLE[name] || name
|