rubocop 1.79.2 → 1.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +259 -90
- data/config/obsoletion.yml +30 -1
- data/exe/rubocop +1 -8
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +36 -4
- data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
- data/lib/rubocop/cli/command/lsp.rb +1 -1
- data/lib/rubocop/cli/command/mcp.rb +19 -0
- data/lib/rubocop/cli/command/show_cops.rb +2 -2
- data/lib/rubocop/cli/command/show_docs_url.rb +4 -8
- data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
- data/lib/rubocop/cli.rb +35 -9
- data/lib/rubocop/comment_config.rb +59 -17
- data/lib/rubocop/config.rb +14 -10
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader.rb +37 -23
- data/lib/rubocop/config_loader_resolver.rb +20 -10
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
- data/lib/rubocop/config_store.rb +7 -2
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/base.rb +25 -4
- data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
- data/lib/rubocop/cop/bundler/gem_version.rb +28 -28
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +26 -7
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -5
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +33 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors.rb +28 -0
- data/lib/rubocop/cop/documentation.rb +2 -3
- data/lib/rubocop/cop/exclude_limit.rb +31 -5
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
- data/lib/rubocop/cop/gemspec/require_mfa.rb +5 -5
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +12 -7
- data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +8 -8
- data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +9 -9
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +4 -4
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +41 -4
- data/lib/rubocop/cop/layout/case_indentation.rb +3 -1
- data/lib/rubocop/cop/layout/class_structure.rb +14 -7
- data/lib/rubocop/cop/layout/dot_position.rb +2 -2
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +26 -7
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +31 -13
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +2 -2
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +12 -2
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +16 -2
- data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +16 -2
- data/lib/rubocop/cop/layout/end_alignment.rb +10 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +34 -1
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +26 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +7 -1
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +25 -25
- data/lib/rubocop/cop/layout/hash_alignment.rb +3 -6
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +33 -3
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +123 -7
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +26 -9
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +57 -57
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +56 -56
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +229 -39
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
- data/lib/rubocop/cop/layout/parameter_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +3 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
- data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +4 -2
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +9 -8
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_assignment.rb +1 -11
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +1 -10
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +45 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +4 -3
- data/lib/rubocop/cop/lint/constant_reassignment.rb +93 -11
- data/lib/rubocop/cop/lint/constant_resolution.rb +6 -6
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
- data/lib/rubocop/cop/lint/data_define_override.rb +63 -0
- data/lib/rubocop/cop/lint/debugger.rb +0 -3
- data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -12
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/else_layout.rb +19 -0
- data/lib/rubocop/cop/lint/empty_block.rb +4 -4
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
- data/lib/rubocop/cop/lint/empty_when.rb +8 -1
- data/lib/rubocop/cop/lint/ensure_return.rb +19 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +4 -2
- data/lib/rubocop/cop/lint/float_comparison.rb +2 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +25 -5
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +9 -12
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -10
- data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +2 -0
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +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 +1 -1
- 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 +3 -0
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +7 -7
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -13
- data/lib/rubocop/cop/lint/raise_exception.rb +1 -1
- data/lib/rubocop/cop/lint/rand_one.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +27 -10
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -12
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +15 -4
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +36 -12
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +12 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +10 -3
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_object.rb +5 -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 +2 -1
- 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 +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +18 -0
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +7 -1
- 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 +39 -7
- 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 +14 -0
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +17 -1
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +12 -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 +28 -1
- data/lib/rubocop/cop/lint/to_json.rb +12 -16
- 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 +4 -2
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +7 -5
- data/lib/rubocop/cop/lint/unreachable_pattern_branch.rb +113 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/useless_assignment.rb +53 -25
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
- data/lib/rubocop/cop/lint/useless_or.rb +15 -2
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +8 -4
- 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 +37 -11
- data/lib/rubocop/cop/lint/void.rb +39 -12
- data/lib/rubocop/cop/message_annotator.rb +1 -1
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +23 -0
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/metrics/utils/iterating_block.rb +1 -1
- data/lib/rubocop/cop/migration/department_name.rb +12 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +4 -6
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +5 -5
- data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -60
- data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
- data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
- data/lib/rubocop/cop/mixin.rb +86 -0
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_method.rb +32 -8
- data/lib/rubocop/cop/naming/predicate_prefix.rb +12 -12
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/offense.rb +17 -1
- data/lib/rubocop/cop/registry.rb +62 -38
- data/lib/rubocop/cop/security/eval.rb +15 -2
- data/lib/rubocop/cop/security/io_methods.rb +1 -1
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +15 -4
- data/lib/rubocop/cop/style/accessor_grouping.rb +4 -2
- data/lib/rubocop/cop/style/alias.rb +15 -3
- data/lib/rubocop/cop/style/and_or.rb +2 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
- data/lib/rubocop/cop/style/array_first_last.rb +12 -1
- data/lib/rubocop/cop/style/array_intersect.rb +50 -12
- 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 +8 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +39 -32
- data/lib/rubocop/cop/style/case_equality.rb +29 -15
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +19 -2
- data/lib/rubocop/cop/style/class_equality_comparison.rb +21 -13
- data/lib/rubocop/cop/style/class_methods_definitions.rb +11 -5
- data/lib/rubocop/cop/style/collection_compact.rb +36 -16
- data/lib/rubocop/cop/style/colon_method_call.rb +16 -7
- data/lib/rubocop/cop/style/combinable_loops.rb +5 -0
- data/lib/rubocop/cop/style/comparable_clamp.rb +12 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +7 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +14 -19
- data/lib/rubocop/cop/style/constant_visibility.rb +20 -12
- data/lib/rubocop/cop/style/copyright.rb +22 -11
- data/lib/rubocop/cop/style/date_time.rb +4 -4
- data/lib/rubocop/cop/style/dig_chain.rb +5 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +6 -1
- data/lib/rubocop/cop/style/documentation.rb +6 -6
- data/lib/rubocop/cop/style/documentation_method.rb +8 -8
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +2 -0
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_class_definition.rb +119 -0
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +0 -6
- data/lib/rubocop/cop/style/encoding.rb +7 -1
- data/lib/rubocop/cop/style/end_block.rb +3 -1
- data/lib/rubocop/cop/style/endless_method.rb +23 -5
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
- 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 +15 -1
- data/lib/rubocop/cop/style/for.rb +3 -0
- data/lib/rubocop/cop/style/format_string.rb +4 -3
- data/lib/rubocop/cop/style/format_string_token.rb +49 -5
- data/lib/rubocop/cop/style/global_vars.rb +5 -2
- data/lib/rubocop/cop/style/guard_clause.rb +27 -22
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +27 -9
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
- data/lib/rubocop/cop/style/hash_lookup_method.rb +106 -0
- data/lib/rubocop/cop/style/hash_slice.rb +16 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/hash_transform_keys.rb +17 -7
- data/lib/rubocop/cop/style/hash_transform_values.rb +17 -7
- data/lib/rubocop/cop/style/if_inside_else.rb +16 -7
- data/lib/rubocop/cop/style/if_unless_modifier.rb +58 -18
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -12
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inline_comment.rb +4 -1
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
- data/lib/rubocop/cop/style/lambda_call.rb +8 -8
- data/lib/rubocop/cop/style/magic_comment_format.rb +3 -3
- data/lib/rubocop/cop/style/map_join.rb +123 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +15 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/min_max_comparison.rb +1 -1
- data/lib/rubocop/cop/style/module_member_existence_check.rb +110 -0
- data/lib/rubocop/cop/style/multiline_if_then.rb +4 -4
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
- data/lib/rubocop/cop/style/mutable_constant.rb +106 -12
- data/lib/rubocop/cop/style/negative_array_index.rb +220 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
- data/lib/rubocop/cop/style/not.rb +2 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +3 -2
- data/lib/rubocop/cop/style/one_class_per_file.rb +115 -0
- data/lib/rubocop/cop/style/one_line_conditional.rb +21 -12
- data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +14 -3
- data/lib/rubocop/cop/style/partition_instead_of_double_select.rb +270 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
- data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +12 -12
- data/lib/rubocop/cop/style/proc.rb +3 -2
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/reduce_to_hash.rb +200 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +37 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +6 -3
- data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
- data/lib/rubocop/cop/style/redundant_each.rb +3 -3
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +27 -5
- data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -0
- data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +36 -30
- data/lib/rubocop/cop/style/redundant_percent_q.rb +5 -3
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/redundant_return.rb +3 -1
- data/lib/rubocop/cop/style/redundant_self.rb +2 -2
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
- data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
- data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +114 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +31 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +3 -3
- data/lib/rubocop/cop/style/reverse_find.rb +51 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +25 -8
- data/lib/rubocop/cop/style/select_by_kind.rb +158 -0
- data/lib/rubocop/cop/style/select_by_range.rb +197 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +51 -21
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +41 -8
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +12 -3
- data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
- data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
- data/lib/rubocop/cop/style/super_arguments.rb +2 -2
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +7 -6
- data/lib/rubocop/cop/style/tally_method.rb +181 -0
- data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/style/unless_logical_operators.rb +3 -3
- data/lib/rubocop/cop/style/while_until_do.rb +7 -0
- data/lib/rubocop/cop/style/while_until_modifier.rb +16 -0
- data/lib/rubocop/cop/style/word_array.rb +1 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -1
- data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -3
- data/lib/rubocop/cop/team.rb +87 -36
- data/lib/rubocop/cop/util.rb +2 -3
- data/lib/rubocop/cop/utils/format_string.rb +10 -0
- data/lib/rubocop/cop/variable_force/branch.rb +30 -6
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +9 -7
- data/lib/rubocop/cops_documentation_generator.rb +4 -4
- data/lib/rubocop/directive_comment.rb +48 -4
- data/lib/rubocop/file_patterns.rb +9 -1
- data/lib/rubocop/formatter/clang_style_formatter.rb +5 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +38 -14
- data/lib/rubocop/formatter/formatter_set.rb +2 -2
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
- data/lib/rubocop/formatter/tap_formatter.rb +5 -2
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +22 -21
- data/lib/rubocop/lsp/diagnostic.rb +18 -33
- data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
- data/lib/rubocop/lsp/routes.rb +43 -7
- data/lib/rubocop/lsp/runtime.rb +13 -4
- data/lib/rubocop/lsp/stdin_runner.rb +8 -17
- data/lib/rubocop/magic_comment.rb +20 -0
- data/lib/rubocop/mcp/server.rb +200 -0
- data/lib/rubocop/options.rb +35 -4
- data/lib/rubocop/path_util.rb +14 -2
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/project_index_loader.rb +66 -0
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +10 -8
- data/lib/rubocop/result_cache.rb +61 -38
- data/lib/rubocop/rspec/cop_helper.rb +8 -0
- data/lib/rubocop/rspec/shared_contexts.rb +39 -5
- data/lib/rubocop/rspec/support.rb +2 -1
- data/lib/rubocop/runner.rb +134 -57
- data/lib/rubocop/server/cache.rb +6 -29
- data/lib/rubocop/server/core.rb +8 -0
- data/lib/rubocop/target_finder.rb +17 -10
- data/lib/rubocop/target_ruby.rb +31 -14
- data/lib/rubocop/version.rb +21 -3
- data/lib/rubocop.rb +28 -96
- data/lib/ruby_lsp/rubocop/addon.rb +23 -8
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
- metadata +38 -9
|
@@ -198,12 +198,13 @@ module RuboCop
|
|
|
198
198
|
alias on_csend on_send
|
|
199
199
|
|
|
200
200
|
def on_block(node)
|
|
201
|
-
return if
|
|
201
|
+
return if part_of_ignored_node?(node)
|
|
202
202
|
return if proper_block_style?(node)
|
|
203
203
|
|
|
204
204
|
message = message(node)
|
|
205
205
|
add_offense(node.loc.begin, message: message) do |corrector|
|
|
206
206
|
autocorrect(corrector, node)
|
|
207
|
+
ignore_node(node)
|
|
207
208
|
end
|
|
208
209
|
end
|
|
209
210
|
|
|
@@ -231,9 +232,7 @@ module RuboCop
|
|
|
231
232
|
end
|
|
232
233
|
|
|
233
234
|
def semantic_message(node)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if block_begin == '{'
|
|
235
|
+
if node.braces?
|
|
237
236
|
'Prefer `do...end` over `{...}` for procedural blocks.'
|
|
238
237
|
else
|
|
239
238
|
'Prefer `{...}` over `do...end` for functional blocks.'
|
|
@@ -371,36 +370,42 @@ module RuboCop
|
|
|
371
370
|
end
|
|
372
371
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
373
372
|
|
|
373
|
+
# rubocop:disable Metrics/CyclomaticComplexity -- inlined special_method checks to avoid double evaluation
|
|
374
374
|
def proper_block_style?(node)
|
|
375
375
|
return true if require_do_end?(node)
|
|
376
|
-
|
|
376
|
+
|
|
377
|
+
method_name = node.method_name
|
|
378
|
+
return true if allowed_method?(method_name) || matches_allowed_pattern?(method_name)
|
|
379
|
+
return node.braces? if braces_required_method?(method_name)
|
|
377
380
|
|
|
378
381
|
case style
|
|
379
382
|
when :line_count_based then line_count_based_block_style?(node)
|
|
380
383
|
when :semantic then semantic_block_style?(node)
|
|
381
384
|
when :braces_for_chaining then braces_for_chaining_style?(node)
|
|
382
|
-
when :always_braces then
|
|
385
|
+
when :always_braces then node.braces?
|
|
383
386
|
end
|
|
384
387
|
end
|
|
388
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
385
389
|
|
|
386
390
|
def require_do_end?(node)
|
|
387
391
|
return false if node.braces? || node.multiline?
|
|
388
|
-
return false unless (resbody = node.each_descendant(:resbody).first)
|
|
389
392
|
|
|
390
|
-
|
|
391
|
-
|
|
393
|
+
body = node.body
|
|
394
|
+
return false unless body
|
|
395
|
+
# `ensure` and a block-level `rescue` are illegal inside `{ }`; only a
|
|
396
|
+
# bare modifier rescue (`expr rescue expr`) can be written with braces.
|
|
397
|
+
return true if body.ensure_type?
|
|
398
|
+
return false unless body.rescue_type?
|
|
392
399
|
|
|
393
|
-
|
|
394
|
-
allowed_method?(method_name) ||
|
|
395
|
-
matches_allowed_pattern?(method_name) ||
|
|
396
|
-
braces_required_method?(method_name)
|
|
400
|
+
!modifier_rescue?(body)
|
|
397
401
|
end
|
|
398
402
|
|
|
399
|
-
def
|
|
400
|
-
|
|
401
|
-
return
|
|
403
|
+
def modifier_rescue?(rescue_node)
|
|
404
|
+
return false if rescue_node.body.nil? || rescue_node.else_branch
|
|
405
|
+
return false unless rescue_node.resbody_branches.one?
|
|
402
406
|
|
|
403
|
-
|
|
407
|
+
resbody = rescue_node.resbody_branches.first
|
|
408
|
+
resbody.exceptions.empty? && resbody.exception_variable.nil?
|
|
404
409
|
end
|
|
405
410
|
|
|
406
411
|
def braces_required_method?(method_name)
|
|
@@ -420,24 +425,18 @@ module RuboCop
|
|
|
420
425
|
|
|
421
426
|
if node.braces?
|
|
422
427
|
functional_method?(method_name) || functional_block?(node) ||
|
|
423
|
-
(procedural_oneliners_may_have_braces? &&
|
|
428
|
+
(procedural_oneliners_may_have_braces? && node.single_line?)
|
|
424
429
|
else
|
|
425
430
|
procedural_method?(method_name) || !return_value_used?(node)
|
|
426
431
|
end
|
|
427
432
|
end
|
|
428
433
|
|
|
429
434
|
def braces_for_chaining_style?(node)
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
'{'
|
|
436
|
-
end
|
|
437
|
-
end
|
|
438
|
-
|
|
439
|
-
def braces_style?(node)
|
|
440
|
-
node.loc.begin.source == '{'
|
|
435
|
+
if node.multiline?
|
|
436
|
+
node.chained? ? node.braces? : !node.braces?
|
|
437
|
+
else
|
|
438
|
+
node.braces?
|
|
439
|
+
end
|
|
441
440
|
end
|
|
442
441
|
|
|
443
442
|
def correction_would_break_code?(node)
|
|
@@ -447,7 +446,11 @@ module RuboCop
|
|
|
447
446
|
end
|
|
448
447
|
|
|
449
448
|
def functional_method?(method_name)
|
|
450
|
-
|
|
449
|
+
functional_methods.include?(method_name)
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def functional_methods
|
|
453
|
+
@functional_methods ||= cop_config['FunctionalMethods'].to_set(&:to_sym).freeze
|
|
451
454
|
end
|
|
452
455
|
|
|
453
456
|
def functional_block?(node)
|
|
@@ -459,7 +462,11 @@ module RuboCop
|
|
|
459
462
|
end
|
|
460
463
|
|
|
461
464
|
def procedural_method?(method_name)
|
|
462
|
-
|
|
465
|
+
procedural_methods.include?(method_name)
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
def procedural_methods
|
|
469
|
+
@procedural_methods ||= cop_config['ProceduralMethods'].to_set(&:to_sym).freeze
|
|
463
470
|
end
|
|
464
471
|
|
|
465
472
|
def return_value_used?(node)
|
|
@@ -488,7 +495,7 @@ module RuboCop
|
|
|
488
495
|
def begin_required?(block_node)
|
|
489
496
|
# If the block contains `rescue` or `ensure`, it needs to be wrapped in
|
|
490
497
|
# `begin`...`end` when changing `do-end` to `{}`.
|
|
491
|
-
block_node.each_child_node(:rescue, :ensure).any? &&
|
|
498
|
+
block_node.each_child_node(:rescue, :ensure).any? && block_node.multiline?
|
|
492
499
|
end
|
|
493
500
|
|
|
494
501
|
def single_argument_operator_method?(node)
|
|
@@ -3,31 +3,40 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Checks for uses of the case equality operator(
|
|
6
|
+
# Checks for uses of the case equality operator (`===`).
|
|
7
|
+
# The `===` operator has different behavior depending on the
|
|
8
|
+
# receiver and its use outside of `case`/`when` is confusing.
|
|
9
|
+
# Prefer more explicit alternatives like `is_a?`, `include?`,
|
|
10
|
+
# or `match?`.
|
|
7
11
|
#
|
|
8
12
|
# If `AllowOnConstant` option is enabled, the cop will ignore violations when the receiver of
|
|
9
13
|
# the case equality operator is a constant.
|
|
10
|
-
|
|
14
|
+
#
|
|
11
15
|
# If `AllowOnSelfClass` option is enabled, the cop will ignore violations when the receiver of
|
|
12
16
|
# the case equality operator is `self.class`. Note intermediate variables are not accepted.
|
|
13
17
|
#
|
|
18
|
+
# NOTE: Regexp case equality (`/regexp/ === var`) is allowed because changing it to
|
|
19
|
+
# `/regexp/.match?(var)` needs to take into account `Regexp.last_match?`, `$~`, `$1`, etc.
|
|
20
|
+
# This potentially incompatible transformation is handled by `Performance/RegexpMatch` cop.
|
|
21
|
+
#
|
|
14
22
|
# @example
|
|
15
23
|
# # bad
|
|
16
24
|
# (1..100) === 7
|
|
17
|
-
# /something/ === some_string
|
|
18
25
|
#
|
|
19
26
|
# # good
|
|
20
|
-
# something.is_a?(Array)
|
|
21
27
|
# (1..100).include?(7)
|
|
22
|
-
# /something/.match?(some_string)
|
|
23
28
|
#
|
|
24
29
|
# @example AllowOnConstant: false (default)
|
|
25
30
|
# # bad
|
|
26
31
|
# Array === something
|
|
27
32
|
#
|
|
33
|
+
# # good
|
|
34
|
+
# something.is_a?(Array)
|
|
35
|
+
#
|
|
28
36
|
# @example AllowOnConstant: true
|
|
29
37
|
# # good
|
|
30
38
|
# Array === something
|
|
39
|
+
# something.is_a?(Array)
|
|
31
40
|
#
|
|
32
41
|
# @example AllowOnSelfClass: false (default)
|
|
33
42
|
# # bad
|
|
@@ -51,7 +60,7 @@ module RuboCop
|
|
|
51
60
|
|
|
52
61
|
def on_send(node)
|
|
53
62
|
case_equality?(node) do |lhs, rhs|
|
|
54
|
-
return if lhs.const_type? && !lhs.module_name?
|
|
63
|
+
return if lhs.regexp_type? || (lhs.const_type? && !lhs.module_name?)
|
|
55
64
|
|
|
56
65
|
add_offense(node.loc.selector) do |corrector|
|
|
57
66
|
replacement = replacement(lhs, rhs)
|
|
@@ -71,13 +80,6 @@ module RuboCop
|
|
|
71
80
|
|
|
72
81
|
def replacement(lhs, rhs)
|
|
73
82
|
case lhs.type
|
|
74
|
-
when :regexp
|
|
75
|
-
# The automatic correction from `a === b` to `a.match?(b)` needs to
|
|
76
|
-
# consider `Regexp.last_match?`, `$~`, `$1`, and etc.
|
|
77
|
-
# This correction is expected to be supported by `Performance/Regexp` cop.
|
|
78
|
-
# See: https://github.com/rubocop/rubocop-performance/issues/152
|
|
79
|
-
#
|
|
80
|
-
# So here is noop.
|
|
81
83
|
when :begin
|
|
82
84
|
begin_replacement(lhs, rhs)
|
|
83
85
|
when :const
|
|
@@ -94,13 +96,25 @@ module RuboCop
|
|
|
94
96
|
end
|
|
95
97
|
|
|
96
98
|
def const_replacement(lhs, rhs)
|
|
97
|
-
"#{rhs
|
|
99
|
+
"#{parenthesize_if_needed(rhs)}.is_a?(#{lhs.source})"
|
|
98
100
|
end
|
|
99
101
|
|
|
100
102
|
def send_replacement(lhs, rhs)
|
|
101
103
|
return unless self_class?(lhs)
|
|
102
104
|
|
|
103
|
-
"#{rhs
|
|
105
|
+
"#{parenthesize_if_needed(rhs)}.is_a?(#{lhs.source})"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# `Array === a + b` must become `(a + b).is_a?(Array)`, not
|
|
109
|
+
# `a + b.is_a?(Array)` (which parses as `a + (b.is_a?(Array))`).
|
|
110
|
+
def parenthesize_if_needed(node)
|
|
111
|
+
requires_parentheses?(node) ? "(#{node.source})" : node.source
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def requires_parentheses?(node)
|
|
115
|
+
return true if node.type?(:and, :or, :if, :range) || node.assignment?
|
|
116
|
+
|
|
117
|
+
node.send_type? && (node.operator_method? || node.unary_operation?)
|
|
104
118
|
end
|
|
105
119
|
end
|
|
106
120
|
end
|
|
@@ -8,8 +8,8 @@ module RuboCop
|
|
|
8
8
|
# essentially one-character strings, so this syntax
|
|
9
9
|
# is mostly redundant at this point.
|
|
10
10
|
#
|
|
11
|
-
#
|
|
12
|
-
# That's a good use case of
|
|
11
|
+
# A `?` character literal can be used to express meta and control characters.
|
|
12
|
+
# That's a good use case of a `?` literal so it doesn't count as an offense.
|
|
13
13
|
#
|
|
14
14
|
# @example
|
|
15
15
|
# # bad
|
|
@@ -28,16 +28,24 @@ module RuboCop
|
|
|
28
28
|
# manual oversight.
|
|
29
29
|
#
|
|
30
30
|
# @example EnforcedStyle: nested (default)
|
|
31
|
+
# # bad
|
|
32
|
+
# class Foo::Bar
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
31
35
|
# # good
|
|
32
|
-
# # have each child on its own line
|
|
33
36
|
# class Foo
|
|
34
37
|
# class Bar
|
|
35
38
|
# end
|
|
36
39
|
# end
|
|
37
40
|
#
|
|
38
41
|
# @example EnforcedStyle: compact
|
|
42
|
+
# # bad
|
|
43
|
+
# class Foo
|
|
44
|
+
# class Bar
|
|
45
|
+
# end
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
39
48
|
# # good
|
|
40
|
-
# # combine definitions as much as possible
|
|
41
49
|
# class Foo::Bar
|
|
42
50
|
# end
|
|
43
51
|
#
|
|
@@ -173,6 +181,7 @@ module RuboCop
|
|
|
173
181
|
|
|
174
182
|
def check_style(node, body, style)
|
|
175
183
|
return if node.identifier.namespace&.cbase_type?
|
|
184
|
+
return unless const_namespace?(node.identifier.namespace)
|
|
176
185
|
|
|
177
186
|
if style == :nested
|
|
178
187
|
check_nested_style(node)
|
|
@@ -181,8 +190,16 @@ module RuboCop
|
|
|
181
190
|
end
|
|
182
191
|
end
|
|
183
192
|
|
|
193
|
+
def const_namespace?(node)
|
|
194
|
+
return true if node.nil? || node.cbase_type?
|
|
195
|
+
return false unless node.const_type?
|
|
196
|
+
|
|
197
|
+
const_namespace?(node.namespace)
|
|
198
|
+
end
|
|
199
|
+
|
|
184
200
|
def check_nested_style(node)
|
|
185
201
|
return unless compact_node_name?(node)
|
|
202
|
+
return if node.parent&.type?(:class, :module)
|
|
186
203
|
|
|
187
204
|
add_offense(node.loc.name, message: NESTED_MSG) do |corrector|
|
|
188
205
|
autocorrect(corrector, node)
|
|
@@ -90,25 +90,33 @@ module RuboCop
|
|
|
90
90
|
private
|
|
91
91
|
|
|
92
92
|
def class_name(class_node, node)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
unless class_name_method?(node.children.first.method_name)
|
|
94
|
+
# `var.class == 'Foo'` compares a `Class` to a `String` (always false) and
|
|
95
|
+
# has no valid `instance_of?` rewrite, so don't suggest one.
|
|
96
|
+
return if class_node.str_type?
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
# When a variable or return value of a method is used, it returns nil
|
|
104
|
-
# because the type is not known and cannot be suggested.
|
|
105
|
-
return
|
|
106
|
-
end
|
|
98
|
+
return class_node.source
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
if (receiver = class_node.receiver) && class_name_method?(class_node.method_name)
|
|
102
|
+
return receiver.source
|
|
107
103
|
end
|
|
108
104
|
|
|
105
|
+
return string_class_name(class_node) if class_node.str_type?
|
|
106
|
+
# When a variable or return value of a method is used, the type is not known
|
|
107
|
+
# and cannot be suggested.
|
|
108
|
+
return if unable_to_determine_type?(class_node)
|
|
109
|
+
|
|
109
110
|
class_node.source
|
|
110
111
|
end
|
|
111
112
|
|
|
113
|
+
def string_class_name(class_node)
|
|
114
|
+
value = trim_string_quotes(class_node)
|
|
115
|
+
# Avoid `::::Foo` when the name is already fully qualified.
|
|
116
|
+
value.prepend('::') if require_cbase?(class_node) && !value.start_with?('::')
|
|
117
|
+
value
|
|
118
|
+
end
|
|
119
|
+
|
|
112
120
|
def class_name_method?(method_name)
|
|
113
121
|
CLASS_NAME_METHODS.include?(method_name)
|
|
114
122
|
end
|
|
@@ -140,15 +140,21 @@ module RuboCop
|
|
|
140
140
|
|
|
141
141
|
def extract_def_from_sclass(def_node, sclass_node)
|
|
142
142
|
range = source_range_with_comment(def_node)
|
|
143
|
-
source = range
|
|
144
|
-
"def #{def_node.method_name}",
|
|
145
|
-
"def self.#{def_node.method_name}"
|
|
146
|
-
)
|
|
147
|
-
|
|
143
|
+
source = prefix_def_with_self(range, def_node)
|
|
148
144
|
source = source.gsub(/^ {#{indentation_diff(def_node, sclass_node)}}/, '')
|
|
149
145
|
[range, source.chomp]
|
|
150
146
|
end
|
|
151
147
|
|
|
148
|
+
# Splice in `self.` at the actual `def` keyword rather than substituting the
|
|
149
|
+
# first textual `def <name>`, which may appear inside a preceding comment.
|
|
150
|
+
def prefix_def_with_self(range, def_node)
|
|
151
|
+
keyword_offset = def_node.loc.keyword.begin_pos - range.begin_pos
|
|
152
|
+
name_end_offset = def_node.loc.name.end_pos - range.begin_pos
|
|
153
|
+
source = range.source.dup
|
|
154
|
+
source[keyword_offset...name_end_offset] = "def self.#{def_node.method_name}"
|
|
155
|
+
source
|
|
156
|
+
end
|
|
157
|
+
|
|
152
158
|
def indentation_diff(node1, node2)
|
|
153
159
|
node1.loc.column - node2.loc.column
|
|
154
160
|
end
|
|
@@ -64,22 +64,34 @@ module RuboCop
|
|
|
64
64
|
# @!method reject_method?(node)
|
|
65
65
|
def_node_matcher :reject_method?, <<~PATTERN
|
|
66
66
|
(block
|
|
67
|
-
(call
|
|
68
|
-
!nil? {:reject :reject!})
|
|
67
|
+
(call !nil? {:reject :reject!})
|
|
69
68
|
$(args ...)
|
|
70
|
-
(call
|
|
71
|
-
|
|
69
|
+
(call $(lvar _) :nil?))
|
|
70
|
+
PATTERN
|
|
71
|
+
|
|
72
|
+
# @!method reject_method_for_numblock_or_itblock?(node)
|
|
73
|
+
def_node_matcher :reject_method_for_numblock_or_itblock?, <<~PATTERN
|
|
74
|
+
{
|
|
75
|
+
(numblock (call !nil? {:reject :reject!}) _ (call (lvar :_1) :nil?))
|
|
76
|
+
(itblock (call !nil? {:reject :reject!}) _ (call (lvar :it) :nil?))
|
|
77
|
+
}
|
|
72
78
|
PATTERN
|
|
73
79
|
|
|
74
80
|
# @!method select_method?(node)
|
|
75
81
|
def_node_matcher :select_method?, <<~PATTERN
|
|
76
82
|
(block
|
|
77
|
-
(call
|
|
78
|
-
!nil? {:select :select! :filter :filter!})
|
|
83
|
+
(call !nil? {:select :select! :filter :filter!})
|
|
79
84
|
$(args ...)
|
|
80
85
|
(call
|
|
81
|
-
(call
|
|
82
|
-
|
|
86
|
+
(call $(lvar _) :nil?) :!))
|
|
87
|
+
PATTERN
|
|
88
|
+
|
|
89
|
+
# @!method select_method_for_numblock_or_itblock?(node)
|
|
90
|
+
def_node_matcher :select_method_for_numblock_or_itblock?, <<~PATTERN
|
|
91
|
+
{
|
|
92
|
+
(numblock (call !nil? {:select :select! :filter :filter!}) _ (call (call (lvar :_1) :nil?) :!))
|
|
93
|
+
(itblock (call !nil? {:select :select! :filter :filter!}) _ (call (call (lvar :it) :nil?) :!))
|
|
94
|
+
}
|
|
83
95
|
PATTERN
|
|
84
96
|
|
|
85
97
|
# @!method grep_v_with_nil?(node)
|
|
@@ -102,26 +114,34 @@ module RuboCop
|
|
|
102
114
|
|
|
103
115
|
private
|
|
104
116
|
|
|
105
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
106
117
|
def offense_range(node)
|
|
107
118
|
if reject_method_with_block_pass?(node) || grep_v_with_nil?(node)
|
|
108
119
|
range(node, node)
|
|
109
120
|
else
|
|
110
121
|
block_node = node.parent
|
|
111
122
|
|
|
112
|
-
return unless block_node&.
|
|
113
|
-
unless
|
|
114
|
-
return
|
|
115
|
-
end
|
|
116
|
-
return unless args.last.source == receiver.source
|
|
123
|
+
return unless block_node&.any_block_type?
|
|
124
|
+
return unless match_block_method?(block_node)
|
|
117
125
|
|
|
118
126
|
range(node, block_node)
|
|
119
127
|
end
|
|
120
128
|
end
|
|
121
|
-
|
|
129
|
+
|
|
130
|
+
def match_block_method?(block_node)
|
|
131
|
+
if block_node.block_type?
|
|
132
|
+
result = reject_method?(block_node) || select_method?(block_node)
|
|
133
|
+
return false unless result
|
|
134
|
+
|
|
135
|
+
args, receiver = result
|
|
136
|
+
args.last.source == receiver.source
|
|
137
|
+
else
|
|
138
|
+
reject_method_for_numblock_or_itblock?(block_node) ||
|
|
139
|
+
select_method_for_numblock_or_itblock?(block_node)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
122
142
|
|
|
123
143
|
def to_enum_method?(node)
|
|
124
|
-
return false unless node.receiver.
|
|
144
|
+
return false unless node.receiver.call_type?
|
|
125
145
|
|
|
126
146
|
TO_ENUM_METHODS.include?(node.receiver.method_name)
|
|
127
147
|
end
|
|
@@ -4,7 +4,9 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
6
|
# Checks for methods invoked via the `::` operator instead
|
|
7
|
-
# of the `.` operator (like `FileUtils::rmdir` instead of
|
|
7
|
+
# of the `.` operator (like `FileUtils::rmdir` instead of
|
|
8
|
+
# `FileUtils.rmdir`). The `::` operator is conventionally used to
|
|
9
|
+
# reference constants, so using it for method calls can be misleading.
|
|
8
10
|
#
|
|
9
11
|
# @example
|
|
10
12
|
# # bad
|
|
@@ -22,10 +24,9 @@ module RuboCop
|
|
|
22
24
|
|
|
23
25
|
MSG = 'Do not use `::` for method calls.'
|
|
24
26
|
|
|
25
|
-
# @!method
|
|
26
|
-
def_node_matcher :
|
|
27
|
-
(
|
|
28
|
-
(const nil? :Java) _)
|
|
27
|
+
# @!method java_root?(node)
|
|
28
|
+
def_node_matcher :java_root?, <<~PATTERN
|
|
29
|
+
(const nil? :Java)
|
|
29
30
|
PATTERN
|
|
30
31
|
|
|
31
32
|
def self.autocorrect_incompatible_with
|
|
@@ -35,11 +36,19 @@ module RuboCop
|
|
|
35
36
|
def on_send(node)
|
|
36
37
|
return unless node.receiver && node.double_colon?
|
|
37
38
|
return if node.camel_case_method?
|
|
38
|
-
# ignore Java interop code like Java::int
|
|
39
|
-
return if
|
|
39
|
+
# ignore Java interop code like `Java::int` or `Java::com::method`
|
|
40
|
+
return if java_interop?(node)
|
|
40
41
|
|
|
41
42
|
add_offense(node.loc.dot) { |corrector| corrector.replace(node.loc.dot, '.') }
|
|
42
43
|
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def java_interop?(node)
|
|
48
|
+
receiver = node.receiver
|
|
49
|
+
receiver = receiver.receiver while receiver.respond_to?(:receiver) && receiver.receiver
|
|
50
|
+
java_root?(receiver)
|
|
51
|
+
end
|
|
43
52
|
end
|
|
44
53
|
end
|
|
45
54
|
end
|
|
@@ -85,8 +85,13 @@ module RuboCop
|
|
|
85
85
|
def on_for(node)
|
|
86
86
|
return unless node.parent&.begin_type?
|
|
87
87
|
return unless same_collection_looping_for?(node, node.left_sibling)
|
|
88
|
+
return unless node.body && node.left_sibling.body
|
|
88
89
|
|
|
89
90
|
add_offense(node) do |corrector|
|
|
91
|
+
# Combining loops with different iteration variables would leave the second
|
|
92
|
+
# body referencing an undefined variable, so only autocorrect when they match.
|
|
93
|
+
next unless node.variable == node.left_sibling.variable
|
|
94
|
+
|
|
90
95
|
combine_with_left_sibling(corrector, node)
|
|
91
96
|
end
|
|
92
97
|
end
|
|
@@ -90,7 +90,7 @@ module RuboCop
|
|
|
90
90
|
max = if_body.source
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
-
prefer = "#{
|
|
93
|
+
prefer = "#{parenthesize_if_needed(else_body)}.clamp(#{min}, #{max})"
|
|
94
94
|
|
|
95
95
|
add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
|
|
96
96
|
autocorrect(corrector, node, prefer)
|
|
@@ -119,6 +119,17 @@ module RuboCop
|
|
|
119
119
|
|
|
120
120
|
(lhs.source == else_body && op == :<) || (rhs.source == else_body && op == :>)
|
|
121
121
|
end
|
|
122
|
+
|
|
123
|
+
# `a + b` must become `(a + b).clamp(low, high)`, not `a + b.clamp(low, high)`
|
|
124
|
+
# (which parses as `a + (b.clamp(low, high))`).
|
|
125
|
+
def parenthesize_if_needed(node)
|
|
126
|
+
if node.type?(:and, :or, :if, :range) || node.assignment? ||
|
|
127
|
+
(node.send_type? && (node.operator_method? || node.unary_operation?))
|
|
128
|
+
"(#{node.source})"
|
|
129
|
+
else
|
|
130
|
+
node.source
|
|
131
|
+
end
|
|
132
|
+
end
|
|
122
133
|
end
|
|
123
134
|
end
|
|
124
135
|
end
|
|
@@ -52,7 +52,13 @@ module RuboCop
|
|
|
52
52
|
|
|
53
53
|
add_offense(offense, message: message) do |corrector|
|
|
54
54
|
if use_percent_literal
|
|
55
|
+
next unless prefer
|
|
56
|
+
|
|
55
57
|
corrector.replace(offense, prefer)
|
|
58
|
+
elsif node.arguments.any? { |argument| argument.children.empty? }
|
|
59
|
+
# In-place bracket removal would leave dangling commas (e.g.
|
|
60
|
+
# `concat([], [b])` -> `push(, b)`), so rebuild the call instead.
|
|
61
|
+
corrector.replace(offense, preferred_method(node))
|
|
56
62
|
else
|
|
57
63
|
corrector.replace(node.loc.selector, 'push')
|
|
58
64
|
node.arguments.each do |argument|
|
|
@@ -73,7 +79,7 @@ module RuboCop
|
|
|
73
79
|
|
|
74
80
|
def preferred_method(node)
|
|
75
81
|
new_arguments =
|
|
76
|
-
node.arguments.
|
|
82
|
+
node.arguments.flat_map do |arg|
|
|
77
83
|
if arg.percent_literal?
|
|
78
84
|
arg.children.map { |child| child.value.inspect }
|
|
79
85
|
else
|
|
@@ -99,10 +99,6 @@ module RuboCop
|
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
101
|
|
|
102
|
-
def setter_method?(method_name)
|
|
103
|
-
method_name.to_s.end_with?(EQUAL) && !%i[!= == === >= <=].include?(method_name)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
102
|
def assignment_rhs_exist?(node)
|
|
107
103
|
parent = node.parent
|
|
108
104
|
return true unless parent
|
|
@@ -213,9 +209,7 @@ module RuboCop
|
|
|
213
209
|
ASSIGN_TO_CONDITION_MSG = 'Assign variables inside of conditionals.'
|
|
214
210
|
VARIABLE_ASSIGNMENT_TYPES = %i[casgn cvasgn gvasgn ivasgn lvasgn].freeze
|
|
215
211
|
ASSIGNMENT_TYPES = VARIABLE_ASSIGNMENT_TYPES + %i[and_asgn or_asgn op_asgn masgn].freeze
|
|
216
|
-
LINE_LENGTH = 'Layout/LineLength'
|
|
217
212
|
ENABLED = 'Enabled'
|
|
218
|
-
MAX = 'Max'
|
|
219
213
|
SINGLE_LINE_CONDITIONS_ONLY = 'SingleLineConditionsOnly'
|
|
220
214
|
|
|
221
215
|
# The shovel operator `<<` does not have its own type. It is a `send`
|
|
@@ -289,7 +283,10 @@ module RuboCop
|
|
|
289
283
|
|
|
290
284
|
_condition, *branches, else_branch = *assignment
|
|
291
285
|
|
|
292
|
-
|
|
286
|
+
# Use the node accessor rather than the raw destructured branch: for
|
|
287
|
+
# `x = unless cond; body; end` (no `else`) the parser puts `body` in the
|
|
288
|
+
# else slot, but `else_branch` correctly reports there is no `else` clause.
|
|
289
|
+
return unless assignment.else_branch
|
|
293
290
|
return if allowed_single_line?([*branches, else_branch])
|
|
294
291
|
|
|
295
292
|
add_offense(node, message: ASSIGN_TO_CONDITION_MSG) do |corrector|
|
|
@@ -399,7 +396,7 @@ module RuboCop
|
|
|
399
396
|
# of the longest line + the length of the corrected assignment is
|
|
400
397
|
# greater than the max configured line length
|
|
401
398
|
def correction_exceeds_line_limit?(node, branches)
|
|
402
|
-
return false unless
|
|
399
|
+
return false unless config.cop_enabled?('Layout/LineLength')
|
|
403
400
|
|
|
404
401
|
assignment = lhs(tail(branches[0]))
|
|
405
402
|
|
|
@@ -417,14 +414,6 @@ module RuboCop
|
|
|
417
414
|
assignment + longest_line
|
|
418
415
|
end
|
|
419
416
|
|
|
420
|
-
def line_length_cop_enabled?
|
|
421
|
-
config.for_cop(LINE_LENGTH)[ENABLED]
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
def max_line_length
|
|
425
|
-
config.for_cop(LINE_LENGTH)[MAX]
|
|
426
|
-
end
|
|
427
|
-
|
|
428
417
|
def single_line_conditions_only?
|
|
429
418
|
cop_config[SINGLE_LINE_CONDITIONS_ONLY]
|
|
430
419
|
end
|
|
@@ -444,7 +433,7 @@ module RuboCop
|
|
|
444
433
|
next if child.parent.dstr_type?
|
|
445
434
|
|
|
446
435
|
white_space = white_space_range(child, column)
|
|
447
|
-
corrector.remove(white_space) if white_space
|
|
436
|
+
corrector.remove(white_space) if white_space
|
|
448
437
|
end
|
|
449
438
|
|
|
450
439
|
if condition.loc.else && !same_line?(condition.else_branch, condition)
|
|
@@ -465,9 +454,13 @@ module RuboCop
|
|
|
465
454
|
|
|
466
455
|
def white_space_range(node, column)
|
|
467
456
|
expression = node.source_range
|
|
468
|
-
|
|
457
|
+
end_pos = expression.begin_pos
|
|
458
|
+
begin_pos = end_pos - (expression.column - column - 2)
|
|
469
459
|
|
|
470
|
-
|
|
460
|
+
return nil if begin_pos > end_pos
|
|
461
|
+
|
|
462
|
+
white_space = Parser::Source::Range.new(expression.source_buffer, begin_pos, end_pos)
|
|
463
|
+
white_space if white_space.source.strip.empty?
|
|
471
464
|
end
|
|
472
465
|
|
|
473
466
|
def assignment(node)
|
|
@@ -667,6 +660,8 @@ module RuboCop
|
|
|
667
660
|
remove_whitespace_in_branches(corrector, branch, condition, column)
|
|
668
661
|
|
|
669
662
|
parent_keyword = branch.parent.loc.keyword
|
|
663
|
+
return if same_line?(parent_keyword, condition)
|
|
664
|
+
|
|
670
665
|
corrector.remove_preceding(parent_keyword, parent_keyword.column - column)
|
|
671
666
|
end
|
|
672
667
|
end
|