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
|
@@ -9,7 +9,20 @@ module RuboCop
|
|
|
9
9
|
# On the other hand, `ENV.fetch` raises `KeyError` or returns the explicitly
|
|
10
10
|
# specified default value.
|
|
11
11
|
#
|
|
12
|
-
# @example
|
|
12
|
+
# @example DefaultToNil: true (default)
|
|
13
|
+
# # bad
|
|
14
|
+
# ENV['X']
|
|
15
|
+
# x = ENV['X']
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# ENV.fetch('X', nil)
|
|
19
|
+
# x = ENV.fetch('X', nil)
|
|
20
|
+
#
|
|
21
|
+
# # also good
|
|
22
|
+
# !ENV['X']
|
|
23
|
+
# ENV['X'].some_method # (e.g. `.nil?`)
|
|
24
|
+
#
|
|
25
|
+
# @example DefaultToNil: false
|
|
13
26
|
# # bad
|
|
14
27
|
# ENV['X']
|
|
15
28
|
# x = ENV['X']
|
|
@@ -25,7 +38,8 @@ module RuboCop
|
|
|
25
38
|
class FetchEnvVar < Base
|
|
26
39
|
extend AutoCorrector
|
|
27
40
|
|
|
28
|
-
|
|
41
|
+
MSG_WITH_NIL = 'Use `ENV.fetch(%<key>s, nil)` instead of `ENV[%<key>s]`.'
|
|
42
|
+
MSG_WITHOUT_NIL = 'Use `ENV.fetch(%<key>s)` instead of `ENV[%<key>s]`.'
|
|
29
43
|
RESTRICT_ON_SEND = [:[]].freeze
|
|
30
44
|
|
|
31
45
|
# @!method env_with_bracket?(node)
|
|
@@ -37,7 +51,7 @@ module RuboCop
|
|
|
37
51
|
env_with_bracket?(node) do |name_node|
|
|
38
52
|
break unless offensive?(node)
|
|
39
53
|
|
|
40
|
-
message = format(
|
|
54
|
+
message = format(offense_message, key: name_node.source)
|
|
41
55
|
add_offense(node, message: message) do |corrector|
|
|
42
56
|
corrector.replace(node, new_code(name_node))
|
|
43
57
|
end
|
|
@@ -46,19 +60,27 @@ module RuboCop
|
|
|
46
60
|
|
|
47
61
|
private
|
|
48
62
|
|
|
63
|
+
def default_to_nil?
|
|
64
|
+
cop_config.fetch('DefaultToNil', true)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def offense_message
|
|
68
|
+
default_to_nil? ? MSG_WITH_NIL : MSG_WITHOUT_NIL
|
|
69
|
+
end
|
|
70
|
+
|
|
49
71
|
def allowed_var?(node)
|
|
50
72
|
env_key_node = node.children.last
|
|
51
|
-
env_key_node.str_type? && cop_config['
|
|
73
|
+
env_key_node.str_type? && cop_config['AllowedVariables'].include?(env_key_node.value)
|
|
52
74
|
end
|
|
53
75
|
|
|
54
76
|
def used_as_flag?(node)
|
|
55
77
|
return false if node.root?
|
|
56
|
-
return true if used_if_condition_in_body(node)
|
|
78
|
+
return true if used_if_condition_in_body?(node)
|
|
57
79
|
|
|
58
80
|
node.parent.send_type? && (node.parent.prefix_bang? || node.parent.comparison_method?)
|
|
59
81
|
end
|
|
60
82
|
|
|
61
|
-
def used_if_condition_in_body(node)
|
|
83
|
+
def used_if_condition_in_body?(node)
|
|
62
84
|
if_node = node.ancestors.find(&:if_type?)
|
|
63
85
|
|
|
64
86
|
return false unless (condition = if_node&.condition)
|
|
@@ -125,7 +147,11 @@ module RuboCop
|
|
|
125
147
|
end
|
|
126
148
|
|
|
127
149
|
def new_code(name_node)
|
|
128
|
-
|
|
150
|
+
if default_to_nil?
|
|
151
|
+
"ENV.fetch(#{name_node.source}, nil)"
|
|
152
|
+
else
|
|
153
|
+
"ENV.fetch(#{name_node.source})"
|
|
154
|
+
end
|
|
129
155
|
end
|
|
130
156
|
end
|
|
131
157
|
end
|
|
@@ -54,7 +54,7 @@ module RuboCop
|
|
|
54
54
|
@contain_dev_null_string_in_file = ast.each_descendant(:str).any? do |str|
|
|
55
55
|
content = str.str_content
|
|
56
56
|
|
|
57
|
-
valid_string?(content) && content.downcase == '/dev/null' # rubocop:disable Style/FileNull
|
|
57
|
+
valid_string?(content) && content.downcase == '/dev/null' # rubocop:disable Style/FileNull -- the cop needs the literal it is matching
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -62,7 +62,7 @@ module RuboCop
|
|
|
62
62
|
value = node.value
|
|
63
63
|
return unless valid_string?(value)
|
|
64
64
|
return if acceptable?(node)
|
|
65
|
-
return if value.downcase == 'nul' && !@contain_dev_null_string_in_file # rubocop:disable Style/FileNull
|
|
65
|
+
return if value.downcase == 'nul' && !@contain_dev_null_string_in_file # rubocop:disable Style/FileNull -- the cop needs the literal it is matching
|
|
66
66
|
return unless REGEXP.match?(value)
|
|
67
67
|
|
|
68
68
|
add_offense(node, message: format(MSG, source: value)) do |corrector|
|
|
@@ -78,10 +78,12 @@ module RuboCop
|
|
|
78
78
|
|
|
79
79
|
def acceptable?(node)
|
|
80
80
|
# Using a hardcoded null device is acceptable when inside an array or
|
|
81
|
-
# inside a hash to ensure behavior doesn't change.
|
|
81
|
+
# inside a hash to ensure behavior doesn't change. A `str` that is part of
|
|
82
|
+
# an interpolated or concatenated string (`dstr`) is not a standalone null
|
|
83
|
+
# device either, and replacing it would corrupt the surrounding string.
|
|
82
84
|
return false unless node.parent
|
|
83
85
|
|
|
84
|
-
node.parent.type?(:array, :pair)
|
|
86
|
+
node.parent.type?(:array, :pair, :dstr)
|
|
85
87
|
end
|
|
86
88
|
end
|
|
87
89
|
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for `File.open` without a block, which can leak file descriptors.
|
|
7
|
+
#
|
|
8
|
+
# When `File.open` is called without a block, the caller is responsible
|
|
9
|
+
# for closing the file descriptor. If it is not explicitly closed, it
|
|
10
|
+
# will only be closed when the garbage collector runs, which may lead
|
|
11
|
+
# to resource exhaustion. Using the block form ensures the file is
|
|
12
|
+
# automatically closed when the block exits.
|
|
13
|
+
#
|
|
14
|
+
# This cop only registers an offense when the result of `File.open` is
|
|
15
|
+
# assigned to a variable or has a method chained on it, as those are the
|
|
16
|
+
# clearest indicators that the block form should be used instead. When
|
|
17
|
+
# `File.open` is used as a return value or passed as an argument, the
|
|
18
|
+
# caller is likely managing the file descriptor intentionally.
|
|
19
|
+
#
|
|
20
|
+
# @safety
|
|
21
|
+
# This cop is unsafe because it relies on syntax heuristics and cannot
|
|
22
|
+
# verify whether the file descriptor is safely managed. For example, it
|
|
23
|
+
# still flags intentional one-shot reads (`File.open("f").read`) where
|
|
24
|
+
# the file descriptor is closed by the garbage collector.
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
# # bad
|
|
28
|
+
# f = File.open('file')
|
|
29
|
+
#
|
|
30
|
+
# # bad
|
|
31
|
+
# File.open('file').read
|
|
32
|
+
#
|
|
33
|
+
# # good
|
|
34
|
+
# File.open('file') do |f|
|
|
35
|
+
# f.read
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# # good
|
|
39
|
+
# File.open('file', &:read)
|
|
40
|
+
#
|
|
41
|
+
# # good - pass an open file object to an API that manages its lifecycle
|
|
42
|
+
# process(io: File.open('file'))
|
|
43
|
+
#
|
|
44
|
+
# # good - return an open file object for the caller to manage
|
|
45
|
+
# def json_key_io
|
|
46
|
+
# File.open('file')
|
|
47
|
+
# end
|
|
48
|
+
#
|
|
49
|
+
# # good - use File.read for one-shot reads
|
|
50
|
+
# File.read('file')
|
|
51
|
+
#
|
|
52
|
+
class FileOpen < Base
|
|
53
|
+
MSG = '`File.open` without a block may leak a file descriptor; use the block form.'
|
|
54
|
+
RESTRICT_ON_SEND = %i[open].freeze
|
|
55
|
+
|
|
56
|
+
# @!method file_open?(node)
|
|
57
|
+
def_node_matcher :file_open?, <<~PATTERN
|
|
58
|
+
(send (const {nil? cbase} :File) :open ...)
|
|
59
|
+
PATTERN
|
|
60
|
+
|
|
61
|
+
def on_send(node)
|
|
62
|
+
return unless file_open?(node)
|
|
63
|
+
return if node.block_argument?
|
|
64
|
+
return unless offensive_usage?(node)
|
|
65
|
+
|
|
66
|
+
add_offense(node)
|
|
67
|
+
end
|
|
68
|
+
alias on_csend on_send
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def offensive_usage?(node)
|
|
73
|
+
return true unless node.value_used?
|
|
74
|
+
|
|
75
|
+
node.parent.lvasgn_type? || receiver_of_chained_call?(node)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def receiver_of_chained_call?(node)
|
|
79
|
+
node.parent.receiver == node
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -104,28 +104,33 @@ module RuboCop
|
|
|
104
104
|
|
|
105
105
|
def replacement(mode, filename, content, write_node)
|
|
106
106
|
replacement = "#{write_method(mode)}(#{filename.source}, #{content.source})"
|
|
107
|
+
heredocs = removed_heredocs(filename, content, write_node)
|
|
108
|
+
return replacement if heredocs.empty?
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
[replacement, *heredocs.map { |heredoc| heredoc_range(heredoc).source }].join("\n")
|
|
111
|
+
end
|
|
110
112
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
# Heredocs opened in the arguments keep working in the replacement, but their
|
|
114
|
+
# bodies are lost when they lie within the replaced range, so they need to be
|
|
115
|
+
# restored after the replacement.
|
|
116
|
+
def removed_heredocs(filename, content, write_node)
|
|
117
|
+
[filename, content].flat_map { |argument| find_heredocs(argument) }
|
|
118
|
+
.select { |heredoc| removed?(heredoc, write_node) }
|
|
119
|
+
.sort_by { |heredoc| heredoc.loc.heredoc_body.begin_pos }
|
|
118
120
|
end
|
|
119
121
|
|
|
120
|
-
def heredoc
|
|
121
|
-
|
|
122
|
-
first_argument.respond_to?(:heredoc?) && first_argument.heredoc?
|
|
122
|
+
def heredoc_range(heredoc)
|
|
123
|
+
range_between(heredoc.loc.heredoc_body.begin_pos, heredoc.loc.heredoc_end.end_pos)
|
|
123
124
|
end
|
|
124
125
|
|
|
125
|
-
def
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
def find_heredocs(node)
|
|
127
|
+
[node, *node.each_descendant(:any_str)].select do |child|
|
|
128
|
+
child.respond_to?(:heredoc?) && child.heredoc?
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def removed?(heredoc, write_node)
|
|
133
|
+
heredoc.loc.heredoc_end.end_pos <= write_node.source_range.end_pos
|
|
129
134
|
end
|
|
130
135
|
end
|
|
131
136
|
end
|
|
@@ -7,9 +7,12 @@ module RuboCop
|
|
|
7
7
|
# It is recommended to either always use `fdiv` or coerce one side only.
|
|
8
8
|
# This cop also provides other options for code consistency.
|
|
9
9
|
#
|
|
10
|
+
# For `Regexp.last_match` and nth reference (e.g., `$1`), it assumes that the value
|
|
11
|
+
# is a string matched by a regular expression, and allows conversion with `#to_f`.
|
|
12
|
+
#
|
|
10
13
|
# @safety
|
|
11
14
|
# This cop is unsafe, because if the operand variable is a string object
|
|
12
|
-
# then
|
|
15
|
+
# then `#to_f` will be removed and an error will occur.
|
|
13
16
|
#
|
|
14
17
|
# [source,ruby]
|
|
15
18
|
# ----
|
|
@@ -84,6 +87,14 @@ module RuboCop
|
|
|
84
87
|
(send !nil? :to_f)
|
|
85
88
|
PATTERN
|
|
86
89
|
|
|
90
|
+
# @!method regexp_last_match?(node)
|
|
91
|
+
def_node_matcher :regexp_last_match?, <<~PATTERN
|
|
92
|
+
{
|
|
93
|
+
(send (const {nil? cbase} :Regexp) :last_match int)
|
|
94
|
+
(:nth_ref _)
|
|
95
|
+
}
|
|
96
|
+
PATTERN
|
|
97
|
+
|
|
87
98
|
def on_send(node)
|
|
88
99
|
return unless offense_condition?(node)
|
|
89
100
|
|
|
@@ -96,7 +107,7 @@ module RuboCop
|
|
|
96
107
|
remove_to_f_method(corrector, node.receiver)
|
|
97
108
|
add_to_f_method(corrector, node.first_argument)
|
|
98
109
|
when :fdiv
|
|
99
|
-
correct_from_slash_to_fdiv(corrector, node
|
|
110
|
+
correct_from_slash_to_fdiv(corrector, node.receiver, node.first_argument)
|
|
100
111
|
end
|
|
101
112
|
end
|
|
102
113
|
end
|
|
@@ -104,6 +115,9 @@ module RuboCop
|
|
|
104
115
|
private
|
|
105
116
|
|
|
106
117
|
def offense_condition?(node)
|
|
118
|
+
return false if regexp_last_match?(node.receiver.receiver) ||
|
|
119
|
+
regexp_last_match?(node.first_argument.receiver)
|
|
120
|
+
|
|
107
121
|
case style
|
|
108
122
|
when :left_coerce
|
|
109
123
|
right_coerce?(node)
|
|
@@ -131,23 +145,17 @@ module RuboCop
|
|
|
131
145
|
corrector.remove(send_node.loc.selector)
|
|
132
146
|
end
|
|
133
147
|
|
|
134
|
-
def correct_from_slash_to_fdiv(corrector,
|
|
135
|
-
|
|
136
|
-
argument_source = extract_receiver_source(argument)
|
|
148
|
+
def correct_from_slash_to_fdiv(corrector, receiver, argument)
|
|
149
|
+
remove_to_f_method(corrector, receiver) if to_f_method?(receiver)
|
|
137
150
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
151
|
+
argument_parenthesized = argument.begin_type?
|
|
152
|
+
corrector.replace(
|
|
153
|
+
receiver.source_range.end.join(argument.source_range.begin),
|
|
154
|
+
argument_parenthesized ? '.fdiv' : '.fdiv('
|
|
155
|
+
)
|
|
141
156
|
|
|
142
|
-
corrector
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def extract_receiver_source(node)
|
|
146
|
-
if node.send_type? && node.method?(:to_f)
|
|
147
|
-
node.receiver.source
|
|
148
|
-
else
|
|
149
|
-
node.source
|
|
150
|
-
end
|
|
157
|
+
remove_to_f_method(corrector, argument) if to_f_method?(argument)
|
|
158
|
+
corrector.insert_after(argument, ')') unless argument_parenthesized
|
|
151
159
|
end
|
|
152
160
|
end
|
|
153
161
|
end
|
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
|
8
8
|
# parameter. An `each` call with a block on a single line is always
|
|
9
9
|
# allowed.
|
|
10
10
|
#
|
|
11
|
+
# NOTE: `each` is preferred in idiomatic Ruby because `for` leaks
|
|
12
|
+
# its loop variable into the surrounding scope.
|
|
13
|
+
#
|
|
11
14
|
# @example EnforcedStyle: each (default)
|
|
12
15
|
# # bad
|
|
13
16
|
# def foo
|
|
@@ -66,6 +69,7 @@ module RuboCop
|
|
|
66
69
|
|
|
67
70
|
if style == :for
|
|
68
71
|
return unless node.receiver
|
|
72
|
+
return if rescue_or_ensure_body?(node)
|
|
69
73
|
|
|
70
74
|
add_offense(node, message: PREFER_FOR) do |corrector|
|
|
71
75
|
EachToForCorrector.new(node).call(corrector)
|
|
@@ -77,12 +81,17 @@ module RuboCop
|
|
|
77
81
|
end
|
|
78
82
|
|
|
79
83
|
alias on_numblock on_block
|
|
84
|
+
alias on_itblock on_block
|
|
80
85
|
|
|
81
86
|
private
|
|
82
87
|
|
|
83
88
|
def suspect_enumerable?(node)
|
|
84
89
|
node.multiline? && node.method?(:each) && !node.send_node.arguments?
|
|
85
90
|
end
|
|
91
|
+
|
|
92
|
+
def rescue_or_ensure_body?(node)
|
|
93
|
+
node.body&.type?(:rescue, :ensure)
|
|
94
|
+
end
|
|
86
95
|
end
|
|
87
96
|
end
|
|
88
97
|
end
|
|
@@ -11,9 +11,10 @@ module RuboCop
|
|
|
11
11
|
# if the first argument is a string literal and if the second
|
|
12
12
|
# argument is an array literal.
|
|
13
13
|
#
|
|
14
|
-
# Autocorrection will be applied when
|
|
15
|
-
#
|
|
16
|
-
# provided that their return value is not an array.
|
|
14
|
+
# Autocorrection will be applied when the argument is a literal or uses a known
|
|
15
|
+
# built-in conversion method such as `to_d`, `to_f`, `to_h`, `to_i`, `to_r`, `to_s`,
|
|
16
|
+
# and `to_sym` on variables, provided that their return value is not an array.
|
|
17
|
+
# For example, when using `to_s`,
|
|
17
18
|
# `'%s' % [1, 2, 3].to_s` can be autocorrected without any incompatibility:
|
|
18
19
|
#
|
|
19
20
|
# [source,ruby]
|
|
@@ -143,10 +144,22 @@ module RuboCop
|
|
|
143
144
|
end
|
|
144
145
|
|
|
145
146
|
def format_single_parameter(arg)
|
|
147
|
+
# `format(fmt, *args)` is equivalent to `fmt % args`, so unwrap the splat
|
|
148
|
+
# and render the argument it splats.
|
|
149
|
+
return format_single_parameter(arg.children.first) if arg.splat_type?
|
|
150
|
+
|
|
146
151
|
source = arg.source
|
|
147
152
|
return "{ #{source} }" if arg.hash_type?
|
|
148
153
|
|
|
149
|
-
|
|
154
|
+
requires_parentheses?(arg) ? "(#{source})" : source
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# An argument that binds looser than `%` (a ternary, range, assignment, or
|
|
158
|
+
# operator call) must be parenthesized to keep its meaning.
|
|
159
|
+
def requires_parentheses?(arg)
|
|
160
|
+
return true if arg.assignment? || arg.type?(:if, :and, :or, :range)
|
|
161
|
+
|
|
162
|
+
arg.send_type? && arg.operator_method? && !arg.parenthesized?
|
|
150
163
|
end
|
|
151
164
|
end
|
|
152
165
|
end
|
|
@@ -3,16 +3,29 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Use a consistent style for
|
|
6
|
+
# Use a consistent style for tokens within a format string.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
# The reason is that _unannotated_ format is very similar
|
|
12
|
-
# to encoded URLs or Date/Time formatting strings.
|
|
8
|
+
# By default, all strings are evaluated. In some cases, this may be undesirable,
|
|
9
|
+
# as they could be used as arguments to a method that does not consider
|
|
10
|
+
# them to be tokens, but rather other identifiers or just part of the string.
|
|
13
11
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
12
|
+
# `AllowedMethods` or `AllowedPatterns` can be configured with in order to mark specific
|
|
13
|
+
# methods as always allowed, thereby avoiding an offense from the cop. By default, there
|
|
14
|
+
# are no allowed methods.
|
|
15
|
+
#
|
|
16
|
+
# Additionally, the cop can be made conservative by configuring it with
|
|
17
|
+
# `Mode: conservative` (default `aggressive`). In this mode, tokens (regardless
|
|
18
|
+
# of `EnforcedStyle`) are only considered if used in the format string argument to the
|
|
19
|
+
# methods `printf`, `sprintf`, `format` and `%`.
|
|
20
|
+
#
|
|
21
|
+
# NOTE: In `aggressive` mode, offenses are registered for all strings containing tokens,
|
|
22
|
+
# but autocorrection is only applied when the string appears in a known formatting context
|
|
23
|
+
# (`format`, `sprintf`, `printf`, or `%`). This is done in order to prevent false
|
|
24
|
+
# autocorrections for strings that are not actually format strings.
|
|
25
|
+
#
|
|
26
|
+
# NOTE: Tokens in the `unannotated` style (eg. `%s`) are always treated as if
|
|
27
|
+
# configured with `Conservative: true`. This is done in order to prevent false positives,
|
|
28
|
+
# because this format is very similar to encoded URLs or Date/Time formatting strings.
|
|
16
29
|
#
|
|
17
30
|
# @example EnforcedStyle: annotated (default)
|
|
18
31
|
#
|
|
@@ -82,6 +95,42 @@ module RuboCop
|
|
|
82
95
|
# # good
|
|
83
96
|
# redirect('foo/%{bar_id}')
|
|
84
97
|
#
|
|
98
|
+
# @example Mode: aggressive (default), EnforcedStyle: annotated
|
|
99
|
+
#
|
|
100
|
+
# # bad
|
|
101
|
+
# "%{greeting}"
|
|
102
|
+
# foo("%{greeting}")
|
|
103
|
+
#
|
|
104
|
+
# # bad
|
|
105
|
+
# format("%{greeting}", greeting: 'Hello')
|
|
106
|
+
# printf("%{greeting}", greeting: 'Hello')
|
|
107
|
+
# sprintf("%{greeting}", greeting: 'Hello')
|
|
108
|
+
# "%{greeting}" % { greeting: 'Hello' }
|
|
109
|
+
#
|
|
110
|
+
# # good
|
|
111
|
+
# format("%<greeting>s", greeting: 'Hello')
|
|
112
|
+
# printf("%<greeting>s", greeting: 'Hello')
|
|
113
|
+
# sprintf("%<greeting>s", greeting: 'Hello')
|
|
114
|
+
# "%<greeting>s" % { greeting: 'Hello' }
|
|
115
|
+
#
|
|
116
|
+
# @example Mode: conservative, EnforcedStyle: annotated
|
|
117
|
+
#
|
|
118
|
+
# # good
|
|
119
|
+
# "%{greeting}"
|
|
120
|
+
# foo("%{greeting}")
|
|
121
|
+
#
|
|
122
|
+
# # bad
|
|
123
|
+
# format("%{greeting}", greeting: 'Hello')
|
|
124
|
+
# printf("%{greeting}", greeting: 'Hello')
|
|
125
|
+
# sprintf("%{greeting}", greeting: 'Hello')
|
|
126
|
+
# "%{greeting}" % { greeting: 'Hello' }
|
|
127
|
+
#
|
|
128
|
+
# # good
|
|
129
|
+
# format("%<greeting>s", greeting: 'Hello')
|
|
130
|
+
# printf("%<greeting>s", greeting: 'Hello')
|
|
131
|
+
# sprintf("%<greeting>s", greeting: 'Hello')
|
|
132
|
+
# "%<greeting>s" % { greeting: 'Hello' }
|
|
133
|
+
#
|
|
85
134
|
class FormatStringToken < Base
|
|
86
135
|
include ConfigurableEnforcedStyle
|
|
87
136
|
include AllowedMethods
|
|
@@ -96,7 +145,7 @@ module RuboCop
|
|
|
96
145
|
return if allowed_unannotated?(detections)
|
|
97
146
|
|
|
98
147
|
detections.each do |detected_sequence, token_range|
|
|
99
|
-
check_sequence(detected_sequence, token_range)
|
|
148
|
+
check_sequence(node, detected_sequence, token_range)
|
|
100
149
|
end
|
|
101
150
|
end
|
|
102
151
|
|
|
@@ -121,17 +170,34 @@ module RuboCop
|
|
|
121
170
|
matches_allowed_pattern?(send_parent.method_name))
|
|
122
171
|
end
|
|
123
172
|
|
|
124
|
-
def check_sequence(detected_sequence, token_range)
|
|
173
|
+
def check_sequence(node, detected_sequence, token_range)
|
|
125
174
|
if detected_sequence.style == style
|
|
126
175
|
correct_style_detected
|
|
127
176
|
elsif correctable_sequence?(detected_sequence.type)
|
|
128
177
|
style_detected(detected_sequence.style)
|
|
129
|
-
|
|
178
|
+
register_offense(node, detected_sequence, token_range)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def register_offense(node, detected_sequence, token_range)
|
|
183
|
+
msg = message(detected_sequence.style)
|
|
184
|
+
|
|
185
|
+
if format_string_context?(node)
|
|
186
|
+
add_offense(token_range, message: msg) do |corrector|
|
|
130
187
|
autocorrect_sequence(corrector, detected_sequence, token_range)
|
|
131
188
|
end
|
|
189
|
+
else
|
|
190
|
+
add_offense(token_range, message: msg)
|
|
132
191
|
end
|
|
133
192
|
end
|
|
134
193
|
|
|
194
|
+
def format_string_context?(node)
|
|
195
|
+
format_string_in_typical_context?(node) ||
|
|
196
|
+
node.each_ancestor(:dstr).any? do |dstr_node|
|
|
197
|
+
format_string_in_typical_context?(dstr_node)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
135
201
|
def correctable_sequence?(detected_type)
|
|
136
202
|
detected_type == 's' || style == :annotated || style == :unannotated
|
|
137
203
|
end
|
|
@@ -153,15 +219,16 @@ module RuboCop
|
|
|
153
219
|
corrector.replace(token_range, correction)
|
|
154
220
|
end
|
|
155
221
|
|
|
156
|
-
def
|
|
157
|
-
detected_style == :unannotated
|
|
222
|
+
def allowed_string?(node, detected_style)
|
|
223
|
+
(detected_style == :unannotated || conservative?) &&
|
|
224
|
+
!format_string_in_typical_context?(node)
|
|
158
225
|
end
|
|
159
226
|
|
|
160
227
|
def message(detected_style)
|
|
161
228
|
"Prefer #{message_text(style)} over #{message_text(detected_style)}."
|
|
162
229
|
end
|
|
163
230
|
|
|
164
|
-
# rubocop:disable Style/FormatStringToken
|
|
231
|
+
# rubocop:disable-next Style/FormatStringToken -- the cop needs the token style it is matching
|
|
165
232
|
def message_text(style)
|
|
166
233
|
{
|
|
167
234
|
annotated: 'annotated tokens (like `%<foo>s`)',
|
|
@@ -169,7 +236,6 @@ module RuboCop
|
|
|
169
236
|
unannotated: 'unannotated tokens (like `%s`)'
|
|
170
237
|
}[style]
|
|
171
238
|
end
|
|
172
|
-
# rubocop:enable Style/FormatStringToken
|
|
173
239
|
|
|
174
240
|
def tokens(str_node, &block)
|
|
175
241
|
return if str_node.source == '__FILE__'
|
|
@@ -203,7 +269,7 @@ module RuboCop
|
|
|
203
269
|
def collect_detections(node)
|
|
204
270
|
detections = []
|
|
205
271
|
tokens(node) do |detected_sequence, token_range|
|
|
206
|
-
unless
|
|
272
|
+
unless allowed_string?(node, detected_sequence.style)
|
|
207
273
|
detections << [detected_sequence, token_range]
|
|
208
274
|
end
|
|
209
275
|
end
|
|
@@ -222,6 +288,10 @@ module RuboCop
|
|
|
222
288
|
def max_unannotated_placeholders_allowed
|
|
223
289
|
cop_config['MaxUnannotatedPlaceholdersAllowed']
|
|
224
290
|
end
|
|
291
|
+
|
|
292
|
+
def conservative?
|
|
293
|
+
cop_config.fetch('Mode', :aggressive).to_sym == :conservative
|
|
294
|
+
end
|
|
225
295
|
end
|
|
226
296
|
end
|
|
227
297
|
end
|
|
@@ -151,7 +151,7 @@ module RuboCop
|
|
|
151
151
|
|
|
152
152
|
def frozen_string_literal_comment(processed_source)
|
|
153
153
|
processed_source.tokens.find do |token|
|
|
154
|
-
token.text.
|
|
154
|
+
MagicComment.parse(token.text).frozen_string_literal_specified?
|
|
155
155
|
end
|
|
156
156
|
end
|
|
157
157
|
|
|
@@ -189,8 +189,9 @@ module RuboCop
|
|
|
189
189
|
|
|
190
190
|
def enable_comment(corrector)
|
|
191
191
|
comment = frozen_string_literal_comment(processed_source)
|
|
192
|
+
replacement = MagicComment.parse(comment.text).new_frozen_string_literal(true)
|
|
192
193
|
|
|
193
|
-
corrector.replace(line_range(comment.line),
|
|
194
|
+
corrector.replace(line_range(comment.line), replacement)
|
|
194
195
|
end
|
|
195
196
|
|
|
196
197
|
def insert_comment(corrector)
|
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
|
8
8
|
# reassign (possibly to redirect some stream) constants in Ruby, you'll get
|
|
9
9
|
# an interpreter warning if you do so.
|
|
10
10
|
#
|
|
11
|
+
# Additionally, `$stdout/$stderr/$stdin` can safely be accessed in a Ractor because they
|
|
12
|
+
# are ractor-local, while `STDOUT/STDERR/STDIN` will raise `Ractor::IsolationError`.
|
|
13
|
+
#
|
|
11
14
|
# @safety
|
|
12
15
|
# Autocorrection is unsafe because `STDOUT` and `$stdout` may point to different
|
|
13
16
|
# objects, for example.
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Looks for uses of global variables.
|
|
6
|
+
# Looks for uses of global variables. Global variables introduce
|
|
7
|
+
# shared mutable state that makes code harder to test, debug,
|
|
8
|
+
# and reason about, since any part of the program can read or modify them.
|
|
9
|
+
#
|
|
7
10
|
# It does not report offenses for built-in global variables.
|
|
8
11
|
# Built-in global variables are allowed by default. Additionally
|
|
9
12
|
# users can allow additional variables via the AllowedVariables option.
|
|
@@ -54,7 +57,7 @@ module RuboCop
|
|
|
54
57
|
].map(&:to_sym)
|
|
55
58
|
|
|
56
59
|
def user_vars
|
|
57
|
-
cop_config['AllowedVariables'].map(&:to_sym)
|
|
60
|
+
@user_vars ||= cop_config['AllowedVariables'].map(&:to_sym).freeze
|
|
58
61
|
end
|
|
59
62
|
|
|
60
63
|
def allowed_var?(global_var)
|