rubocop 1.71.1 → 1.88.2
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 +513 -149
- data/config/internal_affairs.yml +20 -0
- data/config/obsoletion.yml +38 -4
- 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 +8 -2
- data/lib/rubocop/cli.rb +48 -11
- data/lib/rubocop/comment_config.rb +60 -18
- data/lib/rubocop/config.rb +53 -16
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader.rb +65 -49
- data/lib/rubocop/config_loader_resolver.rb +44 -19
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +6 -3
- data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
- data/lib/rubocop/config_obsoletion.rb +46 -2
- data/lib/rubocop/config_store.rb +7 -2
- data/lib/rubocop/config_validator.rb +7 -6
- data/lib/rubocop/cop/autocorrect_logic.rb +27 -14
- data/lib/rubocop/cop/base.rb +38 -12
- 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/commissioner.rb +13 -11
- 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/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/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 +13 -13
- 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 -1
- 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 +1 -1
- 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 +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 +60 -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 +56 -10
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
- data/lib/rubocop/cop/layout/comment_indentation.rb +9 -2
- 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 +2 -15
- data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +28 -9
- 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 +10 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +35 -2
- 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/hash_alignment.rb +5 -8
- 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 +152 -7
- data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +62 -15
- 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 +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 +236 -41
- 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 +12 -6
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -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 +1 -1
- 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 +18 -3
- 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 +12 -3
- 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/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/ambiguous_range.rb +5 -0
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +13 -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 +93 -11
- data/lib/rubocop/cop/lint/constant_resolution.rb +6 -6
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +90 -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/duplicate_match_pattern.rb +4 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +219 -32
- 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/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 +129 -11
- 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/mixed_case_range.rb +2 -2
- data/lib/rubocop/cop/lint/multiple_comparison.rb +2 -2
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- 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/parentheses_as_grouped_expression.rb +3 -13
- 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 +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_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -23
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +134 -11
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +12 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +268 -0
- data/lib/rubocop/cop/lint/redundant_with_index.rb +4 -1
- 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 +22 -4
- 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 +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/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +123 -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 +36 -3
- 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 +17 -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/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +30 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +55 -25
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +92 -0
- 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 +1 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +11 -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 +147 -0
- data/lib/rubocop/cop/lint/void.rb +50 -21
- 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 +38 -7
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- 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/migration/department_name.rb +12 -1
- 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/check_line_breakable.rb +4 -4
- 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 +1 -1
- 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/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 +15 -14
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
- data/lib/rubocop/cop/mixin/hash_subset.rb +27 -4
- 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/line_length_help.rb +45 -10
- 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/project_index_help.rb +48 -0
- data/lib/rubocop/cop/mixin/range_help.rb +15 -3
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -7
- 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 +25 -6
- 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_forwarding.rb +3 -3
- 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 +11 -2
- data/lib/rubocop/cop/naming/method_name.rb +187 -15
- data/lib/rubocop/cop/naming/predicate_method.rb +330 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +48 -4
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -4
- data/lib/rubocop/cop/naming/variable_name.rb +51 -6
- data/lib/rubocop/cop/offense.rb +17 -1
- data/lib/rubocop/cop/registry.rb +66 -39
- 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/style/access_modifier_declarations.rb +45 -12
- data/lib/rubocop/cop/style/accessor_grouping.rb +46 -8
- 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 +46 -31
- data/lib/rubocop/cop/style/array_first_last.rb +12 -1
- data/lib/rubocop/cop/style/array_intersect.rb +117 -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 +8 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +42 -34
- data/lib/rubocop/cop/style/case_equality.rb +29 -15
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +67 -12
- 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 +6 -0
- 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 +7 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +33 -24
- data/lib/rubocop/cop/style/constant_visibility.rb +20 -12
- data/lib/rubocop/cop/style/copyright.rb +22 -11
- data/lib/rubocop/cop/style/data_inheritance.rb +11 -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/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 +12 -8
- 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 +12 -2
- 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 +0 -6
- 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 +181 -18
- 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 +4 -2
- 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 +4 -0
- data/lib/rubocop/cop/style/format_string.rb +17 -4
- data/lib/rubocop/cop/style/format_string_token.rb +85 -14
- 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 +29 -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 +3 -2
- data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
- data/lib/rubocop/cop/style/hash_lookup_method.rb +102 -0
- data/lib/rubocop/cop/style/hash_slice.rb +16 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +6 -1
- 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 -7
- data/lib/rubocop/cop/style/if_inside_else.rb +26 -20
- data/lib/rubocop/cop/style/if_unless_modifier.rb +83 -16
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +16 -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 +8 -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 +3 -3
- 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 +12 -3
- data/lib/rubocop/cop/style/map_to_set.rb +1 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +9 -8
- 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 +33 -4
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -5
- 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 +10 -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 +4 -4
- data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +13 -16
- 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/next.rb +44 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +11 -10
- data/lib/rubocop/cop/style/nil_lambda.rb +9 -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/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 +21 -12
- data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +11 -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 +57 -25
- 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_begin.rb +38 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +61 -1
- data/lib/rubocop/cop/style/redundant_constant_base.rb +5 -5
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +26 -4
- data/lib/rubocop/cop/style/redundant_each.rb +3 -3
- 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_filter_chain.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +312 -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 +28 -7
- data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +111 -37
- 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 +12 -0
- data/lib/rubocop/cop/style/redundant_return.rb +3 -1
- data/lib/rubocop/cop/style/redundant_self.rb +20 -7
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
- 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_struct_keyword_init.rb +133 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +32 -3
- data/lib/rubocop/cop/style/rescue_modifier.rb +6 -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 +67 -20
- 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 +53 -20
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +45 -12
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +21 -6
- data/lib/rubocop/cop/style/single_line_methods.rb +13 -8
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +77 -101
- data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +18 -15
- data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +24 -2
- data/lib/rubocop/cop/style/super_arguments.rb +3 -4
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +10 -7
- 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/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 +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 +105 -40
- data/lib/rubocop/cop/util.rb +4 -5
- 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 +10 -3
- data/lib/rubocop/cop/variable_force.rb +26 -9
- data/lib/rubocop/cops_documentation_generator.rb +23 -7
- data/lib/rubocop/directive_comment.rb +80 -3
- data/lib/rubocop/ext/regexp_node.rb +0 -1
- 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 -13
- data/lib/rubocop/formatter/formatter_set.rb +2 -2
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +2 -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 +22 -37
- data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
- data/lib/rubocop/lsp/routes.rb +47 -11
- data/lib/rubocop/lsp/runtime.rb +19 -8
- data/lib/rubocop/lsp/server.rb +0 -2
- data/lib/rubocop/lsp/stdin_runner.rb +11 -18
- data/lib/rubocop/magic_comment.rb +28 -0
- data/lib/rubocop/mcp/server.rb +200 -0
- data/lib/rubocop/options.rb +60 -14
- data/lib/rubocop/path_util.rb +18 -2
- data/lib/rubocop/pending_cops_reporter.rb +56 -0
- data/lib/rubocop/plugin/configuration_integrator.rb +143 -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 +66 -0
- data/lib/rubocop/rake_task.rb +5 -2
- data/lib/rubocop/remote_config.rb +10 -8
- data/lib/rubocop/result_cache.rb +72 -47
- data/lib/rubocop/rspec/cop_helper.rb +21 -1
- data/lib/rubocop/rspec/expect_offense.rb +9 -3
- data/lib/rubocop/rspec/shared_contexts.rb +71 -3
- data/lib/rubocop/rspec/support.rb +4 -0
- data/lib/rubocop/runner.rb +188 -65
- data/lib/rubocop/server/cache.rb +56 -41
- data/lib/rubocop/server/cli.rb +2 -2
- 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/target_finder.rb +21 -10
- data/lib/rubocop/target_ruby.rb +31 -14
- data/lib/rubocop/version.rb +50 -10
- data/lib/rubocop.rb +47 -96
- data/lib/ruby_lsp/rubocop/addon.rb +29 -17
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +99 -0
- metadata +86 -16
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
- data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +0 -50
|
@@ -20,6 +20,15 @@ module RuboCop
|
|
|
20
20
|
# In the example below, the safe navigation operator (`&.`) is unnecessary
|
|
21
21
|
# because `NilClass` has methods like `respond_to?` and `is_a?`.
|
|
22
22
|
#
|
|
23
|
+
# The `InferNonNilReceiver` option specifies whether to look into previous code
|
|
24
|
+
# paths to infer if the receiver can't be nil. This check is unsafe because the receiver
|
|
25
|
+
# can be redefined between the safe navigation call and previous regular method call.
|
|
26
|
+
# It does the inference only in the current scope, e.g. within the same method definition etc.
|
|
27
|
+
#
|
|
28
|
+
# The `AdditionalNilMethods` option specifies additional custom methods which are
|
|
29
|
+
# defined on `NilClass`. When `InferNonNilReceiver` is set, they are used to determine
|
|
30
|
+
# whether the receiver can be nil.
|
|
31
|
+
#
|
|
23
32
|
# @safety
|
|
24
33
|
# This cop is unsafe, because autocorrection can change the return type of
|
|
25
34
|
# the expression. An offending expression that previously could return `nil`
|
|
@@ -33,12 +42,42 @@ module RuboCop
|
|
|
33
42
|
# CamelCaseConst.do_something
|
|
34
43
|
#
|
|
35
44
|
# # bad
|
|
45
|
+
# foo.to_s&.strip
|
|
46
|
+
# foo.to_i&.zero?
|
|
47
|
+
# foo.to_f&.zero?
|
|
48
|
+
# foo.to_a&.size
|
|
49
|
+
# foo.to_h&.size
|
|
50
|
+
#
|
|
51
|
+
# # good
|
|
52
|
+
# foo.to_s.strip
|
|
53
|
+
# foo.to_i.zero?
|
|
54
|
+
# foo.to_f.zero?
|
|
55
|
+
# foo.to_a.size
|
|
56
|
+
# foo.to_h.size
|
|
57
|
+
#
|
|
58
|
+
# # bad
|
|
36
59
|
# do_something if attrs&.respond_to?(:[])
|
|
37
60
|
#
|
|
38
61
|
# # good
|
|
39
62
|
# do_something if attrs.respond_to?(:[])
|
|
40
63
|
#
|
|
41
64
|
# # bad
|
|
65
|
+
# foo&.bar ? foo&.bar.baz : qux
|
|
66
|
+
#
|
|
67
|
+
# # good
|
|
68
|
+
# foo&.bar ? foo.bar.baz : qux
|
|
69
|
+
#
|
|
70
|
+
# # bad
|
|
71
|
+
# if foo&.bar
|
|
72
|
+
# foo&.bar.baz
|
|
73
|
+
# end
|
|
74
|
+
#
|
|
75
|
+
# # good
|
|
76
|
+
# if foo&.bar
|
|
77
|
+
# foo.bar.baz
|
|
78
|
+
# end
|
|
79
|
+
#
|
|
80
|
+
# # bad
|
|
42
81
|
# while node&.is_a?(BeginNode)
|
|
43
82
|
# node = node.parent
|
|
44
83
|
# end
|
|
@@ -48,8 +87,9 @@ module RuboCop
|
|
|
48
87
|
# node = node.parent
|
|
49
88
|
# end
|
|
50
89
|
#
|
|
51
|
-
# # good - without `&.` this
|
|
90
|
+
# # good - without `&.` this changes the return value for `nil`
|
|
52
91
|
# foo&.respond_to?(:to_a)
|
|
92
|
+
# foo&.respond_to?(:class)
|
|
53
93
|
#
|
|
54
94
|
# # bad - for `nil`s conversion methods return default values for the type
|
|
55
95
|
# foo&.to_h || {}
|
|
@@ -81,27 +121,69 @@ module RuboCop
|
|
|
81
121
|
# do_something if attrs.nil_safe_method(:[])
|
|
82
122
|
# do_something if attrs&.not_nil_safe_method(:[])
|
|
83
123
|
#
|
|
124
|
+
# @example InferNonNilReceiver: false (default)
|
|
125
|
+
# # good
|
|
126
|
+
# foo.bar
|
|
127
|
+
# foo&.baz
|
|
128
|
+
#
|
|
129
|
+
# @example InferNonNilReceiver: true
|
|
130
|
+
# # bad
|
|
131
|
+
# foo.bar
|
|
132
|
+
# foo&.baz # would raise on previous line if `foo` is nil
|
|
133
|
+
#
|
|
134
|
+
# # good
|
|
135
|
+
# foo.bar
|
|
136
|
+
# foo.baz
|
|
137
|
+
#
|
|
138
|
+
# # bad
|
|
139
|
+
# if foo.condition?
|
|
140
|
+
# foo&.bar
|
|
141
|
+
# end
|
|
142
|
+
#
|
|
143
|
+
# # good
|
|
144
|
+
# if foo.condition?
|
|
145
|
+
# foo.bar
|
|
146
|
+
# end
|
|
147
|
+
#
|
|
148
|
+
# # good (different scopes)
|
|
149
|
+
# def method1
|
|
150
|
+
# foo.bar
|
|
151
|
+
# end
|
|
152
|
+
#
|
|
153
|
+
# def method2
|
|
154
|
+
# foo&.bar
|
|
155
|
+
# end
|
|
156
|
+
#
|
|
157
|
+
# @example AdditionalNilMethods: [present?]
|
|
158
|
+
# # good
|
|
159
|
+
# foo.present?
|
|
160
|
+
# foo&.bar
|
|
161
|
+
#
|
|
84
162
|
class RedundantSafeNavigation < Base
|
|
85
163
|
include AllowedMethods
|
|
86
164
|
extend AutoCorrector
|
|
87
165
|
|
|
88
166
|
MSG = 'Redundant safe navigation detected, use `.` instead.'
|
|
89
167
|
MSG_LITERAL = 'Redundant safe navigation with default literal detected.'
|
|
168
|
+
MSG_NON_NIL = 'Redundant safe navigation on non-nil receiver (detected by analyzing ' \
|
|
169
|
+
'previous code/method invocations).'
|
|
90
170
|
|
|
91
|
-
|
|
171
|
+
NIL_METHODS = nil.methods.to_set.freeze
|
|
92
172
|
|
|
93
173
|
SNAKE_CASE = /\A[[:digit:][:upper:]_]+\z/.freeze
|
|
94
174
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
175
|
+
GUARANTEED_INSTANCE_METHODS = %i[to_s to_i to_f to_a to_h].freeze
|
|
176
|
+
|
|
177
|
+
# @!method respond_to_nil_method?(node)
|
|
178
|
+
def_node_matcher :respond_to_nil_method?, <<~PATTERN
|
|
179
|
+
(csend _ :respond_to? (sym %NIL_METHODS))
|
|
98
180
|
PATTERN
|
|
99
181
|
|
|
100
182
|
# @!method conversion_with_default?(node)
|
|
101
183
|
def_node_matcher :conversion_with_default?, <<~PATTERN
|
|
102
184
|
{
|
|
103
185
|
(or $(csend _ :to_h) (hash))
|
|
104
|
-
(or (
|
|
186
|
+
(or (any_block $(csend _ :to_h) ...) (hash))
|
|
105
187
|
(or $(csend _ :to_a) (array))
|
|
106
188
|
(or $(csend _ :to_i) (int 0))
|
|
107
189
|
(or $(csend _ :to_f) (float 0.0))
|
|
@@ -109,17 +191,24 @@ module RuboCop
|
|
|
109
191
|
}
|
|
110
192
|
PATTERN
|
|
111
193
|
|
|
112
|
-
# rubocop:disable Metrics/AbcSize
|
|
113
194
|
def on_csend(node)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
195
|
+
range = node.loc.dot
|
|
196
|
+
|
|
197
|
+
if infer_non_nil_receiver?
|
|
198
|
+
checker = Lint::Utils::NilReceiverChecker.new(node.receiver, additional_nil_methods)
|
|
199
|
+
|
|
200
|
+
if checker.cant_be_nil?
|
|
201
|
+
add_offense(range, message: MSG_NON_NIL) { |corrector| corrector.replace(range, '.') }
|
|
202
|
+
return
|
|
203
|
+
end
|
|
117
204
|
end
|
|
118
205
|
|
|
119
|
-
|
|
206
|
+
return if guarded_by_nil_receiver?(node)
|
|
207
|
+
|
|
120
208
|
add_offense(range) { |corrector| corrector.replace(range, '.') }
|
|
121
209
|
end
|
|
122
210
|
|
|
211
|
+
# rubocop:disable Metrics/AbcSize
|
|
123
212
|
def on_or(node)
|
|
124
213
|
conversion_with_default?(node) do |send_node|
|
|
125
214
|
range = send_node.loc.dot.begin.join(node.source_range.end)
|
|
@@ -136,13 +225,38 @@ module RuboCop
|
|
|
136
225
|
|
|
137
226
|
private
|
|
138
227
|
|
|
228
|
+
# Returns true when the `&.` is meaningful because the receiver may actually be nil.
|
|
229
|
+
def guarded_by_nil_receiver?(node)
|
|
230
|
+
return false if assume_receiver_instance_exists?(node.receiver)
|
|
231
|
+
|
|
232
|
+
guaranteed_instance = guaranteed_instance?(node.receiver)
|
|
233
|
+
return true if !guaranteed_instance && !check?(node)
|
|
234
|
+
|
|
235
|
+
# `nil.respond_to?(<nil method>)` is `true`, so `&.` is meaningful when the receiver
|
|
236
|
+
# may be nil. A guaranteed instance can never be nil, so `&.` is still redundant there.
|
|
237
|
+
respond_to_nil_method?(node) && !guaranteed_instance
|
|
238
|
+
end
|
|
239
|
+
|
|
139
240
|
def assume_receiver_instance_exists?(receiver)
|
|
140
241
|
return true if receiver.const_type? && !receiver.short_name.match?(SNAKE_CASE)
|
|
141
242
|
|
|
142
243
|
receiver.self_type? || (receiver.literal? && !receiver.nil_type?)
|
|
143
244
|
end
|
|
144
245
|
|
|
246
|
+
def guaranteed_instance?(node)
|
|
247
|
+
receiver = if node.any_block_type?
|
|
248
|
+
node.send_node
|
|
249
|
+
else
|
|
250
|
+
node
|
|
251
|
+
end
|
|
252
|
+
return false unless receiver.send_type?
|
|
253
|
+
|
|
254
|
+
GUARANTEED_INSTANCE_METHODS.include?(receiver.method_name)
|
|
255
|
+
end
|
|
256
|
+
|
|
145
257
|
def check?(node)
|
|
258
|
+
return false unless allowed_method?(node.method_name)
|
|
259
|
+
|
|
146
260
|
parent = node.parent
|
|
147
261
|
return false unless parent
|
|
148
262
|
|
|
@@ -154,6 +268,15 @@ module RuboCop
|
|
|
154
268
|
def condition?(parent, node)
|
|
155
269
|
(parent.conditional? || parent.post_condition_loop?) && parent.condition == node
|
|
156
270
|
end
|
|
271
|
+
|
|
272
|
+
def infer_non_nil_receiver?
|
|
273
|
+
cop_config['InferNonNilReceiver']
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def additional_nil_methods
|
|
277
|
+
@additional_nil_methods ||=
|
|
278
|
+
Array(cop_config.fetch('AdditionalNilMethods', []).map(&:to_sym))
|
|
279
|
+
end
|
|
157
280
|
end
|
|
158
281
|
end
|
|
159
282
|
end
|
|
@@ -77,7 +77,7 @@ module RuboCop
|
|
|
77
77
|
PERCENT_CAPITAL_W = '%W'
|
|
78
78
|
PERCENT_I = '%i'
|
|
79
79
|
PERCENT_CAPITAL_I = '%I'
|
|
80
|
-
ASSIGNMENT_TYPES = %i[lvasgn ivasgn cvasgn gvasgn].freeze
|
|
80
|
+
ASSIGNMENT_TYPES = %i[lvasgn ivasgn cvasgn gvasgn casgn].freeze
|
|
81
81
|
|
|
82
82
|
# @!method array_new?(node)
|
|
83
83
|
def_node_matcher :array_new?, <<~PATTERN
|
|
@@ -122,6 +122,10 @@ module RuboCop
|
|
|
122
122
|
|
|
123
123
|
grandparent = node.parent.parent
|
|
124
124
|
return if grandparent && !ASSIGNMENT_TYPES.include?(grandparent.type)
|
|
125
|
+
# An empty array/percent literal (`*[]`, `*%w()`, ...) expands to nothing, so
|
|
126
|
+
# removing the splat would produce invalid or semantically different code.
|
|
127
|
+
elsif expanded_item.array_type? && expanded_item.children.empty?
|
|
128
|
+
return
|
|
125
129
|
end
|
|
126
130
|
|
|
127
131
|
yield
|
|
@@ -144,7 +148,9 @@ module RuboCop
|
|
|
144
148
|
expression = node.parent.source_range if node.parent.array_type?
|
|
145
149
|
[expression, variable.source]
|
|
146
150
|
elsif !variable.array_type?
|
|
147
|
-
|
|
151
|
+
replacement = variable.source
|
|
152
|
+
replacement = "[#{replacement}]" if wrap_in_brackets?(node)
|
|
153
|
+
[expression, replacement]
|
|
148
154
|
elsif redundant_brackets?(node)
|
|
149
155
|
[expression, remove_brackets(variable)]
|
|
150
156
|
else
|
|
@@ -176,6 +182,10 @@ module RuboCop
|
|
|
176
182
|
grandparent&.resbody_type?
|
|
177
183
|
end
|
|
178
184
|
|
|
185
|
+
def wrap_in_brackets?(node)
|
|
186
|
+
node.parent.array_type? && !node.parent.bracketed?
|
|
187
|
+
end
|
|
188
|
+
|
|
179
189
|
def remove_brackets(array)
|
|
180
190
|
array_start = array.loc.begin.source
|
|
181
191
|
elements = *array
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Lint
|
|
6
|
+
# Checks for redundant uses of `to_s`, `to_sym`, `to_i`, `to_f`, `to_d`, `to_r`, `to_c`,
|
|
7
|
+
# `to_a`, `to_h`, and `to_set`.
|
|
8
|
+
#
|
|
9
|
+
# When one of these methods is called on an object of the same type, that object
|
|
10
|
+
# is returned, making the call unnecessary. The cop detects conversion methods called
|
|
11
|
+
# on object literals, class constructors, class `[]` methods, and the `Kernel` methods
|
|
12
|
+
# `String()`, `Integer()`, `Float()`, BigDecimal(), `Rational()`, `Complex()`, and `Array()`.
|
|
13
|
+
#
|
|
14
|
+
# Specifically, these cases are detected for each conversion method:
|
|
15
|
+
#
|
|
16
|
+
# * `to_s` when called on a string literal, interpolated string, heredoc,
|
|
17
|
+
# or with `String.new` or `String()`.
|
|
18
|
+
# * `to_sym` when called on a symbol literal or interpolated symbol.
|
|
19
|
+
# * `to_i` when called on an integer literal or with `Integer()`.
|
|
20
|
+
# * `to_f` when called on a float literal or with `Float()`.
|
|
21
|
+
# * `to_d` when called with `BigDecimal()`.
|
|
22
|
+
# * `to_r` when called on a rational literal or with `Rational()`.
|
|
23
|
+
# * `to_c` when called on a complex literal or with `Complex()`.
|
|
24
|
+
# * `to_a` when called on an array literal, or with `Array.new`, `Array()` or `Array[]`.
|
|
25
|
+
# * `to_h` when called on a hash literal, or with `Hash.new`, `Hash()` or `Hash[]`.
|
|
26
|
+
# * `to_set` when called on `Set.new` or `Set[]`.
|
|
27
|
+
#
|
|
28
|
+
# In all cases, chaining one of the same `to_*` conversion methods listed above is redundant.
|
|
29
|
+
#
|
|
30
|
+
# The cop can also register an offense for chaining conversion methods on methods that are
|
|
31
|
+
# expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s` and
|
|
32
|
+
# `foo.to_json.to_s`).
|
|
33
|
+
#
|
|
34
|
+
# @example
|
|
35
|
+
# # bad
|
|
36
|
+
# "text".to_s
|
|
37
|
+
# :sym.to_sym
|
|
38
|
+
# 42.to_i
|
|
39
|
+
# 8.5.to_f
|
|
40
|
+
# 12r.to_r
|
|
41
|
+
# 1i.to_c
|
|
42
|
+
# [].to_a
|
|
43
|
+
# {}.to_h
|
|
44
|
+
# Set.new.to_set
|
|
45
|
+
#
|
|
46
|
+
# # good
|
|
47
|
+
# "text"
|
|
48
|
+
# :sym
|
|
49
|
+
# 42
|
|
50
|
+
# 8.5
|
|
51
|
+
# 12r
|
|
52
|
+
# 1i
|
|
53
|
+
# []
|
|
54
|
+
# {}
|
|
55
|
+
# Set.new
|
|
56
|
+
#
|
|
57
|
+
# # bad
|
|
58
|
+
# Integer(var).to_i
|
|
59
|
+
#
|
|
60
|
+
# # good
|
|
61
|
+
# Integer(var)
|
|
62
|
+
#
|
|
63
|
+
# # good - chaining to a type constructor with exceptions suppressed
|
|
64
|
+
# # in this case, `Integer()` could return `nil`
|
|
65
|
+
# Integer(var, exception: false).to_i
|
|
66
|
+
#
|
|
67
|
+
# # bad
|
|
68
|
+
# BigDecimal(var).to_d
|
|
69
|
+
#
|
|
70
|
+
# # good
|
|
71
|
+
# BigDecimal(var)
|
|
72
|
+
#
|
|
73
|
+
# # bad - chaining the same conversion
|
|
74
|
+
# foo.to_s.to_s
|
|
75
|
+
#
|
|
76
|
+
# # good
|
|
77
|
+
# foo.to_s
|
|
78
|
+
#
|
|
79
|
+
# # bad - chaining a conversion to a method that is expected to return the same type
|
|
80
|
+
# foo.inspect.to_s
|
|
81
|
+
# foo.to_json.to_s
|
|
82
|
+
#
|
|
83
|
+
# # good
|
|
84
|
+
# foo.inspect
|
|
85
|
+
# foo.to_json
|
|
86
|
+
#
|
|
87
|
+
class RedundantTypeConversion < Base
|
|
88
|
+
extend AutoCorrector
|
|
89
|
+
|
|
90
|
+
MSG = 'Redundant `%<method>s` detected.'
|
|
91
|
+
|
|
92
|
+
# Maps conversion methods to the node types for the literals of that type
|
|
93
|
+
LITERAL_NODE_TYPES = {
|
|
94
|
+
to_s: %i[str dstr],
|
|
95
|
+
to_sym: %i[sym dsym],
|
|
96
|
+
to_i: %i[int],
|
|
97
|
+
to_f: %i[float],
|
|
98
|
+
to_r: %i[rational],
|
|
99
|
+
to_c: %i[complex],
|
|
100
|
+
to_a: %i[array],
|
|
101
|
+
to_h: %i[hash],
|
|
102
|
+
to_set: [] # sets don't have a literal or node type
|
|
103
|
+
}.freeze
|
|
104
|
+
|
|
105
|
+
# Maps each conversion method to the pattern matcher for that type's constructors
|
|
106
|
+
# Not every type has a constructor, for instance Symbol.
|
|
107
|
+
CONSTRUCTOR_MAPPING = {
|
|
108
|
+
to_s: 'string_constructor?',
|
|
109
|
+
to_i: 'integer_constructor?',
|
|
110
|
+
to_f: 'float_constructor?',
|
|
111
|
+
to_d: 'bigdecimal_constructor?',
|
|
112
|
+
to_r: 'rational_constructor?',
|
|
113
|
+
to_c: 'complex_constructor?',
|
|
114
|
+
to_a: 'array_constructor?',
|
|
115
|
+
to_h: 'hash_constructor?',
|
|
116
|
+
to_set: 'set_constructor?'
|
|
117
|
+
}.freeze
|
|
118
|
+
|
|
119
|
+
# Methods that already are expected to return a given type, which makes a further
|
|
120
|
+
# conversion redundant.
|
|
121
|
+
TYPED_METHODS = { to_s: %i[inspect to_json] }.freeze
|
|
122
|
+
|
|
123
|
+
CONVERSION_METHODS = Set[*LITERAL_NODE_TYPES.keys].freeze
|
|
124
|
+
RESTRICT_ON_SEND = CONVERSION_METHODS + [:to_d]
|
|
125
|
+
|
|
126
|
+
private_constant :LITERAL_NODE_TYPES, :CONSTRUCTOR_MAPPING
|
|
127
|
+
|
|
128
|
+
# @!method type_constructor?(node, type_symbol)
|
|
129
|
+
def_node_matcher :type_constructor?, <<~PATTERN
|
|
130
|
+
(send {nil? (const {cbase nil?} :Kernel)} %1 ...)
|
|
131
|
+
PATTERN
|
|
132
|
+
|
|
133
|
+
# @!method string_constructor?(node)
|
|
134
|
+
def_node_matcher :string_constructor?, <<~PATTERN
|
|
135
|
+
{
|
|
136
|
+
(send (const {cbase nil?} :String) :new ...)
|
|
137
|
+
#type_constructor?(:String)
|
|
138
|
+
}
|
|
139
|
+
PATTERN
|
|
140
|
+
|
|
141
|
+
# @!method integer_constructor?(node)
|
|
142
|
+
def_node_matcher :integer_constructor?, <<~PATTERN
|
|
143
|
+
#type_constructor?(:Integer)
|
|
144
|
+
PATTERN
|
|
145
|
+
|
|
146
|
+
# @!method float_constructor?(node)
|
|
147
|
+
def_node_matcher :float_constructor?, <<~PATTERN
|
|
148
|
+
#type_constructor?(:Float)
|
|
149
|
+
PATTERN
|
|
150
|
+
|
|
151
|
+
# @!method bigdecimal_constructor?(node)
|
|
152
|
+
def_node_matcher :bigdecimal_constructor?, <<~PATTERN
|
|
153
|
+
#type_constructor?(:BigDecimal)
|
|
154
|
+
PATTERN
|
|
155
|
+
|
|
156
|
+
# @!method rational_constructor?(node)
|
|
157
|
+
def_node_matcher :rational_constructor?, <<~PATTERN
|
|
158
|
+
#type_constructor?(:Rational)
|
|
159
|
+
PATTERN
|
|
160
|
+
|
|
161
|
+
# @!method complex_constructor?(node)
|
|
162
|
+
def_node_matcher :complex_constructor?, <<~PATTERN
|
|
163
|
+
#type_constructor?(:Complex)
|
|
164
|
+
PATTERN
|
|
165
|
+
|
|
166
|
+
# @!method array_constructor?(node)
|
|
167
|
+
def_node_matcher :array_constructor?, <<~PATTERN
|
|
168
|
+
{
|
|
169
|
+
(send (const {cbase nil?} :Array) {:new :[]} ...)
|
|
170
|
+
#type_constructor?(:Array)
|
|
171
|
+
}
|
|
172
|
+
PATTERN
|
|
173
|
+
|
|
174
|
+
# @!method hash_constructor?(node)
|
|
175
|
+
def_node_matcher :hash_constructor?, <<~PATTERN
|
|
176
|
+
{
|
|
177
|
+
(block (send (const {cbase nil?} :Hash) :new) ...)
|
|
178
|
+
(send (const {cbase nil?} :Hash) {:new :[]} ...)
|
|
179
|
+
(send {nil? (const {cbase nil?} :Kernel)} :Hash ...)
|
|
180
|
+
}
|
|
181
|
+
PATTERN
|
|
182
|
+
|
|
183
|
+
# @!method set_constructor?(node)
|
|
184
|
+
def_node_matcher :set_constructor?, <<~PATTERN
|
|
185
|
+
{
|
|
186
|
+
(send (const {cbase nil?} :Set) {:new :[]} ...)
|
|
187
|
+
}
|
|
188
|
+
PATTERN
|
|
189
|
+
|
|
190
|
+
# @!method exception_false_keyword_argument?(node)
|
|
191
|
+
def_node_matcher :exception_false_keyword_argument?, <<~PATTERN
|
|
192
|
+
(hash (pair (sym :exception) false))
|
|
193
|
+
PATTERN
|
|
194
|
+
|
|
195
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
196
|
+
def on_send(node)
|
|
197
|
+
return if node.arguments.any? || hash_or_set_with_block?(node)
|
|
198
|
+
|
|
199
|
+
receiver = find_receiver(node)
|
|
200
|
+
return unless literal_receiver?(node, receiver) ||
|
|
201
|
+
constructor?(node, receiver) ||
|
|
202
|
+
chained_conversion?(node, receiver) ||
|
|
203
|
+
chained_to_typed_method?(node, receiver)
|
|
204
|
+
|
|
205
|
+
message = format(MSG, method: node.method_name)
|
|
206
|
+
|
|
207
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
|
208
|
+
corrector.remove(node.loc.dot.join(node.loc.end || node.loc.selector))
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
212
|
+
alias on_csend on_send
|
|
213
|
+
|
|
214
|
+
private
|
|
215
|
+
|
|
216
|
+
def hash_or_set_with_block?(node)
|
|
217
|
+
return false if !node.method?(:to_h) && !node.method?(:to_set)
|
|
218
|
+
|
|
219
|
+
node.parent&.any_block_type? || node.last_argument&.block_pass_type?
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def find_receiver(node)
|
|
223
|
+
receiver = node.receiver
|
|
224
|
+
return unless receiver
|
|
225
|
+
|
|
226
|
+
while receiver.begin_type?
|
|
227
|
+
break unless receiver.children.one?
|
|
228
|
+
|
|
229
|
+
receiver = receiver.children.first
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
receiver
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def literal_receiver?(node, receiver)
|
|
236
|
+
return false unless receiver
|
|
237
|
+
|
|
238
|
+
receiver.type?(*LITERAL_NODE_TYPES[node.method_name])
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def constructor?(node, receiver)
|
|
242
|
+
matcher = CONSTRUCTOR_MAPPING[node.method_name]
|
|
243
|
+
return false unless matcher
|
|
244
|
+
|
|
245
|
+
public_send(matcher, receiver) && !constructor_suppresses_exceptions?(receiver)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def constructor_suppresses_exceptions?(receiver)
|
|
249
|
+
# If the constructor suppresses exceptions with `exception: false`, it is possible
|
|
250
|
+
# it could return `nil`, and therefore a chained conversion is not redundant.
|
|
251
|
+
receiver.arguments.any? { |arg| exception_false_keyword_argument?(arg) }
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def chained_conversion?(node, receiver)
|
|
255
|
+
return false unless receiver&.call_type?
|
|
256
|
+
|
|
257
|
+
receiver.method?(node.method_name)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def chained_to_typed_method?(node, receiver)
|
|
261
|
+
return false unless receiver&.call_type?
|
|
262
|
+
|
|
263
|
+
TYPED_METHODS.fetch(node.method_name, []).include?(receiver.method_name)
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
@@ -53,6 +53,7 @@ module RuboCop
|
|
|
53
53
|
# rubocop:enable Metrics/AbcSize
|
|
54
54
|
|
|
55
55
|
alias on_numblock on_block
|
|
56
|
+
alias on_itblock on_block
|
|
56
57
|
|
|
57
58
|
private
|
|
58
59
|
|
|
@@ -61,9 +62,11 @@ module RuboCop
|
|
|
61
62
|
{
|
|
62
63
|
(block
|
|
63
64
|
$(call _ {:each_with_index :with_index} ...)
|
|
64
|
-
(args (arg _)) ...)
|
|
65
|
+
{(args (arg _)) (args)} ...)
|
|
65
66
|
(numblock
|
|
66
67
|
$(call _ {:each_with_index :with_index} ...) 1 ...)
|
|
68
|
+
(itblock
|
|
69
|
+
$(call _ {:each_with_index :with_index} ...) _ ...)
|
|
67
70
|
}
|
|
68
71
|
PATTERN
|
|
69
72
|
|
|
@@ -5,6 +5,11 @@ module RuboCop
|
|
|
5
5
|
module Lint
|
|
6
6
|
# Checks for redundant `with_object`.
|
|
7
7
|
#
|
|
8
|
+
# @safety
|
|
9
|
+
# This cop's autocorrection is unsafe because the return value changes:
|
|
10
|
+
# `each_with_object` returns the memo object, while the corrected `each` returns
|
|
11
|
+
# the receiver. This matters when the result of the expression is used.
|
|
12
|
+
#
|
|
8
13
|
# @example
|
|
9
14
|
# # bad
|
|
10
15
|
# ary.each_with_object([]) do |v|
|
|
@@ -49,6 +54,7 @@ module RuboCop
|
|
|
49
54
|
end
|
|
50
55
|
|
|
51
56
|
alias on_numblock on_block
|
|
57
|
+
alias on_itblock on_block
|
|
52
58
|
|
|
53
59
|
private
|
|
54
60
|
|
|
@@ -59,6 +65,8 @@ module RuboCop
|
|
|
59
65
|
$(call _ {:each_with_object :with_object} _) (args (arg _)) ...)
|
|
60
66
|
(numblock
|
|
61
67
|
$(call _ {:each_with_object :with_object} _) 1 ...)
|
|
68
|
+
(itblock
|
|
69
|
+
$(call _ {:each_with_object :with_object} _) _ ...)
|
|
62
70
|
}
|
|
63
71
|
PATTERN
|
|
64
72
|
|
|
@@ -32,9 +32,12 @@ module RuboCop
|
|
|
32
32
|
# end
|
|
33
33
|
#
|
|
34
34
|
class RefinementImportMethods < Base
|
|
35
|
+
extend AutoCorrector
|
|
35
36
|
extend TargetRubyVersion
|
|
36
37
|
|
|
37
38
|
MSG = 'Use `import_methods` instead of `%<current>s` because it is deprecated in Ruby 3.1.'
|
|
39
|
+
MSG_REMOVED = 'Use `import_methods` instead of `%<current>s` ' \
|
|
40
|
+
'because it was removed in Ruby 3.2.'
|
|
38
41
|
RESTRICT_ON_SEND = %i[include prepend].freeze
|
|
39
42
|
|
|
40
43
|
minimum_target_ruby_version 3.1
|
|
@@ -44,7 +47,11 @@ module RuboCop
|
|
|
44
47
|
return unless (parent = node.parent)
|
|
45
48
|
return unless parent.block_type? && parent.method?(:refine)
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
template = target_ruby_version >= 3.2 ? MSG_REMOVED : MSG
|
|
51
|
+
message = format(template, current: node.method_name)
|
|
52
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
|
53
|
+
corrector.replace(node.loc.selector, 'import_methods')
|
|
54
|
+
end
|
|
48
55
|
end
|
|
49
56
|
end
|
|
50
57
|
end
|
|
@@ -26,7 +26,15 @@ module RuboCop
|
|
|
26
26
|
return if node.ancestors.none?(&:conditional?)
|
|
27
27
|
return if part_of_ignored_node?(node)
|
|
28
28
|
|
|
29
|
-
add_offense(node)
|
|
29
|
+
add_offense(node) do |corrector|
|
|
30
|
+
# `!` binds tighter than `=~`, so `!/foo/ =~ $_` would parse as
|
|
31
|
+
# `(!/foo/) =~ $_`. Wrap the match in parentheses to preserve the meaning.
|
|
32
|
+
if node.parent&.send_type? && node.parent.method?(:!)
|
|
33
|
+
corrector.replace(node.parent, "!(#{node.source} =~ $_)")
|
|
34
|
+
else
|
|
35
|
+
corrector.replace(node, "#{node.source} =~ $_")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
30
38
|
|
|
31
39
|
ignore_node(node)
|
|
32
40
|
end
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
# Checks for
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
6
|
+
# Checks for method calls with at least one argument where no parentheses
|
|
7
|
+
# are used around the parameter list, and the call could be misread as an
|
|
8
|
+
# operand of a boolean operator (`&&` or `||`). Two forms are flagged:
|
|
9
|
+
#
|
|
10
|
+
# * a predicate method whose last argument is a `&&`/`||` expression, and
|
|
11
|
+
# * any method whose first argument is a ternary expression with a
|
|
12
|
+
# `&&`/`||` condition.
|
|
10
13
|
#
|
|
11
14
|
# The idea behind warning for these constructs is that the user might
|
|
12
15
|
# be under the impression that the return value from the method call is
|
|
@@ -23,6 +26,12 @@ module RuboCop
|
|
|
23
26
|
# if day.is?(:tuesday) && month == :jan
|
|
24
27
|
# # ...
|
|
25
28
|
# end
|
|
29
|
+
#
|
|
30
|
+
# # bad
|
|
31
|
+
# foo a && b ? c : d
|
|
32
|
+
#
|
|
33
|
+
# # good
|
|
34
|
+
# foo(a && b ? c : d)
|
|
26
35
|
class RequireParentheses < Base
|
|
27
36
|
include RangeHelp
|
|
28
37
|
|
|
@@ -38,12 +38,13 @@ module RuboCop
|
|
|
38
38
|
# 42)
|
|
39
39
|
#
|
|
40
40
|
class RequireRangeParentheses < Base
|
|
41
|
-
MSG = 'Wrap the
|
|
41
|
+
MSG = 'Wrap the range literal `%<range>s` in parentheses ' \
|
|
42
|
+
'to avoid confusion with an endless range.'
|
|
42
43
|
|
|
43
44
|
def on_irange(node)
|
|
44
45
|
return if node.parent&.begin_type?
|
|
45
46
|
return unless node.begin && node.end
|
|
46
|
-
return if same_line?(node.
|
|
47
|
+
return if same_line?(node.loc.operator, node.end)
|
|
47
48
|
|
|
48
49
|
message = format(MSG, range: "#{node.begin.source}#{node.loc.operator.source}")
|
|
49
50
|
|