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
|
@@ -12,6 +12,11 @@ module RuboCop
|
|
|
12
12
|
# exception class handle `StandardError` and its subclasses,
|
|
13
13
|
# but not `Exception` and its subclasses.
|
|
14
14
|
#
|
|
15
|
+
# When `AllCops/UseProjectIndex` is enabled and the `rubydex` gem is
|
|
16
|
+
# installed, indirect inheritance is also detected: a class whose parent
|
|
17
|
+
# (defined anywhere in the project) ultimately inherits from `Exception`
|
|
18
|
+
# is reported, without autocorrection.
|
|
19
|
+
#
|
|
15
20
|
# @example EnforcedStyle: standard_error (default)
|
|
16
21
|
# # bad
|
|
17
22
|
#
|
|
@@ -39,9 +44,11 @@ module RuboCop
|
|
|
39
44
|
# C = Class.new(RuntimeError)
|
|
40
45
|
class InheritException < Base
|
|
41
46
|
include ConfigurableEnforcedStyle
|
|
47
|
+
include ProjectIndexHelp
|
|
42
48
|
extend AutoCorrector
|
|
43
49
|
|
|
44
50
|
MSG = 'Inherit from `%<prefer>s` instead of `Exception`.'
|
|
51
|
+
INDIRECT_MSG = 'Inherit from `%<prefer>s` instead of `Exception` (inherited via `%<via>s`).'
|
|
45
52
|
PREFERRED_BASE_CLASS = {
|
|
46
53
|
runtime_error: 'RuntimeError',
|
|
47
54
|
standard_error: 'StandardError'
|
|
@@ -57,13 +64,20 @@ module RuboCop
|
|
|
57
64
|
PATTERN
|
|
58
65
|
|
|
59
66
|
def on_class(node)
|
|
60
|
-
|
|
61
|
-
return
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
parent_class = node.parent_class
|
|
68
|
+
return unless parent_class
|
|
69
|
+
|
|
70
|
+
if exception_class?(parent_class)
|
|
71
|
+
return if inherit_exception_class_with_omitted_namespace?(node)
|
|
72
|
+
|
|
73
|
+
add_offense(parent_class, message: message(parent_class)) do |corrector|
|
|
74
|
+
corrector.replace(parent_class, preferred_base_class)
|
|
75
|
+
end
|
|
76
|
+
elsif (via = inherits_exception_via(parent_class))
|
|
77
|
+
# No autocorrection: the `Exception` inheritance lives at another
|
|
78
|
+
# class' definition site, possibly in another file.
|
|
79
|
+
message = format(INDIRECT_MSG, prefer: preferred_base_class, via: via)
|
|
80
|
+
add_offense(parent_class, message: message)
|
|
67
81
|
end
|
|
68
82
|
end
|
|
69
83
|
|
|
@@ -88,6 +102,38 @@ module RuboCop
|
|
|
88
102
|
class_node.const_name == 'Exception'
|
|
89
103
|
end
|
|
90
104
|
|
|
105
|
+
# When `AllCops/UseProjectIndex` is enabled, indirect inheritance is
|
|
106
|
+
# detected by walking the parent's indexed ancestry: `Exception` itself
|
|
107
|
+
# is not indexed, so a chain ending in it shows up as an ancestor whose
|
|
108
|
+
# superclass reference is unresolved and literally named `Exception`.
|
|
109
|
+
# Returns the name of that ancestor, or `nil`.
|
|
110
|
+
def inherits_exception_via(parent_class)
|
|
111
|
+
return nil unless project_index && parent_class.const_type?
|
|
112
|
+
|
|
113
|
+
declaration = resolve_constant_in_index(parent_class)
|
|
114
|
+
return nil unless declaration.is_a?(Rubydex::Class)
|
|
115
|
+
|
|
116
|
+
exception_ancestor(declaration)&.name
|
|
117
|
+
rescue StandardError
|
|
118
|
+
nil
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def exception_ancestor(declaration)
|
|
122
|
+
declaration.ancestors.find do |ancestor|
|
|
123
|
+
ancestor.is_a?(Rubydex::Class) && exception_superclass_reference?(ancestor)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def exception_superclass_reference?(ancestor)
|
|
128
|
+
ancestor.definitions.any? do |definition|
|
|
129
|
+
next false unless definition.is_a?(Rubydex::ClassDefinition)
|
|
130
|
+
|
|
131
|
+
superclass = definition.superclass
|
|
132
|
+
superclass.is_a?(Rubydex::UnresolvedConstantReference) &&
|
|
133
|
+
superclass.name.delete_prefix('::') == 'Exception'
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
91
137
|
def inherit_exception_class_with_omitted_namespace?(class_node)
|
|
92
138
|
return false if class_node.parent_class.namespace&.cbase_type?
|
|
93
139
|
|
|
@@ -24,8 +24,25 @@ module RuboCop
|
|
|
24
24
|
MSG = 'Interpolation in single quoted string detected. ' \
|
|
25
25
|
'Use double quoted strings if you need interpolation.'
|
|
26
26
|
|
|
27
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
28
27
|
def on_str(node)
|
|
28
|
+
check(node)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# A multiline single-quoted string is parsed as a `dstr` of `str` segments, so it
|
|
32
|
+
# is not covered by `on_str`. Inspect single-quoted `dstr`s here; double-quoted
|
|
33
|
+
# interpolation is also a `dstr`, hence the delimiter check.
|
|
34
|
+
def on_dstr(node)
|
|
35
|
+
# A heredoc is also a `dstr`, but its `loc` is a `Parser::Source::Map::Heredoc`
|
|
36
|
+
# with no `begin`, so bail before touching it.
|
|
37
|
+
return if heredoc?(node)
|
|
38
|
+
|
|
39
|
+
check(node) if node.loc.begin&.source == "'"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
# rubocop:disable-next Metrics/CyclomaticComplexity
|
|
45
|
+
def check(node)
|
|
29
46
|
return if node.parent&.regexp_type?
|
|
30
47
|
return unless /(?<!\\)#\{.*\}/.match?(node.source)
|
|
31
48
|
return if heredoc?(node)
|
|
@@ -34,9 +51,6 @@ module RuboCop
|
|
|
34
51
|
|
|
35
52
|
add_offense(node) { |corrector| autocorrect(corrector, node) }
|
|
36
53
|
end
|
|
37
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
38
|
-
|
|
39
|
-
private
|
|
40
54
|
|
|
41
55
|
def autocorrect(corrector, node)
|
|
42
56
|
starting_token, ending_token = if node.source.include?('"')
|
|
@@ -54,9 +68,14 @@ module RuboCop
|
|
|
54
68
|
end
|
|
55
69
|
|
|
56
70
|
def valid_syntax?(node)
|
|
57
|
-
double_quoted_string = node.source.
|
|
71
|
+
double_quoted_string = if node.source.include?('"')
|
|
72
|
+
node.source.sub(/\A'/, '%{').sub(/'\z/, '}')
|
|
73
|
+
else
|
|
74
|
+
node.source.gsub(/\A'|'\z/, '"')
|
|
75
|
+
end
|
|
58
76
|
|
|
59
|
-
parse(double_quoted_string)
|
|
77
|
+
processed_source = parse(double_quoted_string)
|
|
78
|
+
processed_source.valid_syntax? && processed_source.ast.dstr_type?
|
|
60
79
|
end
|
|
61
80
|
end
|
|
62
81
|
end
|
|
@@ -18,12 +18,15 @@ module RuboCop
|
|
|
18
18
|
# end
|
|
19
19
|
#
|
|
20
20
|
# # bad
|
|
21
|
-
#
|
|
21
|
+
# # We're only interested in the left hand side being a truthy literal,
|
|
22
|
+
# # because it affects the evaluation of the &&, whereas the right hand
|
|
23
|
+
# # side will be conditionally executed/called and can be a literal.
|
|
24
|
+
# if true && some_var
|
|
22
25
|
# do_something
|
|
23
26
|
# end
|
|
24
27
|
#
|
|
25
28
|
# # good
|
|
26
|
-
# if some_var
|
|
29
|
+
# if some_var
|
|
27
30
|
# do_something
|
|
28
31
|
# end
|
|
29
32
|
#
|
|
@@ -34,30 +37,105 @@ module RuboCop
|
|
|
34
37
|
# end
|
|
35
38
|
class LiteralAsCondition < Base
|
|
36
39
|
include RangeHelp
|
|
40
|
+
extend AutoCorrector
|
|
37
41
|
|
|
38
42
|
MSG = 'Literal `%<literal>s` appeared as a condition.'
|
|
39
43
|
RESTRICT_ON_SEND = [:!].freeze
|
|
40
44
|
|
|
45
|
+
def on_and(node)
|
|
46
|
+
return unless node.lhs.truthy_literal?
|
|
47
|
+
|
|
48
|
+
add_offense(node.lhs) do |corrector|
|
|
49
|
+
# Don't autocorrect `'foo' && return` because having `return` as
|
|
50
|
+
# the leftmost node can lead to a void value expression syntax error.
|
|
51
|
+
next if void_value_expression?(node.rhs)
|
|
52
|
+
|
|
53
|
+
corrector.replace(node, node.rhs.source)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def on_or(node)
|
|
58
|
+
return unless node.lhs.falsey_literal?
|
|
59
|
+
|
|
60
|
+
add_offense(node.lhs) do |corrector|
|
|
61
|
+
# Don't autocorrect `'foo' && return` because having `return` as
|
|
62
|
+
# the leftmost node can lead to a void value expression syntax error.
|
|
63
|
+
next if void_value_expression?(node.rhs)
|
|
64
|
+
|
|
65
|
+
corrector.replace(node, node.rhs.source)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
41
69
|
def on_if(node)
|
|
42
|
-
|
|
70
|
+
cond = condition(node)
|
|
71
|
+
|
|
72
|
+
return unless cond.falsey_literal? || cond.truthy_literal?
|
|
73
|
+
|
|
74
|
+
correct_if_node(node, cond)
|
|
43
75
|
end
|
|
44
76
|
|
|
45
77
|
def on_while(node)
|
|
46
|
-
return if
|
|
78
|
+
return if node.condition.source == 'true'
|
|
47
79
|
|
|
48
|
-
|
|
80
|
+
if node.condition.truthy_literal?
|
|
81
|
+
add_offense(node.condition) do |corrector|
|
|
82
|
+
corrector.replace(node.condition, 'true')
|
|
83
|
+
end
|
|
84
|
+
elsif node.condition.falsey_literal?
|
|
85
|
+
add_offense(node.condition) do |corrector|
|
|
86
|
+
corrector.remove(node)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
92
|
+
def on_while_post(node)
|
|
93
|
+
return if node.condition.source == 'true'
|
|
94
|
+
|
|
95
|
+
if node.condition.truthy_literal?
|
|
96
|
+
add_offense(node.condition) do |corrector|
|
|
97
|
+
corrector.replace(node, node.source.sub(node.condition.source, 'true'))
|
|
98
|
+
end
|
|
99
|
+
elsif node.condition.falsey_literal?
|
|
100
|
+
add_offense(node.condition) do |corrector|
|
|
101
|
+
corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
|
|
102
|
+
end
|
|
103
|
+
end
|
|
49
104
|
end
|
|
50
|
-
alias on_while_post on_while
|
|
51
105
|
|
|
52
106
|
def on_until(node)
|
|
53
|
-
return if
|
|
107
|
+
return if node.condition.source == 'false'
|
|
54
108
|
|
|
55
|
-
|
|
109
|
+
if node.condition.falsey_literal?
|
|
110
|
+
add_offense(node.condition) do |corrector|
|
|
111
|
+
corrector.replace(node.condition, 'false')
|
|
112
|
+
end
|
|
113
|
+
elsif node.condition.truthy_literal?
|
|
114
|
+
add_offense(node.condition) do |corrector|
|
|
115
|
+
corrector.remove(node)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
121
|
+
def on_until_post(node)
|
|
122
|
+
return if node.condition.source == 'false'
|
|
123
|
+
|
|
124
|
+
if node.condition.falsey_literal?
|
|
125
|
+
add_offense(node.condition) do |corrector|
|
|
126
|
+
corrector.replace(node, node.source.sub(node.condition.source, 'false'))
|
|
127
|
+
end
|
|
128
|
+
elsif node.condition.truthy_literal?
|
|
129
|
+
add_offense(node.condition) do |corrector|
|
|
130
|
+
corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
|
|
131
|
+
end
|
|
132
|
+
end
|
|
56
133
|
end
|
|
57
|
-
alias on_until_post on_until
|
|
58
134
|
|
|
59
135
|
def on_case(case_node)
|
|
60
|
-
if case_node.condition
|
|
136
|
+
if (cond = case_node.condition)
|
|
137
|
+
return if !cond.falsey_literal? && !cond.truthy_literal?
|
|
138
|
+
|
|
61
139
|
check_case(case_node)
|
|
62
140
|
else
|
|
63
141
|
case_node.when_branches.each do |when_node|
|
|
@@ -77,7 +155,7 @@ module RuboCop
|
|
|
77
155
|
|
|
78
156
|
check_case(case_match_node)
|
|
79
157
|
else
|
|
80
|
-
case_match_node.
|
|
158
|
+
case_match_node.in_pattern_branches.each do |in_pattern_node|
|
|
81
159
|
next unless in_pattern_node.condition.literal?
|
|
82
160
|
|
|
83
161
|
add_offense(in_pattern_node)
|
|
@@ -97,6 +175,12 @@ module RuboCop
|
|
|
97
175
|
|
|
98
176
|
private
|
|
99
177
|
|
|
178
|
+
def void_value_expression?(node)
|
|
179
|
+
node = node.children.last while node&.begin_type?
|
|
180
|
+
|
|
181
|
+
node&.type?(:return, :break, :next)
|
|
182
|
+
end
|
|
183
|
+
|
|
100
184
|
def check_for_literal(node)
|
|
101
185
|
cond = condition(node)
|
|
102
186
|
if cond.literal?
|
|
@@ -130,6 +214,8 @@ module RuboCop
|
|
|
130
214
|
|
|
131
215
|
def handle_node(node)
|
|
132
216
|
if node.literal?
|
|
217
|
+
return if node.parent.and_type?
|
|
218
|
+
|
|
133
219
|
add_offense(node)
|
|
134
220
|
elsif %i[send and or begin].include?(node.type)
|
|
135
221
|
check_node(node)
|
|
@@ -159,6 +245,46 @@ module RuboCop
|
|
|
159
245
|
when_node.conditions.last.source_range.end_pos
|
|
160
246
|
)
|
|
161
247
|
end
|
|
248
|
+
|
|
249
|
+
def condition_evaluation?(node, cond)
|
|
250
|
+
if node.unless?
|
|
251
|
+
cond.falsey_literal?
|
|
252
|
+
else
|
|
253
|
+
cond.truthy_literal?
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# rubocop:disable-next Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
258
|
+
def correct_if_node(node, cond)
|
|
259
|
+
result = condition_evaluation?(node, cond)
|
|
260
|
+
|
|
261
|
+
# When the branch that survives the literal condition is missing,
|
|
262
|
+
# there is no meaningful correction, so no offense is registered.
|
|
263
|
+
surviving_branch = result ? node.if_branch : node.else_branch
|
|
264
|
+
return if surviving_branch.nil? && (node.elsif? || node.else?)
|
|
265
|
+
|
|
266
|
+
new_node = if node.elsif? && result
|
|
267
|
+
"else\n #{range_with_comments(node.if_branch).source}"
|
|
268
|
+
elsif node.elsif? && !result
|
|
269
|
+
"else\n #{node.else_branch.source}"
|
|
270
|
+
elsif node.if_branch && result
|
|
271
|
+
node.if_branch.source
|
|
272
|
+
elsif node.elsif_conditional?
|
|
273
|
+
"#{node.else_branch.source.sub('elsif', 'if')}\nend"
|
|
274
|
+
elsif node.else? || node.ternary?
|
|
275
|
+
node.else_branch.source
|
|
276
|
+
else
|
|
277
|
+
'' # Equivalent to removing the node
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
add_offense(cond) do |corrector|
|
|
281
|
+
next if part_of_ignored_node?(node)
|
|
282
|
+
|
|
283
|
+
corrector.replace(node, new_node)
|
|
284
|
+
|
|
285
|
+
ignore_node(node)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
162
288
|
end
|
|
163
289
|
end
|
|
164
290
|
end
|
|
@@ -56,7 +56,17 @@ module RuboCop
|
|
|
56
56
|
def traverse_node(node, &block)
|
|
57
57
|
yield node if node.equals_asgn?
|
|
58
58
|
|
|
59
|
-
node.each_child_node
|
|
59
|
+
node.each_child_node do |child|
|
|
60
|
+
next if scope_body?(node, child)
|
|
61
|
+
|
|
62
|
+
traverse_node(child, &block)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# An assignment inside a block or method body within the condition belongs to
|
|
67
|
+
# that inner scope rather than the condition itself, so it is not inspected.
|
|
68
|
+
def scope_body?(node, child)
|
|
69
|
+
node.type?(:any_block, :any_def) && child == node.body
|
|
60
70
|
end
|
|
61
71
|
|
|
62
72
|
def all_literals?(node)
|
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
|
24
24
|
MSG = 'Literal interpolation detected.'
|
|
25
25
|
COMPOSITE = %i[array hash pair irange erange].freeze
|
|
26
26
|
|
|
27
|
-
# rubocop:disable Metrics/AbcSize
|
|
27
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
28
28
|
def on_interpolation(begin_node)
|
|
29
29
|
final_node = begin_node.children.last
|
|
30
30
|
return unless offending?(final_node)
|
|
@@ -50,7 +50,6 @@ module RuboCop
|
|
|
50
50
|
corrector.replace(final_node.parent, replacement)
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
|
-
# rubocop:enable Metrics/AbcSize
|
|
54
53
|
|
|
55
54
|
private
|
|
56
55
|
|
|
@@ -66,7 +65,7 @@ module RuboCop
|
|
|
66
65
|
|
|
67
66
|
def special_keyword?(node)
|
|
68
67
|
# handle strings like __FILE__
|
|
69
|
-
(node.str_type? && !node.loc
|
|
68
|
+
(node.str_type? && !node.loc?(:begin)) || node.source_range.is?('__LINE__')
|
|
70
69
|
end
|
|
71
70
|
|
|
72
71
|
def array_in_regexp?(node)
|
|
@@ -74,7 +73,7 @@ module RuboCop
|
|
|
74
73
|
node.array_type? && grandparent.regexp_type?
|
|
75
74
|
end
|
|
76
75
|
|
|
77
|
-
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
76
|
+
# rubocop:disable-next Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
78
77
|
def autocorrected_value(node)
|
|
79
78
|
case node.type
|
|
80
79
|
when :int
|
|
@@ -95,7 +94,6 @@ module RuboCop
|
|
|
95
94
|
node.source.gsub('"', '\"')
|
|
96
95
|
end
|
|
97
96
|
end
|
|
98
|
-
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
99
97
|
|
|
100
98
|
def handle_special_regexp_chars(begin_node, value)
|
|
101
99
|
parent_node = begin_node.parent
|
|
@@ -119,11 +117,13 @@ module RuboCop
|
|
|
119
117
|
end
|
|
120
118
|
|
|
121
119
|
def autocorrected_value_for_string(node)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
return node.source.delete_prefix('"').delete_suffix('"') unless node.value.valid_encoding?
|
|
121
|
+
|
|
122
|
+
escape_string_content(node.children.last)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def escape_string_content(string)
|
|
126
|
+
string.gsub(/[\\"]|#(?=[@{$])/, '\\\\\&')
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
def autocorrected_value_for_symbol(node)
|
|
@@ -134,12 +134,7 @@ module RuboCop
|
|
|
134
134
|
end
|
|
135
135
|
|
|
136
136
|
def autocorrected_value_in_hash_for_symbol(node)
|
|
137
|
-
|
|
138
|
-
if / |"|'/.match?(node.value.to_s)
|
|
139
|
-
":\\\"#{node.value.to_s.gsub('"') { '\\\\\"' }}\\\""
|
|
140
|
-
else
|
|
141
|
-
":#{node.value}"
|
|
142
|
-
end
|
|
137
|
+
escape_string_content(node.value.inspect)
|
|
143
138
|
end
|
|
144
139
|
|
|
145
140
|
def autocorrected_value_for_array(node)
|
|
@@ -158,7 +153,7 @@ module RuboCop
|
|
|
158
153
|
"{#{hash_string}}"
|
|
159
154
|
end
|
|
160
155
|
|
|
161
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
156
|
+
# rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize
|
|
162
157
|
def autocorrected_value_in_hash(node)
|
|
163
158
|
case node.type
|
|
164
159
|
when :int
|
|
@@ -166,7 +161,7 @@ module RuboCop
|
|
|
166
161
|
when :float
|
|
167
162
|
node.children.last.to_f.to_s
|
|
168
163
|
when :str
|
|
169
|
-
|
|
164
|
+
escape_string_content(node.value.inspect)
|
|
170
165
|
when :sym
|
|
171
166
|
autocorrected_value_in_hash_for_symbol(node)
|
|
172
167
|
when :array
|
|
@@ -177,7 +172,6 @@ module RuboCop
|
|
|
177
172
|
node.source.gsub('"', '\"')
|
|
178
173
|
end
|
|
179
174
|
end
|
|
180
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
|
181
175
|
|
|
182
176
|
# Does node print its own source when converted to a string?
|
|
183
177
|
def prints_as_self?(node)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Lint
|
|
6
|
+
# Checks for magic comments placed where Ruby silently ignores them.
|
|
7
|
+
#
|
|
8
|
+
# The `encoding` magic comment is only honored on the first line of a file,
|
|
9
|
+
# or on the second line when the first line is a shebang. Anywhere else it
|
|
10
|
+
# is silently ignored - even directly below another comment or a blank line.
|
|
11
|
+
#
|
|
12
|
+
# Other magic comments (such as `frozen_string_literal`) are honored
|
|
13
|
+
# anywhere before the first token of code, but are ignored after any code,
|
|
14
|
+
# with a warning emitted only when running Ruby with `-w`.
|
|
15
|
+
#
|
|
16
|
+
# A magic comment misplaced ahead of a shebang also renders the shebang
|
|
17
|
+
# ineffective, since a shebang is only recognized on the first line.
|
|
18
|
+
#
|
|
19
|
+
# NOTE: An `encoding` comment that is only preceded by other magic
|
|
20
|
+
# comments is not flagged by this cop; that case is handled by
|
|
21
|
+
# `Lint/OrderedMagicComments`. `shareable_constant_value` is never
|
|
22
|
+
# flagged, as Ruby intentionally allows it mid-file with block scoping.
|
|
23
|
+
#
|
|
24
|
+
# @safety
|
|
25
|
+
# This cop's autocorrection is unsafe because moving the magic comment
|
|
26
|
+
# to its effective position activates it, which changes runtime
|
|
27
|
+
# behavior (e.g. the source encoding or string mutability).
|
|
28
|
+
#
|
|
29
|
+
# @example
|
|
30
|
+
# # bad
|
|
31
|
+
# # Documentation comment
|
|
32
|
+
# # encoding: ascii-8bit
|
|
33
|
+
# puts 'hello'
|
|
34
|
+
#
|
|
35
|
+
# # good
|
|
36
|
+
# # encoding: ascii-8bit
|
|
37
|
+
# # Documentation comment
|
|
38
|
+
# puts 'hello'
|
|
39
|
+
#
|
|
40
|
+
# # bad
|
|
41
|
+
# require 'foo'
|
|
42
|
+
# # frozen_string_literal: true
|
|
43
|
+
#
|
|
44
|
+
# # good
|
|
45
|
+
# # frozen_string_literal: true
|
|
46
|
+
# require 'foo'
|
|
47
|
+
#
|
|
48
|
+
# # bad
|
|
49
|
+
# # frozen_string_literal: true
|
|
50
|
+
# #!/usr/bin/env ruby
|
|
51
|
+
# puts 'hello'
|
|
52
|
+
#
|
|
53
|
+
# # good
|
|
54
|
+
# #!/usr/bin/env ruby
|
|
55
|
+
# # frozen_string_literal: true
|
|
56
|
+
# puts 'hello'
|
|
57
|
+
class MisplacedMagicComment < Base
|
|
58
|
+
include RangeHelp
|
|
59
|
+
extend AutoCorrector
|
|
60
|
+
|
|
61
|
+
MSG_ENCODING = 'The `encoding` magic comment is ignored unless placed on the first ' \
|
|
62
|
+
'line (or below a shebang on the first line).'
|
|
63
|
+
MSG_AFTER_CODE = 'The `%<directive>s` magic comment is ignored after any code.'
|
|
64
|
+
MSG_ABOVE_SHEBANG = 'A magic comment above a shebang renders the shebang ineffective.'
|
|
65
|
+
|
|
66
|
+
def on_new_investigation
|
|
67
|
+
return if processed_source.buffer.source.empty?
|
|
68
|
+
|
|
69
|
+
check_magic_comment_above_shebang
|
|
70
|
+
processed_source.comments.each { |comment| check_comment(comment) }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def check_comment(comment)
|
|
76
|
+
return unless magic_comment_shaped?(comment.text)
|
|
77
|
+
|
|
78
|
+
magic_comment = MagicComment.parse(comment.text)
|
|
79
|
+
return unless magic_comment.valid?
|
|
80
|
+
|
|
81
|
+
if magic_comment.encoding_specified?
|
|
82
|
+
return unless known_encoding?(magic_comment.encoding)
|
|
83
|
+
|
|
84
|
+
check_encoding_comment(comment)
|
|
85
|
+
elsif magic_comment.frozen_string_literal_specified?
|
|
86
|
+
check_top_block_comment(comment, 'frozen_string_literal')
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# The Emacs and Vim regexps in `MagicComment` match anywhere inside a
|
|
91
|
+
# comment, which would flag documentation that merely quotes a magic
|
|
92
|
+
# comment (e.g. `# # -*- coding: UTF-8 -*-`). Require the magic
|
|
93
|
+
# comment to start right after the `#`.
|
|
94
|
+
def magic_comment_shaped?(text)
|
|
95
|
+
/\A#(?![^#]*#)/.match?(text)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Prose that happens to open with `Encoding:` parses as an encoding
|
|
99
|
+
# comment (`# Encoding: force given encoding` yields `force`). Ruby
|
|
100
|
+
# ignores a misplaced encoding comment entirely, so a name no encoding
|
|
101
|
+
# answers to means the line is a comment, not a directive.
|
|
102
|
+
def known_encoding?(name)
|
|
103
|
+
Encoding.find(name)
|
|
104
|
+
true
|
|
105
|
+
rescue ArgumentError
|
|
106
|
+
false
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def shebang?
|
|
110
|
+
processed_source.lines.first.to_s.start_with?('#!')
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# First line that may carry an effective encoding comment.
|
|
114
|
+
def effective_encoding_line
|
|
115
|
+
shebang? ? 2 : 1
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def first_code_token
|
|
119
|
+
@first_code_token ||= processed_source.sorted_tokens.find { |token| !token.comment? }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def check_encoding_comment(comment)
|
|
123
|
+
line = comment.source_range.line
|
|
124
|
+
return if line == effective_encoding_line && comment_starts_line?(comment)
|
|
125
|
+
# Leave `# frozen_string_literal: true` + `# encoding: x` runs at the
|
|
126
|
+
# very top to Lint/OrderedMagicComments, which already reorders them.
|
|
127
|
+
return if preceded_only_by_magic_comments?(comment)
|
|
128
|
+
|
|
129
|
+
add_offense(comment, message: MSG_ENCODING) do |corrector|
|
|
130
|
+
move_comment(corrector, comment, effective_encoding_line)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def check_top_block_comment(comment, directive)
|
|
135
|
+
return unless first_code_token
|
|
136
|
+
return unless comment.source_range.begin_pos > first_code_token.begin_pos
|
|
137
|
+
|
|
138
|
+
message = format(MSG_AFTER_CODE, directive: directive)
|
|
139
|
+
add_offense(comment, message: message) do |corrector|
|
|
140
|
+
move_comment(corrector, comment, effective_encoding_line)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def check_magic_comment_above_shebang
|
|
145
|
+
shebang_comment = processed_source.comments.find do |comment|
|
|
146
|
+
comment.source_range.line > 1 && comment.text.start_with?('#!') &&
|
|
147
|
+
comment.source_range.column.zero?
|
|
148
|
+
end
|
|
149
|
+
return unless shebang_comment
|
|
150
|
+
# Only flag when what precedes the shebang is magic comments -
|
|
151
|
+
# a `#!` comment deep inside a file is not an intended shebang.
|
|
152
|
+
return unless preceded_only_by_magic_comments?(shebang_comment)
|
|
153
|
+
|
|
154
|
+
add_offense(shebang_comment, message: MSG_ABOVE_SHEBANG)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def preceded_only_by_magic_comments?(comment)
|
|
158
|
+
(1...comment.source_range.line).all? do |line_number|
|
|
159
|
+
text = processed_source.lines[line_number - 1]
|
|
160
|
+
(line_number == 1 && text.start_with?('#!')) || MagicComment.parse(text).valid?
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def comment_starts_line?(comment)
|
|
165
|
+
processed_source.lines[comment.source_range.line - 1].lstrip.start_with?('#')
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def move_comment(corrector, comment, target_line)
|
|
169
|
+
removal_range = if comment_starts_line?(comment)
|
|
170
|
+
range_by_whole_lines(comment.source_range, include_final_newline: true)
|
|
171
|
+
else
|
|
172
|
+
range_with_surrounding_space(comment.source_range, side: :left)
|
|
173
|
+
end
|
|
174
|
+
corrector.remove(removal_range)
|
|
175
|
+
target_range = processed_source.buffer.line_range(target_line)
|
|
176
|
+
if comment.source_range.line < target_line
|
|
177
|
+
corrector.insert_after(target_range, "\n#{comment.text}")
|
|
178
|
+
else
|
|
179
|
+
corrector.insert_before(target_range, "#{comment.text}\n")
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|