rubocop 1.84.2 → 1.88.1
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/config/default.yml +183 -87
- data/config/obsoletion.yml +26 -1
- data/lib/rubocop/cache_config.rb +1 -1
- data/lib/rubocop/cli/command/auto_generate_config.rb +34 -2
- data/lib/rubocop/cli/command/list_enabled_cops_for.rb +40 -0
- 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 +9 -7
- data/lib/rubocop/comment_config.rb +12 -15
- data/lib/rubocop/config.rb +14 -10
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_loader.rb +17 -2
- data/lib/rubocop/config_loader_resolver.rb +13 -4
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -2
- data/lib/rubocop/config_store.rb +2 -2
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +2 -1
- data/lib/rubocop/cop/base.rb +25 -4
- data/lib/rubocop/cop/bundler/gem_comment.rb +5 -3
- 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/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 +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/development_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/require_mfa.rb +9 -6
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
- data/lib/rubocop/cop/internal_affairs/itblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +5 -3
- 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 +58 -4
- data/lib/rubocop/cop/layout/class_structure.rb +8 -4
- data/lib/rubocop/cop/layout/condition_position.rb +13 -3
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +23 -7
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +15 -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 +8 -5
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +20 -15
- data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +40 -0
- data/lib/rubocop/cop/layout/line_length.rb +5 -3
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +9 -2
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +53 -3
- 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/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +3 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +6 -2
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -0
- 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/assignment_in_condition.rb +13 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +1 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
- 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/data_define_override.rb +63 -0
- data/lib/rubocop/cop/lint/debugger.rb +0 -1
- data/lib/rubocop/cop/lint/deprecated_constants.rb +2 -8
- data/lib/rubocop/cop/lint/duplicate_methods.rb +55 -8
- 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_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 +1 -0
- 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_assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +8 -11
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +5 -5
- 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 +16 -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 +4 -1
- 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_safe_navigation.rb +36 -12
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +4 -0
- 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_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 +24 -1
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -1
- 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/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 +35 -2
- 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/unmodified_reduce_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +2 -2
- 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/useless_assignment.rb +14 -14
- 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_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 +35 -9
- data/lib/rubocop/cop/lint/void.rb +32 -12
- 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 +2 -2
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +38 -7
- 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 +1 -1
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
- data/lib/rubocop/cop/mixin/configurable_max.rb +6 -5
- data/lib/rubocop/cop/mixin/hash_subset.rb +8 -0
- data/lib/rubocop/cop/mixin/hash_transform_method/autocorrection.rb +63 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +14 -60
- data/lib/rubocop/cop/mixin/project_index_help.rb +48 -0
- 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/file_name.rb +4 -3
- data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +10 -1
- data/lib/rubocop/cop/naming/predicate_method.rb +2 -2
- data/lib/rubocop/cop/naming/predicate_prefix.rb +1 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -4
- data/lib/rubocop/cop/offense.rb +8 -0
- 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 +2 -2
- data/lib/rubocop/cop/security/marshal_load.rb +1 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +14 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +15 -3
- 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 +4 -0
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +3 -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 +3 -1
- data/lib/rubocop/cop/style/begin_block.rb +3 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +37 -31
- data/lib/rubocop/cop/style/case_equality.rb +18 -2
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +18 -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 +6 -5
- data/lib/rubocop/cop/style/constant_visibility.rb +4 -1
- data/lib/rubocop/cop/style/copyright.rb +22 -11
- data/lib/rubocop/cop/style/data_inheritance.rb +4 -0
- 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/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/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_case_condition.rb +12 -2
- data/lib/rubocop/cop/style/empty_class_definition.rb +51 -21
- 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 +7 -2
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +30 -20
- 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 +8 -3
- data/lib/rubocop/cop/style/env_home.rb +4 -0
- 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/fetch_env_var.rb +1 -1
- 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/for.rb +3 -0
- data/lib/rubocop/cop/style/format_string.rb +17 -4
- data/lib/rubocop/cop/style/format_string_token.rb +29 -2
- data/lib/rubocop/cop/style/global_vars.rb +5 -2
- data/lib/rubocop/cop/style/guard_clause.rb +9 -6
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +21 -5
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -1
- data/lib/rubocop/cop/style/hash_lookup_method.rb +19 -7
- data/lib/rubocop/cop/style/hash_slice.rb +16 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +2 -0
- 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 +15 -4
- data/lib/rubocop/cop/style/if_with_semicolon.rb +16 -6
- data/lib/rubocop/cop/style/inline_comment.rb +5 -2
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
- data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +7 -3
- data/lib/rubocop/cop/style/lambda.rb +7 -1
- 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 +1 -1
- data/lib/rubocop/cop/style/map_join.rb +123 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -3
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +6 -2
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/min_max_comparison.rb +4 -1
- data/lib/rubocop/cop/style/module_member_existence_check.rb +7 -14
- data/lib/rubocop/cop/style/multiline_if_then.rb +4 -2
- data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +11 -4
- data/lib/rubocop/cop/style/mutable_constant.rb +106 -12
- data/lib/rubocop/cop/style/nil_comparison.rb +2 -3
- 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/one_class_per_file.rb +115 -0
- data/lib/rubocop/cop/style/one_line_conditional.rb +4 -3
- data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
- 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 +23 -3
- 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/perl_backrefs.rb +5 -3
- data/lib/rubocop/cop/style/predicate_with_kind.rb +84 -0
- 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_array_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +3 -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 +6 -0
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +29 -0
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +26 -10
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +27 -3
- data/lib/rubocop/cop/style/redundant_min_max_by.rb +93 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +25 -22
- data/lib/rubocop/cop/style/redundant_percent_q.rb +4 -1
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +2 -2
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -4
- data/lib/rubocop/cop/style/redundant_return.rb +3 -1
- data/lib/rubocop/cop/style/redundant_self.rb +11 -2
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
- data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +133 -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/safe_navigation.rb +7 -7
- 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 +22 -5
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +18 -5
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -2
- data/lib/rubocop/cop/style/special_global_vars.rb +6 -1
- data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +13 -0
- 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/ternary_parentheses.rb +11 -0
- data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -2
- 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 +7 -8
- 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 +86 -35
- data/lib/rubocop/cop/variable_force/branch.rb +2 -2
- data/lib/rubocop/directive_comment.rb +2 -1
- data/lib/rubocop/file_patterns.rb +9 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -9
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +0 -2
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +22 -21
- data/lib/rubocop/lsp/diagnostic.rb +1 -0
- data/lib/rubocop/lsp/routes.rb +10 -3
- data/lib/rubocop/lsp/runtime.rb +1 -2
- 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/result_cache.rb +22 -10
- data/lib/rubocop/rspec/cop_helper.rb +8 -0
- data/lib/rubocop/rspec/shared_contexts.rb +32 -2
- data/lib/rubocop/runner.rb +126 -53
- data/lib/rubocop/server/cache.rb +5 -7
- data/lib/rubocop/server/core.rb +8 -0
- data/lib/rubocop/target_finder.rb +14 -7
- data/lib/rubocop/target_ruby.rb +18 -12
- data/lib/rubocop/version.rb +21 -3
- data/lib/rubocop.rb +22 -96
- metadata +27 -5
|
@@ -24,8 +24,25 @@ module RuboCop
|
|
|
24
24
|
MSG = 'Interpolation in single quoted string detected. ' \
|
|
25
25
|
'Use double quoted strings if you need interpolation.'
|
|
26
26
|
|
|
27
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
28
27
|
def on_str(node)
|
|
28
|
+
check(node)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# A multiline single-quoted string is parsed as a `dstr` of `str` segments, so it
|
|
32
|
+
# is not covered by `on_str`. Inspect single-quoted `dstr`s here; double-quoted
|
|
33
|
+
# interpolation is also a `dstr`, hence the delimiter check.
|
|
34
|
+
def on_dstr(node)
|
|
35
|
+
# A heredoc is also a `dstr`, but its `loc` is a `Parser::Source::Map::Heredoc`
|
|
36
|
+
# with no `begin`, so bail before touching it.
|
|
37
|
+
return if heredoc?(node)
|
|
38
|
+
|
|
39
|
+
check(node) if node.loc.begin&.source == "'"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
45
|
+
def check(node)
|
|
29
46
|
return if node.parent&.regexp_type?
|
|
30
47
|
return unless /(?<!\\)#\{.*\}/.match?(node.source)
|
|
31
48
|
return if heredoc?(node)
|
|
@@ -36,8 +53,6 @@ module RuboCop
|
|
|
36
53
|
end
|
|
37
54
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
38
55
|
|
|
39
|
-
private
|
|
40
|
-
|
|
41
56
|
def autocorrect(corrector, node)
|
|
42
57
|
starting_token, ending_token = if node.source.include?('"')
|
|
43
58
|
['%{', '}']
|
|
@@ -54,9 +69,14 @@ module RuboCop
|
|
|
54
69
|
end
|
|
55
70
|
|
|
56
71
|
def valid_syntax?(node)
|
|
57
|
-
double_quoted_string = node.source.
|
|
72
|
+
double_quoted_string = if node.source.include?('"')
|
|
73
|
+
node.source.sub(/\A'/, '%{').sub(/'\z/, '}')
|
|
74
|
+
else
|
|
75
|
+
node.source.gsub(/\A'|'\z/, '"')
|
|
76
|
+
end
|
|
58
77
|
|
|
59
|
-
parse(double_quoted_string)
|
|
78
|
+
processed_source = parse(double_quoted_string)
|
|
79
|
+
processed_source.valid_syntax? && processed_source.ast.dstr_type?
|
|
60
80
|
end
|
|
61
81
|
end
|
|
62
82
|
end
|
|
@@ -56,7 +56,17 @@ module RuboCop
|
|
|
56
56
|
def traverse_node(node, &block)
|
|
57
57
|
yield node if node.equals_asgn?
|
|
58
58
|
|
|
59
|
-
node.each_child_node
|
|
59
|
+
node.each_child_node do |child|
|
|
60
|
+
next if scope_body?(node, child)
|
|
61
|
+
|
|
62
|
+
traverse_node(child, &block)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# An assignment inside a block or method body within the condition belongs to
|
|
67
|
+
# that inner scope rather than the condition itself, so it is not inspected.
|
|
68
|
+
def scope_body?(node, child)
|
|
69
|
+
node.type?(:any_block, :any_def) && child == node.body
|
|
60
70
|
end
|
|
61
71
|
|
|
62
72
|
def all_literals?(node)
|
|
@@ -119,11 +119,13 @@ module RuboCop
|
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
def autocorrected_value_for_string(node)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
122
|
+
return node.source.delete_prefix('"').delete_suffix('"') unless node.value.valid_encoding?
|
|
123
|
+
|
|
124
|
+
escape_string_content(node.children.last)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def escape_string_content(string)
|
|
128
|
+
string.gsub(/[\\"]|#(?=[@{$])/, '\\\\\&')
|
|
127
129
|
end
|
|
128
130
|
|
|
129
131
|
def autocorrected_value_for_symbol(node)
|
|
@@ -134,12 +136,7 @@ module RuboCop
|
|
|
134
136
|
end
|
|
135
137
|
|
|
136
138
|
def autocorrected_value_in_hash_for_symbol(node)
|
|
137
|
-
|
|
138
|
-
if / |"|'/.match?(node.value.to_s)
|
|
139
|
-
":\\\"#{node.value.to_s.gsub('"') { '\\\\\"' }}\\\""
|
|
140
|
-
else
|
|
141
|
-
":#{node.value}"
|
|
142
|
-
end
|
|
139
|
+
escape_string_content(node.value.inspect)
|
|
143
140
|
end
|
|
144
141
|
|
|
145
142
|
def autocorrected_value_for_array(node)
|
|
@@ -6,10 +6,10 @@ module RuboCop
|
|
|
6
6
|
module Lint
|
|
7
7
|
# Checks that there is an `# rubocop:enable ...` statement
|
|
8
8
|
# after a `# rubocop:disable ...` statement. This will prevent leaving
|
|
9
|
-
# cop disables on wide ranges of code, that
|
|
9
|
+
# cop disables on wide ranges of code, that later contributors to
|
|
10
10
|
# a file wouldn't be aware of.
|
|
11
11
|
#
|
|
12
|
-
# You can set `
|
|
12
|
+
# You can set `MaxRangeSize` to define the maximum number of
|
|
13
13
|
# consecutive lines a cop can be disabled for.
|
|
14
14
|
#
|
|
15
15
|
# - `.inf` any size (default)
|
|
@@ -23,7 +23,7 @@ module RuboCop
|
|
|
23
23
|
# # rubocop:enable SomeCop
|
|
24
24
|
# ----
|
|
25
25
|
#
|
|
26
|
-
# @example
|
|
26
|
+
# @example MaxRangeSize: .inf (default)
|
|
27
27
|
#
|
|
28
28
|
# # good
|
|
29
29
|
# # rubocop:disable Layout/SpaceAroundOperators
|
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
|
37
37
|
# x= 0
|
|
38
38
|
# # EOF
|
|
39
39
|
#
|
|
40
|
-
# @example
|
|
40
|
+
# @example MaxRangeSize: 2
|
|
41
41
|
#
|
|
42
42
|
# # good
|
|
43
43
|
# # rubocop:disable Layout/SpaceAroundOperators
|
|
@@ -94,7 +94,7 @@ module RuboCop
|
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
def max_range
|
|
97
|
-
@max_range ||= cop_config['
|
|
97
|
+
@max_range ||= cop_config['MaxRangeSize']
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
def message(cop, comment, type = 'cop')
|
|
@@ -4,8 +4,8 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
6
|
# In math and Python, we can use `x < y < z` style comparison to compare
|
|
7
|
-
# multiple
|
|
8
|
-
# the comparison is not syntax error. This cop checks the bad usage of
|
|
7
|
+
# multiple values. However, we can't use the comparison in Ruby. However,
|
|
8
|
+
# the comparison is not a syntax error. This cop checks the bad usage of
|
|
9
9
|
# comparison operators.
|
|
10
10
|
#
|
|
11
11
|
# @example
|
|
@@ -31,6 +31,7 @@ module RuboCop
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
alias on_numblock on_block
|
|
34
|
+
alias on_itblock on_block
|
|
34
35
|
|
|
35
36
|
private
|
|
36
37
|
|
|
@@ -39,6 +40,7 @@ module RuboCop
|
|
|
39
40
|
{
|
|
40
41
|
(block (call _recv {:reduce :inject} !sym) _blockargs $(begin ...))
|
|
41
42
|
(numblock (call _recv {:reduce :inject} !sym) _argscount $(begin ...))
|
|
43
|
+
(itblock (call _recv {:reduce :inject} !sym) _argscount $(begin ...))
|
|
42
44
|
}
|
|
43
45
|
PATTERN
|
|
44
46
|
|
|
@@ -41,6 +41,8 @@ module RuboCop
|
|
|
41
41
|
def on_lvasgn(node)
|
|
42
42
|
node.each_node(:kwbegin) do |kwbegin_node|
|
|
43
43
|
kwbegin_node.each_node(:return) do |return_node|
|
|
44
|
+
next if return_from_inner_scope?(return_node, kwbegin_node)
|
|
45
|
+
|
|
44
46
|
add_offense(return_node)
|
|
45
47
|
end
|
|
46
48
|
end
|
|
@@ -51,6 +53,20 @@ module RuboCop
|
|
|
51
53
|
alias on_casgn on_lvasgn
|
|
52
54
|
alias on_or_asgn on_lvasgn
|
|
53
55
|
alias on_op_asgn on_lvasgn
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
# A `return` inside a nested method definition or lambda within the
|
|
60
|
+
# `begin..end` returns from that inner scope rather than the assignment
|
|
61
|
+
# context, so it is not an offense. A `return` inside a plain block (or
|
|
62
|
+
# `proc`) does propagate out, so it remains an offense.
|
|
63
|
+
def return_from_inner_scope?(return_node, kwbegin_node)
|
|
64
|
+
return_node.each_ancestor do |ancestor|
|
|
65
|
+
break if ancestor == kwbegin_node
|
|
66
|
+
return true if ancestor.any_def_type? || (ancestor.any_block_type? && ancestor.lambda?)
|
|
67
|
+
end
|
|
68
|
+
false
|
|
69
|
+
end
|
|
54
70
|
end
|
|
55
71
|
end
|
|
56
72
|
end
|
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
|
12
12
|
# always sort the list.
|
|
13
13
|
#
|
|
14
14
|
# `Dir.glob` and `Dir[]` sort globbed results by default in Ruby 3.0.
|
|
15
|
-
# So all bad cases are acceptable when Ruby 3.0 or higher
|
|
15
|
+
# So all bad cases are acceptable when Ruby 3.0 or higher is used.
|
|
16
16
|
#
|
|
17
17
|
# NOTE: This cop will be deprecated and removed when supporting only Ruby 3.0 and higher.
|
|
18
18
|
#
|
|
@@ -65,7 +65,9 @@ module RuboCop
|
|
|
65
65
|
|
|
66
66
|
maximum_target_ruby_version 2.7
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
# NOTE: itblock is not handled because this cop is limited to Ruby <= 2.7
|
|
69
|
+
# via `maximum_target_ruby_version`, so itblock nodes (Ruby 3.4+) are never encountered.
|
|
70
|
+
def on_block(node) # rubocop:disable InternalAffairs/ItblockHandler
|
|
69
71
|
return unless node.body
|
|
70
72
|
return unless unsorted_dir_loop?(node.send_node)
|
|
71
73
|
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
# Warns the usage of unsafe number conversions. Unsafe
|
|
7
|
-
# number conversion can cause unexpected error if auto type conversion
|
|
8
|
-
# fails.
|
|
6
|
+
# Warns against the usage of unsafe number conversions. Unsafe
|
|
7
|
+
# number conversion can cause an unexpected error if auto type conversion
|
|
8
|
+
# fails. The cop prefers parsing with a number class instead.
|
|
9
9
|
#
|
|
10
10
|
# Conversion with `Integer`, `Float`, etc. will raise an `ArgumentError`
|
|
11
11
|
# if given input that is not numeric (eg. an empty string), whereas
|
|
@@ -14,10 +14,10 @@ module RuboCop
|
|
|
14
14
|
# always correct to raise if a value is not numeric.
|
|
15
15
|
#
|
|
16
16
|
# NOTE: Some values cannot be converted properly using one of the `Kernel`
|
|
17
|
-
#
|
|
17
|
+
# methods (for instance, `Time` and `DateTime` values are allowed by this
|
|
18
18
|
# cop by default). Similarly, Rails' duration methods do not work well
|
|
19
19
|
# with `Integer()` and can be allowed with `AllowedMethods`. By default,
|
|
20
|
-
# there are no methods
|
|
20
|
+
# there are no allowed methods.
|
|
21
21
|
#
|
|
22
22
|
# @safety
|
|
23
23
|
# Autocorrection is unsafe because it is not guaranteed that the
|
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
|
66
66
|
# # good
|
|
67
67
|
# 10.minutes.to_i
|
|
68
68
|
#
|
|
69
|
-
# @example
|
|
69
|
+
# @example AllowedClasses: [Time, DateTime] (default)
|
|
70
70
|
#
|
|
71
71
|
# # good
|
|
72
72
|
# Time.now.to_datetime.to_i
|
|
@@ -117,11 +117,11 @@ module RuboCop
|
|
|
117
117
|
|
|
118
118
|
message = format(
|
|
119
119
|
MSG,
|
|
120
|
-
current:
|
|
120
|
+
current: current_method(node, receiver, to_method),
|
|
121
121
|
corrected_method: correct_method(node, receiver)
|
|
122
122
|
)
|
|
123
123
|
add_offense(node, message: message) do |corrector|
|
|
124
|
-
next if part_of_ignored_node?(node)
|
|
124
|
+
next if safe_navigation?(node) || part_of_ignored_node?(node)
|
|
125
125
|
|
|
126
126
|
corrector.replace(node, correct_method(node, node.receiver))
|
|
127
127
|
|
|
@@ -156,13 +156,22 @@ module RuboCop
|
|
|
156
156
|
"{ |i| #{body} }"
|
|
157
157
|
end
|
|
158
158
|
|
|
159
|
+
def current_method(node, receiver, to_method)
|
|
160
|
+
operator = node.csend_type? ? '&.' : '.'
|
|
161
|
+
"#{receiver.source}#{operator}#{to_method}"
|
|
162
|
+
end
|
|
163
|
+
|
|
159
164
|
def remove_parentheses(corrector, node)
|
|
160
165
|
corrector.replace(node.loc.begin, ' ')
|
|
161
166
|
corrector.remove(node.loc.end)
|
|
162
167
|
end
|
|
163
168
|
|
|
169
|
+
def safe_navigation?(node)
|
|
170
|
+
node.csend_type? || node.each_descendant(:csend).any?
|
|
171
|
+
end
|
|
172
|
+
|
|
164
173
|
def allow_receiver?(receiver)
|
|
165
|
-
if receiver.numeric_type? || (receiver.
|
|
174
|
+
if receiver.numeric_type? || (receiver.call_type? &&
|
|
166
175
|
(conversion_method?(receiver.method_name) ||
|
|
167
176
|
allowed_method_name?(receiver.method_name)))
|
|
168
177
|
true
|
|
@@ -188,7 +197,7 @@ module RuboCop
|
|
|
188
197
|
end
|
|
189
198
|
|
|
190
199
|
def ignored_classes
|
|
191
|
-
cop_config.fetch('
|
|
200
|
+
cop_config.fetch('AllowedClasses', [])
|
|
192
201
|
end
|
|
193
202
|
|
|
194
203
|
def ignored_class?(name)
|
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
|
16
16
|
# ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
|
|
17
17
|
# -e:1: _1 is reserved for numbered parameter
|
|
18
18
|
#
|
|
19
|
-
# NOTE: The
|
|
19
|
+
# NOTE: The numbered parameters are from `_1` to `_9`. This cop checks `_0`, and over `_10`
|
|
20
20
|
# as well to prevent confusion.
|
|
21
21
|
#
|
|
22
22
|
# @example
|
|
@@ -58,6 +58,9 @@ module RuboCop
|
|
|
58
58
|
'(op-asgn (lvasgn $_lhs) $_operation ({int lvar} $_rhs))'
|
|
59
59
|
|
|
60
60
|
def on_send(node)
|
|
61
|
+
# Safe navigation short-circuits to `nil` when the receiver is `nil`, so the
|
|
62
|
+
# result is not constant and replacing it with `0`/`1` would change behavior.
|
|
63
|
+
return if node.csend_type?
|
|
61
64
|
return unless (lhs, operation, rhs = operation_with_constant_result?(node))
|
|
62
65
|
return unless (result = constant_result?(lhs, operation, rhs))
|
|
63
66
|
|
|
@@ -38,23 +38,23 @@ module RuboCop
|
|
|
38
38
|
def on_new_investigation
|
|
39
39
|
return if processed_source.buffer.source.empty?
|
|
40
40
|
|
|
41
|
-
encoding_line,
|
|
41
|
+
encoding_line, other_magic_comment_line = magic_comment_lines
|
|
42
42
|
|
|
43
|
-
return unless encoding_line &&
|
|
44
|
-
return if encoding_line <
|
|
43
|
+
return unless encoding_line && other_magic_comment_line
|
|
44
|
+
return if encoding_line < other_magic_comment_line
|
|
45
45
|
|
|
46
46
|
range = processed_source.buffer.line_range(encoding_line + 1)
|
|
47
47
|
|
|
48
48
|
add_offense(range) do |corrector|
|
|
49
|
-
autocorrect(corrector, encoding_line,
|
|
49
|
+
autocorrect(corrector, encoding_line, other_magic_comment_line)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
private
|
|
54
54
|
|
|
55
|
-
def autocorrect(corrector, encoding_line,
|
|
55
|
+
def autocorrect(corrector, encoding_line, other_magic_comment_line)
|
|
56
56
|
range1 = processed_source.buffer.line_range(encoding_line + 1)
|
|
57
|
-
range2 = processed_source.buffer.line_range(
|
|
57
|
+
range2 = processed_source.buffer.line_range(other_magic_comment_line + 1)
|
|
58
58
|
|
|
59
59
|
corrector.replace(range1, range2.source)
|
|
60
60
|
corrector.replace(range2, range1.source)
|
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
|
66
66
|
leading_magic_comments.each.with_index do |comment, index|
|
|
67
67
|
if comment.encoding_specified?
|
|
68
68
|
lines[0] = index
|
|
69
|
-
elsif comment.
|
|
69
|
+
elsif comment.valid?
|
|
70
70
|
lines[1] = index
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -63,19 +63,9 @@ module RuboCop
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def spaces_before_left_parenthesis(node)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
else
|
|
70
|
-
0
|
|
71
|
-
end
|
|
72
|
-
without_receiver = node.source[receiver_length..]
|
|
73
|
-
|
|
74
|
-
# Escape question mark if any.
|
|
75
|
-
method_regexp = Regexp.escape(node.method_name)
|
|
76
|
-
|
|
77
|
-
match = without_receiver.match(/^\s*&?\.?\s*#{method_regexp}(\s+)\(/)
|
|
78
|
-
match ? match.captures[0].length : 0
|
|
66
|
+
return 0 if node.parenthesized? || !node.first_argument.source.start_with?('(')
|
|
67
|
+
|
|
68
|
+
node.first_argument.source_range.begin_pos - node.loc.selector.end_pos
|
|
79
69
|
end
|
|
80
70
|
|
|
81
71
|
def space_range(expr, space_length)
|
|
@@ -283,7 +283,10 @@ module RuboCop
|
|
|
283
283
|
end
|
|
284
284
|
|
|
285
285
|
def matching_range(haystack, needle)
|
|
286
|
-
|
|
286
|
+
# Match the cop name as a whole token so a shorter name is not found inside a
|
|
287
|
+
# longer one that shares its prefix (e.g. `Lint/AmbiguousOperator` in
|
|
288
|
+
# `Lint/AmbiguousOperatorPrecedence`).
|
|
289
|
+
offset = haystack.source.index(/#{Regexp.escape(needle)}(?!\w)/)
|
|
287
290
|
return unless offset
|
|
288
291
|
|
|
289
292
|
offset += haystack.begin_pos
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# The Lint/RedundantCopEnableDirective and Lint/RedundantCopDisableDirective
|
|
4
|
-
# cops need to be disabled so as to be able to provide a (bad) example of an
|
|
5
|
-
# unneeded enable.
|
|
6
|
-
|
|
7
|
-
# rubocop:disable Lint/RedundantCopEnableDirective
|
|
8
|
-
# rubocop:disable Lint/RedundantCopDisableDirective
|
|
9
3
|
module RuboCop
|
|
10
4
|
module Cop
|
|
11
5
|
module Lint
|
|
12
6
|
# Detects instances of rubocop:enable comments that can be
|
|
13
7
|
# removed.
|
|
14
8
|
#
|
|
15
|
-
# When comment enables all cops at once `rubocop:enable all`
|
|
16
|
-
#
|
|
9
|
+
# When a comment enables all cops at once `rubocop:enable all`
|
|
10
|
+
# the cop checks whether any cop was actually enabled.
|
|
17
11
|
#
|
|
18
12
|
# @example
|
|
19
13
|
#
|
|
@@ -80,7 +74,10 @@ module RuboCop
|
|
|
80
74
|
end
|
|
81
75
|
|
|
82
76
|
def cop_name_indention(comment, name)
|
|
83
|
-
|
|
77
|
+
# Match the cop name as a whole token so a shorter name is not found inside a
|
|
78
|
+
# longer one that shares its prefix (e.g. `Layout/EmptyLines` in
|
|
79
|
+
# `Layout/EmptyLinesAfterModuleInclusion`).
|
|
80
|
+
comment.text.index(/#{Regexp.escape(name)}(?!\w)/)
|
|
84
81
|
end
|
|
85
82
|
|
|
86
83
|
def range_with_comma(comment, name)
|
|
@@ -130,6 +127,3 @@ module RuboCop
|
|
|
130
127
|
end
|
|
131
128
|
end
|
|
132
129
|
end
|
|
133
|
-
|
|
134
|
-
# rubocop:enable Lint/RedundantCopDisableDirective
|
|
135
|
-
# rubocop:enable Lint/RedundantCopEnableDirective
|
|
@@ -38,10 +38,10 @@ module RuboCop
|
|
|
38
38
|
GLOB_METHODS = %i[glob []].freeze
|
|
39
39
|
|
|
40
40
|
def on_send(node)
|
|
41
|
-
return unless (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return if multiple_argument?(receiver)
|
|
41
|
+
return unless dir_glob?(node.receiver)
|
|
42
|
+
# `sort` with a comparator block or block-pass changes the order, so it is
|
|
43
|
+
# not redundant with the default sorting performed by `Dir.glob`/`Dir[]`.
|
|
44
|
+
return if sort_with_comparator?(node) || multiple_argument?(node.receiver)
|
|
45
45
|
|
|
46
46
|
selector = node.loc.selector
|
|
47
47
|
|
|
@@ -53,9 +53,20 @@ module RuboCop
|
|
|
53
53
|
|
|
54
54
|
private
|
|
55
55
|
|
|
56
|
+
def dir_glob?(receiver)
|
|
57
|
+
return false unless receiver&.receiver&.const_type?
|
|
58
|
+
return false unless receiver.receiver.short_name == :Dir
|
|
59
|
+
|
|
60
|
+
GLOB_METHODS.include?(receiver.method_name)
|
|
61
|
+
end
|
|
62
|
+
|
|
56
63
|
def multiple_argument?(glob_method)
|
|
57
64
|
glob_method.arguments.count >= 2 || glob_method.first_argument&.splat_type?
|
|
58
65
|
end
|
|
66
|
+
|
|
67
|
+
def sort_with_comparator?(node)
|
|
68
|
+
node.parent&.any_block_type? || node.last_argument&.block_pass_type?
|
|
69
|
+
end
|
|
59
70
|
end
|
|
60
71
|
end
|
|
61
72
|
end
|
|
@@ -62,6 +62,22 @@ module RuboCop
|
|
|
62
62
|
# do_something if attrs.respond_to?(:[])
|
|
63
63
|
#
|
|
64
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
|
|
65
81
|
# while node&.is_a?(BeginNode)
|
|
66
82
|
# node = node.parent
|
|
67
83
|
# end
|
|
@@ -71,8 +87,9 @@ module RuboCop
|
|
|
71
87
|
# node = node.parent
|
|
72
88
|
# end
|
|
73
89
|
#
|
|
74
|
-
# # good - without `&.` this
|
|
90
|
+
# # good - without `&.` this changes the return value for `nil`
|
|
75
91
|
# foo&.respond_to?(:to_a)
|
|
92
|
+
# foo&.respond_to?(:class)
|
|
76
93
|
#
|
|
77
94
|
# # bad - for `nil`s conversion methods return default values for the type
|
|
78
95
|
# foo&.to_h || {}
|
|
@@ -151,22 +168,22 @@ module RuboCop
|
|
|
151
168
|
MSG_NON_NIL = 'Redundant safe navigation on non-nil receiver (detected by analyzing ' \
|
|
152
169
|
'previous code/method invocations).'
|
|
153
170
|
|
|
154
|
-
|
|
171
|
+
NIL_METHODS = nil.methods.to_set.freeze
|
|
155
172
|
|
|
156
173
|
SNAKE_CASE = /\A[[:digit:][:upper:]_]+\z/.freeze
|
|
157
174
|
|
|
158
175
|
GUARANTEED_INSTANCE_METHODS = %i[to_s to_i to_f to_a to_h].freeze
|
|
159
176
|
|
|
160
|
-
# @!method
|
|
161
|
-
def_node_matcher :
|
|
162
|
-
(csend _ :respond_to? (sym %
|
|
177
|
+
# @!method respond_to_nil_method?(node)
|
|
178
|
+
def_node_matcher :respond_to_nil_method?, <<~PATTERN
|
|
179
|
+
(csend _ :respond_to? (sym %NIL_METHODS))
|
|
163
180
|
PATTERN
|
|
164
181
|
|
|
165
182
|
# @!method conversion_with_default?(node)
|
|
166
183
|
def_node_matcher :conversion_with_default?, <<~PATTERN
|
|
167
184
|
{
|
|
168
185
|
(or $(csend _ :to_h) (hash))
|
|
169
|
-
(or (
|
|
186
|
+
(or (any_block $(csend _ :to_h) ...) (hash))
|
|
170
187
|
(or $(csend _ :to_a) (array))
|
|
171
188
|
(or $(csend _ :to_i) (int 0))
|
|
172
189
|
(or $(csend _ :to_f) (float 0.0))
|
|
@@ -174,7 +191,6 @@ module RuboCop
|
|
|
174
191
|
}
|
|
175
192
|
PATTERN
|
|
176
193
|
|
|
177
|
-
# rubocop:disable Metrics/AbcSize
|
|
178
194
|
def on_csend(node)
|
|
179
195
|
range = node.loc.dot
|
|
180
196
|
|
|
@@ -187,14 +203,10 @@ module RuboCop
|
|
|
187
203
|
end
|
|
188
204
|
end
|
|
189
205
|
|
|
190
|
-
|
|
191
|
-
return if !guaranteed_instance?(node.receiver) && !check?(node)
|
|
192
|
-
return if respond_to_nil_specific_method?(node)
|
|
193
|
-
end
|
|
206
|
+
return if guarded_by_nil_receiver?(node)
|
|
194
207
|
|
|
195
208
|
add_offense(range) { |corrector| corrector.replace(range, '.') }
|
|
196
209
|
end
|
|
197
|
-
# rubocop:enable Metrics/AbcSize
|
|
198
210
|
|
|
199
211
|
# rubocop:disable Metrics/AbcSize
|
|
200
212
|
def on_or(node)
|
|
@@ -213,6 +225,18 @@ module RuboCop
|
|
|
213
225
|
|
|
214
226
|
private
|
|
215
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
|
+
|
|
216
240
|
def assume_receiver_instance_exists?(receiver)
|
|
217
241
|
return true if receiver.const_type? && !receiver.short_name.match?(SNAKE_CASE)
|
|
218
242
|
|
|
@@ -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
|