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
|
@@ -17,14 +17,15 @@ module RuboCop
|
|
|
17
17
|
# or with `String.new` or `String()`.
|
|
18
18
|
# * `to_sym` when called on a symbol literal or interpolated symbol.
|
|
19
19
|
# * `to_i` when called on an integer literal or with `Integer()`.
|
|
20
|
-
# * `to_f` when called on a float literal
|
|
20
|
+
# * `to_f` when called on a float literal or with `Float()`.
|
|
21
|
+
# * `to_d` when called with `BigDecimal()`.
|
|
21
22
|
# * `to_r` when called on a rational literal or with `Rational()`.
|
|
22
|
-
# * `to_c` when called on a complex literal
|
|
23
|
+
# * `to_c` when called on a complex literal or with `Complex()`.
|
|
23
24
|
# * `to_a` when called on an array literal, or with `Array.new`, `Array()` or `Array[]`.
|
|
24
25
|
# * `to_h` when called on a hash literal, or with `Hash.new`, `Hash()` or `Hash[]`.
|
|
25
26
|
# * `to_set` when called on `Set.new` or `Set[]`.
|
|
26
27
|
#
|
|
27
|
-
# In all cases, chaining one same `to_*` conversion methods listed above is redundant.
|
|
28
|
+
# In all cases, chaining one of the same `to_*` conversion methods listed above is redundant.
|
|
28
29
|
#
|
|
29
30
|
# The cop can also register an offense for chaining conversion methods on methods that are
|
|
30
31
|
# expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s` and
|
|
@@ -63,6 +64,12 @@ module RuboCop
|
|
|
63
64
|
# # in this case, `Integer()` could return `nil`
|
|
64
65
|
# Integer(var, exception: false).to_i
|
|
65
66
|
#
|
|
67
|
+
# # bad
|
|
68
|
+
# BigDecimal(var).to_d
|
|
69
|
+
#
|
|
70
|
+
# # good
|
|
71
|
+
# BigDecimal(var)
|
|
72
|
+
#
|
|
66
73
|
# # bad - chaining the same conversion
|
|
67
74
|
# foo.to_s.to_s
|
|
68
75
|
#
|
|
@@ -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|
|
|
@@ -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,7 +38,8 @@ 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?
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
# Checks for
|
|
6
|
+
# Checks for a file requiring itself with `require_relative`.
|
|
7
7
|
#
|
|
8
8
|
# @example
|
|
9
9
|
#
|
|
@@ -38,11 +38,13 @@ module RuboCop
|
|
|
38
38
|
private
|
|
39
39
|
|
|
40
40
|
def same_file?(file_path, required_feature)
|
|
41
|
-
|
|
42
|
-
end
|
|
41
|
+
return false unless File.extname(file_path) == '.rb'
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
# `require_relative` is resolved relative to the current file's directory, so a
|
|
44
|
+
# bare `foo`/`foo.rb` (no path separator) requires the current file itself. Compare
|
|
45
|
+
# against the basename so this works whether `file_path` is relative or absolute.
|
|
46
|
+
basename = File.basename(file_path, '.rb')
|
|
47
|
+
required_feature == basename || required_feature == "#{basename}.rb"
|
|
46
48
|
end
|
|
47
49
|
end
|
|
48
50
|
end
|
|
@@ -39,7 +39,7 @@ module RuboCop
|
|
|
39
39
|
|
|
40
40
|
MSG = 'Rescuing from `%<invalid_exceptions>s` will raise a ' \
|
|
41
41
|
'`TypeError` instead of catching the actual exception.'
|
|
42
|
-
INVALID_TYPES = %i[array dstr float hash nil int str sym].freeze
|
|
42
|
+
INVALID_TYPES = %i[array complex dstr false float hash nil int rational str sym true].freeze
|
|
43
43
|
|
|
44
44
|
def on_resbody(node)
|
|
45
45
|
invalid_exceptions = invalid_exceptions(node.exceptions)
|
|
@@ -34,23 +34,29 @@ module RuboCop
|
|
|
34
34
|
{
|
|
35
35
|
(send $(csend ...) $_ ...)
|
|
36
36
|
(send $(any_block (csend ...) ...) $_ ...)
|
|
37
|
+
(send $(begin (csend ...)) $_ ...)
|
|
37
38
|
}
|
|
38
39
|
PATTERN
|
|
39
40
|
|
|
41
|
+
# rubocop:disable Metrics/AbcSize
|
|
40
42
|
def on_send(node)
|
|
41
43
|
return unless require_safe_navigation?(node)
|
|
42
44
|
|
|
43
45
|
bad_method?(node) do |safe_nav, method|
|
|
44
46
|
return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
|
|
47
|
+
return if ternary_safe_navigation?(node, safe_nav)
|
|
45
48
|
|
|
46
49
|
begin_range = node.loc.dot || safe_nav.source_range.end
|
|
47
50
|
location = begin_range.join(node.source_range.end)
|
|
48
51
|
|
|
49
52
|
add_offense(location) do |corrector|
|
|
53
|
+
next if ternary_else_branch?(node, safe_nav)
|
|
54
|
+
|
|
50
55
|
autocorrect(corrector, offense_range: location, send_node: node)
|
|
51
56
|
end
|
|
52
57
|
end
|
|
53
58
|
end
|
|
59
|
+
# rubocop:enable Metrics/AbcSize
|
|
54
60
|
|
|
55
61
|
private
|
|
56
62
|
|
|
@@ -61,6 +67,18 @@ module RuboCop
|
|
|
61
67
|
parent.rhs != node || parent.lhs.receiver != parent.rhs.receiver
|
|
62
68
|
end
|
|
63
69
|
|
|
70
|
+
def ternary_safe_navigation?(node, safe_nav)
|
|
71
|
+
return false unless (parent = node.parent)
|
|
72
|
+
|
|
73
|
+
parent.if_type? && node.equal?(parent.if_branch) && parent.condition == safe_nav
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def ternary_else_branch?(node, safe_nav)
|
|
77
|
+
return false unless (parent = node.parent)
|
|
78
|
+
|
|
79
|
+
parent.if_type? && node.equal?(parent.else_branch) && parent.condition == safe_nav
|
|
80
|
+
end
|
|
81
|
+
|
|
64
82
|
# @param [Parser::Source::Range] offense_range
|
|
65
83
|
# @param [RuboCop::AST::SendNode] send_node
|
|
66
84
|
# @return [String]
|
|
@@ -3,10 +3,16 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
#
|
|
6
|
+
# Checks that if safe navigation is used in an `&&` or `||` condition,
|
|
7
7
|
# consistent and appropriate safe navigation, without excess or deficiency,
|
|
8
8
|
# is used for all method calls on the same object.
|
|
9
9
|
#
|
|
10
|
+
# @safety
|
|
11
|
+
# Autocorrection is unsafe because if the receiver is not a local variable
|
|
12
|
+
# but a method call, it may not be idempotent. For example, replacing
|
|
13
|
+
# `foo&.bar` with `foo.bar` could raise `NoMethodError` if `foo` returns
|
|
14
|
+
# `nil` on a subsequent call.
|
|
15
|
+
#
|
|
10
16
|
# @example
|
|
11
17
|
# # bad
|
|
12
18
|
# foo&.bar && foo&.baz
|
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
|
46
46
|
message = format_message_from(processed_source)
|
|
47
47
|
|
|
48
48
|
add_offense(comment, message: message) do
|
|
49
|
-
autocorrect if
|
|
49
|
+
autocorrect if autocorrect?
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -57,6 +57,10 @@ module RuboCop
|
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def executable?(processed_source)
|
|
60
|
+
# Virtual sources (LSP buffers, programmatic `ProcessedSource`) have no file on
|
|
61
|
+
# disk to stat or `chmod`, so treat them as executable to skip the offense.
|
|
62
|
+
return true unless File.exist?(processed_source.file_path)
|
|
63
|
+
|
|
60
64
|
# Returns true if stat is executable or if the operating system
|
|
61
65
|
# doesn't distinguish executable files from nonexecutable files.
|
|
62
66
|
# See at: https://github.com/ruby/ruby/blob/ruby_2_4/file.c#L5362
|
|
@@ -90,12 +90,35 @@ module RuboCop
|
|
|
90
90
|
def on_or_asgn(node)
|
|
91
91
|
return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.lhs)
|
|
92
92
|
|
|
93
|
-
add_offense(node) if
|
|
93
|
+
add_offense(node) if or_and_asgn_self_assignment?(node.lhs, node.rhs)
|
|
94
94
|
end
|
|
95
95
|
alias on_and_asgn on_or_asgn
|
|
96
96
|
|
|
97
97
|
private
|
|
98
98
|
|
|
99
|
+
def or_and_asgn_self_assignment?(lhs, rhs)
|
|
100
|
+
case lhs.type
|
|
101
|
+
when :casgn
|
|
102
|
+
rhs.const_type? && lhs.namespace == rhs.namespace && lhs.short_name == rhs.short_name
|
|
103
|
+
when :send, :csend
|
|
104
|
+
reader_self_assignment?(lhs, rhs)
|
|
105
|
+
else
|
|
106
|
+
rhs_matches_lhs?(rhs, lhs)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Compares two reader calls (attribute `foo.bar` or key `hash['foo']`).
|
|
111
|
+
def reader_self_assignment?(lhs, rhs)
|
|
112
|
+
return false unless rhs.type == lhs.type
|
|
113
|
+
return false unless lhs.method?(rhs.method_name)
|
|
114
|
+
return false unless lhs.receiver == rhs.receiver
|
|
115
|
+
return false unless lhs.arguments == rhs.arguments
|
|
116
|
+
|
|
117
|
+
# `hash[foo] ||= hash[foo]` is intentionally allowed because a method-call key may
|
|
118
|
+
# return different results on each call.
|
|
119
|
+
lhs.arguments.none?(&:call_type?)
|
|
120
|
+
end
|
|
121
|
+
|
|
99
122
|
def multiple_self_assignment?(node)
|
|
100
123
|
lhs = node.lhs
|
|
101
124
|
rhs = node.rhs
|
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
|
45
45
|
# @!method send_with_mixin_argument?(node)
|
|
46
46
|
def_node_matcher :send_with_mixin_argument?, <<~PATTERN
|
|
47
47
|
(send
|
|
48
|
-
(const _ _) {:#{SEND_METHODS.join(' :')}}
|
|
48
|
+
{nil? self (const _ _)} {:#{SEND_METHODS.join(' :')}}
|
|
49
49
|
({sym str} $#mixin_method?)
|
|
50
50
|
$(const _ _)+)
|
|
51
51
|
PATTERN
|
|
@@ -75,6 +75,8 @@ module RuboCop
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def same_conditions_node_different_branch?(variable, outer_local_variable)
|
|
78
|
+
return true if different_case_in_branch?(variable, outer_local_variable)
|
|
79
|
+
|
|
78
80
|
variable_node = variable_node(variable)
|
|
79
81
|
return false unless node_or_its_ascendant_conditional?(variable_node)
|
|
80
82
|
|
|
@@ -88,6 +90,18 @@ module RuboCop
|
|
|
88
90
|
variable_node == outer_local_variable_node.else_branch
|
|
89
91
|
end
|
|
90
92
|
|
|
93
|
+
# `case ... in` binds variables in the pattern itself, so a block argument in one
|
|
94
|
+
# `in` branch does not shadow a pattern variable from a different `in` branch of the
|
|
95
|
+
# same `case` (the branches are mutually exclusive).
|
|
96
|
+
def different_case_in_branch?(variable, outer_local_variable)
|
|
97
|
+
inner_branch = variable.scope.node.each_ancestor(:in_pattern).first
|
|
98
|
+
outer_branch = outer_local_variable.declaration_node.each_ancestor(:in_pattern).first
|
|
99
|
+
|
|
100
|
+
return false unless inner_branch && outer_branch
|
|
101
|
+
|
|
102
|
+
inner_branch != outer_branch && inner_branch.parent == outer_branch.parent
|
|
103
|
+
end
|
|
104
|
+
|
|
91
105
|
def variable_node(variable)
|
|
92
106
|
parent_node = variable.scope.node.parent
|
|
93
107
|
|
|
@@ -56,7 +56,9 @@ module RuboCop
|
|
|
56
56
|
{array hash (send (const {nil? cbase} {:Array :Hash}) :new)}
|
|
57
57
|
!#capacity_keyword_argument?
|
|
58
58
|
])
|
|
59
|
-
(send (const {nil? cbase} :Hash) :new
|
|
59
|
+
(send (const {nil? cbase} :Hash) :new
|
|
60
|
+
{array hash (send (const {nil? cbase} {:Array :Hash}) :new)}
|
|
61
|
+
#capacity_keyword_argument?)
|
|
60
62
|
}
|
|
61
63
|
PATTERN
|
|
62
64
|
|
|
@@ -88,6 +88,10 @@ module RuboCop
|
|
|
88
88
|
return unless (method = numeric_constructor_rescue_nil(node))
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
+
# `Integer(arg, exception: false)` already suppresses the conversion error, so there
|
|
92
|
+
# is nothing unintentionally swallowed; adding another `exception: false` is wrong.
|
|
93
|
+
return if exception_keyword_argument?(method)
|
|
94
|
+
|
|
91
95
|
arguments = method.arguments.map(&:source) << 'exception: false'
|
|
92
96
|
prefer = "#{method.method_name}(#{arguments.join(', ')})"
|
|
93
97
|
prefer = "#{method.receiver.source}#{method.loc.dot.source}#{prefer}" if method.receiver
|
|
@@ -100,6 +104,14 @@ module RuboCop
|
|
|
100
104
|
|
|
101
105
|
private
|
|
102
106
|
|
|
107
|
+
def exception_keyword_argument?(method)
|
|
108
|
+
method.arguments.any? do |argument|
|
|
109
|
+
argument.hash_type? && argument.pairs.any? do |pair|
|
|
110
|
+
pair.key.sym_type? && pair.key.value == :exception
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
103
115
|
def expected_exception_classes_only?(exception_classes)
|
|
104
116
|
return true unless (arguments = exception_classes.first)
|
|
105
117
|
|
|
@@ -77,11 +77,28 @@ module RuboCop
|
|
|
77
77
|
|
|
78
78
|
def on_send(node)
|
|
79
79
|
return unless node.receiver
|
|
80
|
+
return unless (correction = symbol_conversion_correction(node.receiver))
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
register_offense(node, correction: correction)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def symbol_conversion_correction(receiver)
|
|
86
|
+
if receiver.type?(:str, :sym)
|
|
87
|
+
receiver.value.to_sym.inspect
|
|
88
|
+
elsif receiver.dstr_type? && !receiver.heredoc?
|
|
89
|
+
dstr_correction(receiver)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Reuse the already-escaped inner source for a plain `"..."` string so embedded
|
|
94
|
+
# quotes stay escaped. Percent literals (`%{}`, `%Q{}`, ...) and adjacent string
|
|
95
|
+
# concatenation have multi-character or no delimiters, so slicing the source would
|
|
96
|
+
# corrupt them; fall back to the node's value there.
|
|
97
|
+
def dstr_correction(receiver)
|
|
98
|
+
if receiver.loc.begin&.source == '"'
|
|
99
|
+
":\"#{receiver.source[1..-2]}\""
|
|
100
|
+
else
|
|
101
|
+
":\"#{receiver.value.to_sym}\""
|
|
85
102
|
end
|
|
86
103
|
end
|
|
87
104
|
|
|
@@ -26,7 +26,31 @@ module RuboCop
|
|
|
26
26
|
"#{diagnostic.message}\n(Using Ruby #{ruby_version} parser; " \
|
|
27
27
|
'configure using `TargetRubyVersion` parameter, under `AllCops`)'
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
location = diagnostic_location(diagnostic.location)
|
|
30
|
+
add_offense(location, message: message, severity: diagnostic.level)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Expand zero-length diagnostic ranges so that editors and formatters
|
|
34
|
+
# can display them. This typically occurs when the parser reports
|
|
35
|
+
# `unexpected token $end` at EOF.
|
|
36
|
+
def diagnostic_location(location)
|
|
37
|
+
return location if location.size.positive?
|
|
38
|
+
|
|
39
|
+
source_buffer = location.source_buffer
|
|
40
|
+
if location.end_pos < source_buffer.source.size
|
|
41
|
+
location.resize(1)
|
|
42
|
+
elsif location.begin_pos.positive?
|
|
43
|
+
location.adjust(begin_pos: -1)
|
|
44
|
+
else
|
|
45
|
+
location
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Override to skip multiline_ranges check which requires AST.
|
|
50
|
+
# Syntax errors mean the AST is nil, so we go directly to
|
|
51
|
+
# the EOL comment insertion path.
|
|
52
|
+
def disable_offense(offense_range)
|
|
53
|
+
disable_offense_with_eol_or_surround_comment(offense_range)
|
|
30
54
|
end
|
|
31
55
|
|
|
32
56
|
def add_offense_from_error(error)
|
|
@@ -61,7 +61,7 @@ module RuboCop
|
|
|
61
61
|
def arguments_match?(arguments, def_node)
|
|
62
62
|
index = 0
|
|
63
63
|
|
|
64
|
-
def_node.arguments.reject(&:blockarg_type?).all? do |def_arg|
|
|
64
|
+
all_present = def_node.arguments.reject(&:blockarg_type?).all? do |def_arg|
|
|
65
65
|
send_arg = arguments[index]
|
|
66
66
|
case def_arg.type
|
|
67
67
|
when :arg, :restarg, :optarg
|
|
@@ -70,6 +70,33 @@ module RuboCop
|
|
|
70
70
|
|
|
71
71
|
send_arg && argument_match?(send_arg, def_arg)
|
|
72
72
|
end
|
|
73
|
+
|
|
74
|
+
all_present && !extra_positional_arguments?(arguments, def_node)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# The enumerator re-invokes the method with these arguments, so passing more
|
|
78
|
+
# positional arguments than the method accepts raises `ArgumentError` at runtime.
|
|
79
|
+
def extra_positional_arguments?(arguments, def_node)
|
|
80
|
+
return false if variadic_parameters?(def_node) || expandable_arguments?(arguments)
|
|
81
|
+
|
|
82
|
+
positional_arguments(arguments).size > positional_parameters(def_node).size
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def variadic_parameters?(def_node)
|
|
86
|
+
def_node.arguments.any? { |arg| arg.type?(:restarg, :forward_arg) }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# A splat or argument forwarding on the call side can expand to any arity.
|
|
90
|
+
def expandable_arguments?(arguments)
|
|
91
|
+
arguments.any? { |arg| arg.type?(:splat, :forwarded_args, :forwarded_restarg) }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def positional_arguments(arguments)
|
|
95
|
+
arguments.reject { |arg| arg.type?(:hash, :kwsplat, :block_pass, :forwarded_kwrestarg) }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def positional_parameters(def_node)
|
|
99
|
+
def_node.arguments.select { |arg| arg.type?(:arg, :optarg) }
|
|
73
100
|
end
|
|
74
101
|
|
|
75
102
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
@@ -82,9 +109,11 @@ module RuboCop
|
|
|
82
109
|
when :optarg
|
|
83
110
|
send_arg.source == def_arg_name.to_s
|
|
84
111
|
when :kwoptarg, :kwarg
|
|
85
|
-
send_arg
|
|
112
|
+
keyword_hash_argument?(send_arg) &&
|
|
86
113
|
send_arg.pairs.any? { |pair| passing_keyword_arg?(pair, def_arg_name) }
|
|
87
114
|
when :kwrestarg
|
|
115
|
+
return false unless keyword_hash_argument?(send_arg)
|
|
116
|
+
|
|
88
117
|
send_arg.each_child_node(:kwsplat, :forwarded_kwrestarg).any? do |child|
|
|
89
118
|
child.source == def_arg.source
|
|
90
119
|
end
|
|
@@ -93,6 +122,10 @@ module RuboCop
|
|
|
93
122
|
end
|
|
94
123
|
end
|
|
95
124
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
125
|
+
|
|
126
|
+
def keyword_hash_argument?(send_arg)
|
|
127
|
+
send_arg.hash_type? && !send_arg.braces?
|
|
128
|
+
end
|
|
96
129
|
end
|
|
97
130
|
end
|
|
98
131
|
end
|
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
|
40
40
|
# top-level return node's ancestors should not be of block, def, or
|
|
41
41
|
# defs type.
|
|
42
42
|
def top_level_return?(return_node)
|
|
43
|
-
return_node.each_ancestor(:
|
|
43
|
+
return_node.each_ancestor(:any_block, :any_def).none?
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
end
|
|
@@ -32,9 +32,13 @@ module RuboCop
|
|
|
32
32
|
include RangeHelp
|
|
33
33
|
|
|
34
34
|
MSG = 'Avoid leaving a trailing comma in attribute declarations.'
|
|
35
|
+
RESTRICT_ON_SEND = %i[attr_reader attr_writer attr_accessor attr].freeze
|
|
35
36
|
|
|
36
37
|
def on_send(node)
|
|
37
|
-
return unless node.attribute_accessor? && node.last_argument.
|
|
38
|
+
return unless node.attribute_accessor? && node.last_argument.any_def_type?
|
|
39
|
+
# A lone `def` argument (e.g. `attr_reader def foo; end`) has no preceding
|
|
40
|
+
# attribute, so there is no trailing comma to flag.
|
|
41
|
+
return unless node.arguments.size > 1
|
|
38
42
|
|
|
39
43
|
trailing_comma = trailing_comma_range(node)
|
|
40
44
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
# Checks for
|
|
6
|
+
# Checks for Regexps (both literals and via `Regexp.new` / `Regexp.compile`)
|
|
7
7
|
# that contain unescaped `]` characters.
|
|
8
8
|
#
|
|
9
9
|
# It emulates the following Ruby warning:
|
|
@@ -44,9 +44,7 @@ module RuboCop
|
|
|
44
44
|
|
|
45
45
|
def on_regexp(node)
|
|
46
46
|
RuboCop::Util.silence_warnings do
|
|
47
|
-
node.parsed_tree
|
|
48
|
-
detect_offenses(node, expr)
|
|
49
|
-
end
|
|
47
|
+
detect_offenses_in_tree(node, node.parsed_tree)
|
|
50
48
|
end
|
|
51
49
|
end
|
|
52
50
|
|
|
@@ -55,20 +53,46 @@ module RuboCop
|
|
|
55
53
|
return if node.each_descendant(:dstr).any?
|
|
56
54
|
|
|
57
55
|
regexp_constructor(node) do |text|
|
|
58
|
-
parse_regexp(text.value)
|
|
59
|
-
detect_offenses(text, expr)
|
|
60
|
-
end
|
|
56
|
+
detect_offenses_in_tree(text, parse_regexp(text.value))
|
|
61
57
|
end
|
|
62
58
|
end
|
|
63
59
|
|
|
64
60
|
private
|
|
65
61
|
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
# When a character class opens with a bare `]` (e.g. `[^]]`), `regexp_parser` parses
|
|
63
|
+
# `[^]` / `[]` as an empty set and reports the closing `]` as a separate literal.
|
|
64
|
+
# Ruby treats that `]` as the end of the class, not as an unescaped bracket,
|
|
65
|
+
# so the first `]` following an empty set must be skipped.
|
|
66
|
+
def detect_offenses_in_tree(node, tree)
|
|
67
|
+
return unless tree
|
|
68
|
+
|
|
69
|
+
skip_class_closer = false
|
|
70
|
+
tree.each_expression do |expr|
|
|
71
|
+
if empty_character_set?(expr)
|
|
72
|
+
skip_class_closer = true
|
|
73
|
+
elsif expr.type?(:literal)
|
|
74
|
+
skip_class_closer = detect_offenses(node, expr, skip_class_closer)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def empty_character_set?(expr)
|
|
80
|
+
expr.type?(:set) && expr.expressions.empty?
|
|
81
|
+
end
|
|
68
82
|
|
|
83
|
+
def detect_offenses(node, expr, skip_class_closer)
|
|
69
84
|
expr.text.scan(/(?<!\\)\]/) do
|
|
70
85
|
pos = Regexp.last_match.begin(0)
|
|
71
|
-
|
|
86
|
+
|
|
87
|
+
# The first `]` following an empty `[^]` / `[]` set closes the character class.
|
|
88
|
+
if skip_class_closer
|
|
89
|
+
skip_class_closer = false
|
|
90
|
+
next
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# If the unescaped bracket is the first character of the regexp, Ruby does not warn.
|
|
94
|
+
# `pos` is relative to the sub-expression, so add its start offset (`expr.ts`).
|
|
95
|
+
next if (expr.ts + pos).zero?
|
|
72
96
|
|
|
73
97
|
location = range_at_index(node, expr.ts, pos)
|
|
74
98
|
|
|
@@ -76,6 +100,8 @@ module RuboCop
|
|
|
76
100
|
corrector.replace(location, '\]')
|
|
77
101
|
end
|
|
78
102
|
end
|
|
103
|
+
|
|
104
|
+
skip_class_closer
|
|
79
105
|
end
|
|
80
106
|
|
|
81
107
|
def range_at_index(node, index, offset)
|