rubocop 1.48.1 → 1.62.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/LICENSE.txt +1 -1
- data/README.md +7 -5
- data/assets/output.css.erb +159 -0
- data/assets/output.html.erb +1 -160
- data/config/default.yml +217 -35
- data/config/obsoletion.yml +5 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +22 -8
- data/lib/rubocop/cli/command/execute_runner.rb +7 -2
- data/lib/rubocop/cli/command/lsp.rb +19 -0
- data/lib/rubocop/cli.rb +16 -8
- data/lib/rubocop/config.rb +9 -3
- data/lib/rubocop/config_finder.rb +14 -4
- data/lib/rubocop/config_loader.rb +8 -9
- data/lib/rubocop/config_loader_resolver.rb +4 -3
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
- data/lib/rubocop/config_obsoletion.rb +13 -10
- data/lib/rubocop/config_validator.rb +14 -7
- data/lib/rubocop/cop/autocorrect_logic.rb +36 -13
- data/lib/rubocop/cop/base.rb +23 -4
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
- data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
- data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
- data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
- data/lib/rubocop/cop/cop.rb +2 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/exclude_limit.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +3 -3
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +33 -9
- data/lib/rubocop/cop/internal_affairs/example_description.rb +45 -24
- data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +2 -2
- data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
- data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +127 -33
- data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
- data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +29 -2
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +8 -0
- data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
- data/lib/rubocop/cop/layout/dot_position.rb +1 -5
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +27 -4
- data/lib/rubocop/cop/layout/empty_lines.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -0
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +20 -4
- data/lib/rubocop/cop/layout/extra_spacing.rb +3 -4
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +6 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +22 -7
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +25 -34
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +7 -19
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +42 -52
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +38 -55
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +6 -6
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
- data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +8 -27
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +7 -26
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +4 -21
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +6 -30
- data/lib/rubocop/cop/layout/redundant_line_break.rb +33 -11
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
- data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
- data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_operators.rb +53 -21
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_parens.rb +3 -3
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +19 -5
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +3 -3
- data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +6 -7
- data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
- data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
- data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +85 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_super.rb +34 -5
- data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
- data/lib/rubocop/cop/lint/number_conversion.rb +14 -4
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +12 -3
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +72 -8
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
- data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -2
- data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
- data/lib/rubocop/cop/lint/script_permission.rb +3 -3
- data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
- data/lib/rubocop/cop/lint/suppressed_exception.rb +2 -2
- data/lib/rubocop/cop/lint/symbol_conversion.rb +8 -3
- data/lib/rubocop/cop/lint/syntax.rb +6 -3
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +19 -6
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
- data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -3
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
- data/lib/rubocop/cop/lint/useless_method_definition.rb +10 -2
- data/lib/rubocop/cop/lint/useless_times.rb +2 -2
- data/lib/rubocop/cop/lint/void.rb +104 -14
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +8 -2
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +31 -3
- data/lib/rubocop/cop/migration/department_name.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +19 -11
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +4 -3
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/mixin/string_help.rb +4 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +13 -5
- data/lib/rubocop/cop/naming/constant_name.rb +2 -3
- data/lib/rubocop/cop/naming/file_name.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
- data/lib/rubocop/cop/naming/inclusive_language.rb +23 -4
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +26 -11
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
- data/lib/rubocop/cop/naming/variable_name.rb +6 -1
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/security/open.rb +2 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +6 -2
- data/lib/rubocop/cop/style/alias.rb +9 -8
- data/lib/rubocop/cop/style/arguments_forwarding.rb +411 -63
- data/lib/rubocop/cop/style/array_first_last.rb +64 -0
- data/lib/rubocop/cop/style/array_intersect.rb +13 -5
- data/lib/rubocop/cop/style/attr.rb +11 -1
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
- data/lib/rubocop/cop/style/begin_block.rb +1 -2
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +5 -4
- data/lib/rubocop/cop/style/case_like_if.rb +5 -5
- data/lib/rubocop/cop/style/class_and_module_children.rb +2 -2
- data/lib/rubocop/cop/style/class_check.rb +1 -0
- data/lib/rubocop/cop/style/class_equality_comparison.rb +58 -40
- data/lib/rubocop/cop/style/class_vars.rb +3 -3
- data/lib/rubocop/cop/style/collection_compact.rb +35 -12
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
- data/lib/rubocop/cop/style/combinable_loops.rb +36 -8
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +11 -10
- data/lib/rubocop/cop/style/copyright.rb +6 -3
- data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
- data/lib/rubocop/cop/style/date_time.rb +5 -4
- data/lib/rubocop/cop/style/dir.rb +1 -1
- data/lib/rubocop/cop/style/dir_empty.rb +8 -14
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +2 -2
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/double_negation.rb +2 -2
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -7
- data/lib/rubocop/cop/style/each_with_object.rb +2 -2
- data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +8 -19
- data/lib/rubocop/cop/style/exact_regexp_match.rb +69 -0
- data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
- data/lib/rubocop/cop/style/file_empty.rb +3 -3
- data/lib/rubocop/cop/style/file_read.rb +2 -2
- data/lib/rubocop/cop/style/for.rb +3 -1
- data/lib/rubocop/cop/style/format_string.rb +24 -3
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +4 -2
- data/lib/rubocop/cop/style/guard_clause.rb +28 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +106 -33
- data/lib/rubocop/cop/style/hash_except.rb +25 -13
- data/lib/rubocop/cop/style/hash_syntax.rb +9 -2
- data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
- data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +34 -5
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +41 -12
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +14 -13
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +54 -8
- data/lib/rubocop/cop/style/lambda.rb +3 -3
- data/lib/rubocop/cop/style/lambda_call.rb +5 -0
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +8 -10
- data/lib/rubocop/cop/style/map_to_hash.rb +19 -6
- data/lib/rubocop/cop/style/map_to_set.rb +4 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +27 -16
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +45 -40
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
- data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +16 -4
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +6 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
- data/lib/rubocop/cop/style/next.rb +1 -1
- data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +5 -3
- data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +8 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +29 -23
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +4 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +10 -4
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
- data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
- data/lib/rubocop/cop/style/redundant_conditional.rb +2 -10
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +39 -0
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
- data/lib/rubocop/cop/style/redundant_each.rb +7 -4
- data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -7
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +118 -0
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +203 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +72 -23
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +2 -2
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +3 -2
- data/lib/rubocop/cop/style/redundant_return.rb +14 -3
- data/lib/rubocop/cop/style/redundant_self.rb +17 -2
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
- data/lib/rubocop/cop/style/redundant_sort.rb +10 -9
- data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
- data/lib/rubocop/cop/style/redundant_string_escape.rb +5 -4
- data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
- data/lib/rubocop/cop/style/require_order.rb +11 -5
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
- data/lib/rubocop/cop/style/sample.rb +3 -4
- data/lib/rubocop/cop/style/select_by_regexp.rb +22 -11
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +20 -4
- data/lib/rubocop/cop/style/signal_exception.rb +1 -1
- data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
- data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -4
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
- data/lib/rubocop/cop/style/string_chars.rb +1 -0
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
- data/lib/rubocop/cop/style/strip.rb +7 -4
- data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
- data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
- data/lib/rubocop/cop/style/symbol_array.rb +35 -15
- data/lib/rubocop/cop/style/symbol_proc.rb +36 -0
- data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
- data/lib/rubocop/cop/style/unpack_first.rb +11 -14
- data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
- data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
- data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
- data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
- data/lib/rubocop/cop/variable_force.rb +1 -0
- data/lib/rubocop/cops_documentation_generator.rb +26 -7
- data/lib/rubocop/directive_comment.rb +10 -8
- data/lib/rubocop/ext/regexp_node.rb +10 -5
- data/lib/rubocop/ext/regexp_parser.rb +5 -2
- data/lib/rubocop/file_finder.rb +4 -7
- data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
- data/lib/rubocop/formatter/html_formatter.rb +35 -14
- data/lib/rubocop/formatter/json_formatter.rb +0 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
- data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +1 -1
- data/lib/rubocop/lsp/logger.rb +22 -0
- data/lib/rubocop/lsp/routes.rb +246 -0
- data/lib/rubocop/lsp/runtime.rb +99 -0
- data/lib/rubocop/lsp/server.rb +71 -0
- data/lib/rubocop/lsp/severity.rb +27 -0
- data/lib/rubocop/lsp.rb +29 -0
- data/lib/rubocop/magic_comment.rb +13 -11
- data/lib/rubocop/options.rb +26 -10
- data/lib/rubocop/path_util.rb +6 -2
- data/lib/rubocop/result_cache.rb +6 -3
- data/lib/rubocop/rspec/cop_helper.rb +8 -2
- data/lib/rubocop/rspec/expect_offense.rb +8 -8
- data/lib/rubocop/rspec/shared_contexts.rb +42 -18
- data/lib/rubocop/rspec/support.rb +2 -0
- data/lib/rubocop/runner.rb +15 -6
- data/lib/rubocop/server/cache.rb +1 -1
- data/lib/rubocop/server/client_command/exec.rb +3 -3
- data/lib/rubocop/server/helper.rb +1 -1
- data/lib/rubocop/server/server_command/exec.rb +1 -2
- data/lib/rubocop/string_interpreter.rb +3 -3
- data/lib/rubocop/target_finder.rb +91 -81
- data/lib/rubocop/target_ruby.rb +85 -78
- data/lib/rubocop/version.rb +27 -8
- data/lib/rubocop.rb +22 -0
- metadata +59 -14
- /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -0,0 +1,203 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Check for redundant line continuation.
|
7
|
+
#
|
8
|
+
# This cop marks a line continuation as redundant if removing the backslash
|
9
|
+
# does not result in a syntax error.
|
10
|
+
# However, a backslash at the end of a comment or
|
11
|
+
# for string concatenation is not redundant and is not considered an offense.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# foo. \
|
16
|
+
# bar
|
17
|
+
# foo \
|
18
|
+
# &.bar \
|
19
|
+
# .baz
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# foo.
|
23
|
+
# bar
|
24
|
+
# foo
|
25
|
+
# &.bar
|
26
|
+
# .baz
|
27
|
+
#
|
28
|
+
# # bad
|
29
|
+
# [foo, \
|
30
|
+
# bar]
|
31
|
+
# {foo: \
|
32
|
+
# bar}
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
# [foo,
|
36
|
+
# bar]
|
37
|
+
# {foo:
|
38
|
+
# bar}
|
39
|
+
#
|
40
|
+
# # bad
|
41
|
+
# foo(bar, \
|
42
|
+
# baz)
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# foo(bar,
|
46
|
+
# baz)
|
47
|
+
#
|
48
|
+
# # also good - backslash in string concatenation is not redundant
|
49
|
+
# foo('bar' \
|
50
|
+
# 'baz')
|
51
|
+
#
|
52
|
+
# # also good - backslash at the end of a comment is not redundant
|
53
|
+
# foo(bar, # \
|
54
|
+
# baz)
|
55
|
+
#
|
56
|
+
# # also good - backslash at the line following the newline begins with a + or -,
|
57
|
+
# # it is not redundant
|
58
|
+
# 1 \
|
59
|
+
# + 2 \
|
60
|
+
# - 3
|
61
|
+
#
|
62
|
+
# # also good - backslash with newline between the method name and its arguments,
|
63
|
+
# # it is not redundant.
|
64
|
+
# some_method \
|
65
|
+
# (argument)
|
66
|
+
#
|
67
|
+
class RedundantLineContinuation < Base
|
68
|
+
include MatchRange
|
69
|
+
extend AutoCorrector
|
70
|
+
|
71
|
+
MSG = 'Redundant line continuation.'
|
72
|
+
ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
|
73
|
+
ARGUMENT_TYPES = %i[
|
74
|
+
kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
|
75
|
+
tLABEL tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
|
76
|
+
].freeze
|
77
|
+
|
78
|
+
def on_new_investigation
|
79
|
+
return unless processed_source.ast
|
80
|
+
|
81
|
+
each_match_range(processed_source.ast.source_range, /(\\\n)/) do |range|
|
82
|
+
next if require_line_continuation?(range)
|
83
|
+
next unless redundant_line_continuation?(range)
|
84
|
+
|
85
|
+
add_offense(range) do |corrector|
|
86
|
+
corrector.remove_leading(range, 1)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def require_line_continuation?(range)
|
94
|
+
!ends_with_backslash_without_comment?(range.source_line) ||
|
95
|
+
string_concatenation?(range.source_line) ||
|
96
|
+
start_with_arithmetic_operator?(processed_source[range.line]) ||
|
97
|
+
inside_string_literal_or_method_with_argument?(range) ||
|
98
|
+
leading_dot_method_chain_with_blank_line?(range)
|
99
|
+
end
|
100
|
+
|
101
|
+
def ends_with_backslash_without_comment?(source_line)
|
102
|
+
source_line.gsub(/#.+/, '').end_with?('\\')
|
103
|
+
end
|
104
|
+
|
105
|
+
def string_concatenation?(source_line)
|
106
|
+
/["']\s*\\\z/.match?(source_line)
|
107
|
+
end
|
108
|
+
|
109
|
+
def inside_string_literal_or_method_with_argument?(range)
|
110
|
+
processed_source.tokens.each_cons(2).any? do |token, next_token|
|
111
|
+
next if token.line == next_token.line
|
112
|
+
|
113
|
+
inside_string_literal?(range, token) || method_with_argument?(token, next_token)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def leading_dot_method_chain_with_blank_line?(range)
|
118
|
+
return false unless range.source_line.strip.start_with?('.', '&.')
|
119
|
+
|
120
|
+
processed_source[range.line].strip.empty?
|
121
|
+
end
|
122
|
+
|
123
|
+
def redundant_line_continuation?(range)
|
124
|
+
return true unless (node = find_node_for_line(range.line))
|
125
|
+
return false if argument_newline?(node)
|
126
|
+
|
127
|
+
continuation_node = node.parent || node
|
128
|
+
return false if allowed_type?(node) || allowed_type?(continuation_node)
|
129
|
+
|
130
|
+
continuation_node.source.include?("\n") || continuation_node.source.include?("\\\n")
|
131
|
+
end
|
132
|
+
|
133
|
+
def inside_string_literal?(range, token)
|
134
|
+
ALLOWED_STRING_TOKENS.include?(token.type) && token.pos.overlaps?(range)
|
135
|
+
end
|
136
|
+
|
137
|
+
# A method call without parentheses such as the following cannot remove `\`:
|
138
|
+
#
|
139
|
+
# do_something \
|
140
|
+
# argument
|
141
|
+
def method_with_argument?(current_token, next_token)
|
142
|
+
current_token.type == :tIDENTIFIER && ARGUMENT_TYPES.include?(next_token.type)
|
143
|
+
end
|
144
|
+
|
145
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
146
|
+
def argument_newline?(node)
|
147
|
+
node = node.to_a.last if node.assignment?
|
148
|
+
return false if node.parenthesized_call?
|
149
|
+
|
150
|
+
node = node.children.first if node.root? && node.begin_type?
|
151
|
+
|
152
|
+
if argument_is_method?(node) || node.begin_type?
|
153
|
+
argument_newline?(node.children.first)
|
154
|
+
else
|
155
|
+
return false unless method_call_with_arguments?(node)
|
156
|
+
|
157
|
+
!same_line?(node, node.first_argument)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
161
|
+
|
162
|
+
def find_node_for_line(line)
|
163
|
+
processed_source.ast.each_node do |node|
|
164
|
+
return node if same_line?(node, line)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def allowed_type?(node)
|
169
|
+
node.and_type? || node.or_type? || (node.if_type? && node.ternary?)
|
170
|
+
end
|
171
|
+
|
172
|
+
def same_line?(node, line)
|
173
|
+
return false unless (source_range = node.source_range)
|
174
|
+
|
175
|
+
if node.is_a?(AST::StrNode)
|
176
|
+
if node.heredoc?
|
177
|
+
(node.loc.heredoc_body.line..node.loc.heredoc_body.last_line).cover?(line)
|
178
|
+
else
|
179
|
+
(source_range.line..source_range.last_line).cover?(line)
|
180
|
+
end
|
181
|
+
else
|
182
|
+
source_range.line == line
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def argument_is_method?(node)
|
187
|
+
return false unless node.send_type?
|
188
|
+
return false unless (first_argument = node.first_argument)
|
189
|
+
|
190
|
+
method_call_with_arguments?(first_argument)
|
191
|
+
end
|
192
|
+
|
193
|
+
def method_call_with_arguments?(node)
|
194
|
+
node.call_type? && !node.arguments.empty?
|
195
|
+
end
|
196
|
+
|
197
|
+
def start_with_arithmetic_operator?(source_line)
|
198
|
+
%r{\A\s*[+\-*/%]}.match?(source_line)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -17,12 +17,11 @@ module RuboCop
|
|
17
17
|
include Parentheses
|
18
18
|
extend AutoCorrector
|
19
19
|
|
20
|
+
ALLOWED_NODE_TYPES = %i[and or send splat kwsplat].freeze
|
21
|
+
|
20
22
|
# @!method square_brackets?(node)
|
21
23
|
def_node_matcher :square_brackets?, '(send {(send _recv _msg) str array hash} :[] ...)'
|
22
24
|
|
23
|
-
# @!method range_end?(node)
|
24
|
-
def_node_matcher :range_end?, '^^{irange erange}'
|
25
|
-
|
26
25
|
# @!method method_node_and_args(node)
|
27
26
|
def_node_matcher :method_node_and_args, '$(call _recv _msg $...)'
|
28
27
|
|
@@ -54,15 +53,16 @@ module RuboCop
|
|
54
53
|
def ignore_syntax?(node)
|
55
54
|
return false unless (parent = node.parent)
|
56
55
|
|
57
|
-
parent.while_post_type? || parent.until_post_type? ||
|
58
|
-
like_method_argument_parentheses?(parent)
|
56
|
+
parent.while_post_type? || parent.until_post_type? || parent.match_with_lvasgn_type? ||
|
57
|
+
like_method_argument_parentheses?(parent) || multiline_control_flow_statements?(node)
|
59
58
|
end
|
60
59
|
|
61
60
|
def allowed_expression?(node)
|
62
61
|
allowed_ancestor?(node) ||
|
63
62
|
allowed_method_call?(node) ||
|
64
63
|
allowed_multiple_expression?(node) ||
|
65
|
-
allowed_ternary?(node)
|
64
|
+
allowed_ternary?(node) ||
|
65
|
+
node.parent&.range_type?
|
66
66
|
end
|
67
67
|
|
68
68
|
def allowed_ancestor?(node)
|
@@ -85,7 +85,7 @@ module RuboCop
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def allowed_ternary?(node)
|
88
|
-
return unless node&.parent&.if_type?
|
88
|
+
return false unless node&.parent&.if_type?
|
89
89
|
|
90
90
|
node.parent.ternary? && ternary_parentheses_required?
|
91
91
|
end
|
@@ -98,10 +98,19 @@ module RuboCop
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def like_method_argument_parentheses?(node)
|
101
|
-
node.send_type? && node.
|
101
|
+
return false if !node.send_type? && !node.super_type? && !node.yield_type?
|
102
|
+
|
103
|
+
node.arguments.one? && !node.parenthesized? &&
|
102
104
|
!node.arithmetic_operation? && node.first_argument.begin_type?
|
103
105
|
end
|
104
106
|
|
107
|
+
def multiline_control_flow_statements?(node)
|
108
|
+
return false unless (parent = node.parent)
|
109
|
+
return false if parent.single_line?
|
110
|
+
|
111
|
+
parent.return_type? || parent.next_type? || parent.break_type?
|
112
|
+
end
|
113
|
+
|
105
114
|
def empty_parentheses?(node)
|
106
115
|
# Don't flag `()`
|
107
116
|
node.children.empty?
|
@@ -109,34 +118,69 @@ module RuboCop
|
|
109
118
|
|
110
119
|
def first_arg_begins_with_hash_literal?(node)
|
111
120
|
# Don't flag `method ({key: value})` or `method ({key: value}.method)`
|
112
|
-
method_chain_begins_with_hash_literal
|
113
|
-
|
114
|
-
|
121
|
+
hash_literal = method_chain_begins_with_hash_literal(node.children.first)
|
122
|
+
if (root_method = node.each_ancestor(:send).to_a.last)
|
123
|
+
parenthesized = root_method.parenthesized_call?
|
124
|
+
end
|
125
|
+
hash_literal && first_argument?(node) && !parentheses?(hash_literal) && !parenthesized
|
115
126
|
end
|
116
127
|
|
117
|
-
def method_chain_begins_with_hash_literal
|
118
|
-
return
|
119
|
-
return
|
120
|
-
return
|
128
|
+
def method_chain_begins_with_hash_literal(node)
|
129
|
+
return if node.nil?
|
130
|
+
return node if node.hash_type?
|
131
|
+
return unless node.send_type?
|
121
132
|
|
122
|
-
method_chain_begins_with_hash_literal
|
133
|
+
method_chain_begins_with_hash_literal(node.children.first)
|
123
134
|
end
|
124
135
|
|
125
136
|
def check(begin_node)
|
126
137
|
node = begin_node.children.first
|
127
|
-
return offense(begin_node, 'a keyword') if keyword_with_redundant_parentheses?(node)
|
128
|
-
return offense(begin_node, 'a literal') if disallowed_literal?(begin_node, node)
|
129
|
-
return offense(begin_node, 'a variable') if node.variable?
|
130
|
-
return offense(begin_node, 'a constant') if node.const_type?
|
131
138
|
|
132
|
-
|
139
|
+
if (message = find_offense_message(begin_node, node))
|
140
|
+
return offense(begin_node, message)
|
141
|
+
end
|
133
142
|
|
134
143
|
check_send(begin_node, node) if node.call_type?
|
135
144
|
end
|
136
145
|
|
146
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
147
|
+
def find_offense_message(begin_node, node)
|
148
|
+
return 'a keyword' if keyword_with_redundant_parentheses?(node)
|
149
|
+
return 'a literal' if disallowed_literal?(begin_node, node)
|
150
|
+
return 'a variable' if node.variable?
|
151
|
+
return 'a constant' if node.const_type?
|
152
|
+
if node.lambda_or_proc? && (node.braces? || node.send_node.lambda_literal?)
|
153
|
+
return 'an expression'
|
154
|
+
end
|
155
|
+
return 'an interpolated expression' if interpolation?(begin_node)
|
156
|
+
|
157
|
+
return if begin_node.chained?
|
158
|
+
|
159
|
+
if node.and_type? || node.or_type?
|
160
|
+
return if node.semantic_operator? && begin_node.parent
|
161
|
+
return if node.multiline? && allow_in_multiline_conditions?
|
162
|
+
return if ALLOWED_NODE_TYPES.include?(begin_node.parent&.type)
|
163
|
+
return if begin_node.parent&.if_type? && begin_node.parent&.ternary?
|
164
|
+
|
165
|
+
'a logical expression'
|
166
|
+
elsif node.respond_to?(:comparison_method?) && node.comparison_method?
|
167
|
+
return unless begin_node.parent.nil?
|
168
|
+
|
169
|
+
'a comparison expression'
|
170
|
+
end
|
171
|
+
end
|
172
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
173
|
+
|
137
174
|
# @!method interpolation?(node)
|
138
175
|
def_node_matcher :interpolation?, '[^begin ^^dstr]'
|
139
176
|
|
177
|
+
def allow_in_multiline_conditions?
|
178
|
+
parentheses_around_condition_config = config.for_cop('Style/ParenthesesAroundCondition')
|
179
|
+
return false unless parentheses_around_condition_config['Enabled']
|
180
|
+
|
181
|
+
!!parentheses_around_condition_config['AllowInMultilineConditions']
|
182
|
+
end
|
183
|
+
|
140
184
|
def check_send(begin_node, node)
|
141
185
|
return check_unary(begin_node, node) if node.unary_operation?
|
142
186
|
|
@@ -201,7 +245,6 @@ module RuboCop
|
|
201
245
|
def method_call_with_redundant_parentheses?(node)
|
202
246
|
return false unless node.call_type?
|
203
247
|
return false if node.prefix_not?
|
204
|
-
return false if range_end?(node)
|
205
248
|
|
206
249
|
send_node, args = method_node_and_args(node)
|
207
250
|
|
@@ -213,7 +256,13 @@ module RuboCop
|
|
213
256
|
end
|
214
257
|
|
215
258
|
def first_argument?(node)
|
216
|
-
first_send_argument?(node) ||
|
259
|
+
if first_send_argument?(node) ||
|
260
|
+
first_super_argument?(node) ||
|
261
|
+
first_yield_argument?(node)
|
262
|
+
return true
|
263
|
+
end
|
264
|
+
|
265
|
+
node.each_ancestor.any? { |ancestor| first_argument?(ancestor) }
|
217
266
|
end
|
218
267
|
|
219
268
|
# @!method first_send_argument?(node)
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Identifies places where argument can be replaced from
|
7
|
+
# a deterministic regexp to a string.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# 'foo'.byteindex(/f/)
|
12
|
+
# 'foo'.byterindex(/f/)
|
13
|
+
# 'foo'.gsub(/f/, 'x')
|
14
|
+
# 'foo'.gsub!(/f/, 'x')
|
15
|
+
# 'foo'.partition(/f/)
|
16
|
+
# 'foo'.rpartition(/f/)
|
17
|
+
# 'foo'.scan(/f/)
|
18
|
+
# 'foo'.split(/f/)
|
19
|
+
# 'foo'.start_with?(/f/)
|
20
|
+
# 'foo'.sub(/f/, 'x')
|
21
|
+
# 'foo'.sub!(/f/, 'x')
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# 'foo'.byteindex('f')
|
25
|
+
# 'foo'.byterindex('f')
|
26
|
+
# 'foo'.gsub('f', 'x')
|
27
|
+
# 'foo'.gsub!('f', 'x')
|
28
|
+
# 'foo'.partition('f')
|
29
|
+
# 'foo'.rpartition('f')
|
30
|
+
# 'foo'.scan('f')
|
31
|
+
# 'foo'.split('f')
|
32
|
+
# 'foo'.start_with?('f')
|
33
|
+
# 'foo'.sub('f', 'x')
|
34
|
+
# 'foo'.sub!('f', 'x')
|
35
|
+
class RedundantRegexpArgument < Base
|
36
|
+
extend AutoCorrector
|
37
|
+
|
38
|
+
MSG = 'Use string `%<prefer>s` as argument instead of regexp `%<current>s`.'
|
39
|
+
RESTRICT_ON_SEND = %i[
|
40
|
+
byteindex byterindex gsub gsub! partition rpartition scan split start_with? sub sub!
|
41
|
+
].freeze
|
42
|
+
DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze
|
43
|
+
STR_SPECIAL_CHARS = %w[
|
44
|
+
\a \c \C \e \f \M \n \" \' \\\\ \t \b \f \r \u \v \x \0 \1 \2 \3 \4 \5 \6 \7
|
45
|
+
].freeze
|
46
|
+
|
47
|
+
def on_send(node)
|
48
|
+
return unless (regexp_node = node.first_argument)
|
49
|
+
return unless regexp_node.regexp_type?
|
50
|
+
return if !regexp_node.regopt.children.empty? || regexp_node.content == ' '
|
51
|
+
return unless determinist_regexp?(regexp_node)
|
52
|
+
|
53
|
+
prefer = preferred_argument(regexp_node)
|
54
|
+
message = format(MSG, prefer: prefer, current: regexp_node.source)
|
55
|
+
|
56
|
+
add_offense(regexp_node, message: message) do |corrector|
|
57
|
+
corrector.replace(regexp_node, prefer)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
alias on_csend on_send
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def determinist_regexp?(regexp_node)
|
65
|
+
DETERMINISTIC_REGEX.match?(regexp_node.source)
|
66
|
+
end
|
67
|
+
|
68
|
+
def preferred_argument(regexp_node)
|
69
|
+
new_argument = replacement(regexp_node)
|
70
|
+
|
71
|
+
if new_argument.include?('"')
|
72
|
+
new_argument.gsub!("'", "\\\\'")
|
73
|
+
quote = "'"
|
74
|
+
else
|
75
|
+
quote = '"'
|
76
|
+
end
|
77
|
+
|
78
|
+
"#{quote}#{new_argument}#{quote}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def replacement(regexp_node)
|
82
|
+
regexp_content = regexp_node.content
|
83
|
+
stack = []
|
84
|
+
chars = regexp_content.chars.each_with_object([]) do |char, strings|
|
85
|
+
if stack.empty? && char == '\\'
|
86
|
+
stack.push(char)
|
87
|
+
else
|
88
|
+
strings << "#{stack.pop}#{char}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
chars.map do |char|
|
92
|
+
char = char.dup
|
93
|
+
char.delete!('\\') unless STR_SPECIAL_CHARS.include?(char)
|
94
|
+
char
|
95
|
+
end.join
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
next if expr.type != :set || expr.expressions.size != 1
|
64
64
|
next if expr.negative?
|
65
65
|
next if %i[set posixclass nonposixclass].include?(expr.expressions.first.type)
|
66
|
-
next if
|
66
|
+
next if multiple_codepoints?(expr.expressions.first)
|
67
67
|
|
68
68
|
yield expr
|
69
69
|
end
|
@@ -80,7 +80,7 @@ module RuboCop
|
|
80
80
|
!non_redundant
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
83
|
+
def multiple_codepoints?(expression)
|
84
84
|
expression.respond_to?(:codepoints) && expression.codepoints.count >= 2
|
85
85
|
end
|
86
86
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for the instantiation of regexp using redundant `Regexp.new` or `Regexp.compile`.
|
7
|
+
# Autocorrect replaces to regexp literal which is the simplest and fastest.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# Regexp.new(/regexp/)
|
13
|
+
# Regexp.compile(/regexp/)
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# /regexp/
|
17
|
+
# Regexp.new('regexp')
|
18
|
+
# Regexp.compile('regexp')
|
19
|
+
#
|
20
|
+
class RedundantRegexpConstructor < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
23
|
+
MSG = 'Remove the redundant `Regexp.%<method>s`.'
|
24
|
+
RESTRICT_ON_SEND = %i[new compile].freeze
|
25
|
+
|
26
|
+
# @!method redundant_regexp_constructor(node)
|
27
|
+
def_node_matcher :redundant_regexp_constructor, <<~PATTERN
|
28
|
+
(send
|
29
|
+
(const {nil? cbase} :Regexp) {:new :compile}
|
30
|
+
(regexp $... (regopt $...)))
|
31
|
+
PATTERN
|
32
|
+
|
33
|
+
def on_send(node)
|
34
|
+
return unless (regexp, regopt = redundant_regexp_constructor(node))
|
35
|
+
|
36
|
+
add_offense(node, message: format(MSG, method: node.method_name)) do |corrector|
|
37
|
+
pattern = regexp.map(&:source).join
|
38
|
+
regopt = regopt.join
|
39
|
+
|
40
|
+
corrector.replace(node, "/#{pattern}/#{regopt}")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -44,7 +44,8 @@ module RuboCop
|
|
44
44
|
|
45
45
|
def on_regexp(node)
|
46
46
|
each_escape(node) do |char, index, within_character_class|
|
47
|
-
next if allowed_escape?(node, char, index,
|
47
|
+
next if char.valid_encoding? && allowed_escape?(node, char, index,
|
48
|
+
within_character_class)
|
48
49
|
|
49
50
|
location = escape_range_at_index(node, index)
|
50
51
|
|
@@ -107,7 +108,7 @@ module RuboCop
|
|
107
108
|
end
|
108
109
|
end
|
109
110
|
# Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
|
110
|
-
# It's for compatibility with
|
111
|
+
# It's for compatibility with regexp_parser 1.8 and will never be maintained.
|
111
112
|
else
|
112
113
|
def each_escape(node)
|
113
114
|
node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
|
@@ -22,13 +22,18 @@ module RuboCop
|
|
22
22
|
# return something
|
23
23
|
# end
|
24
24
|
#
|
25
|
-
# #
|
25
|
+
# # bad
|
26
26
|
# def test
|
27
27
|
# return something if something_else
|
28
28
|
# end
|
29
29
|
#
|
30
30
|
# # good
|
31
31
|
# def test
|
32
|
+
# something if something_else
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # good
|
36
|
+
# def test
|
32
37
|
# if x
|
33
38
|
# elsif y
|
34
39
|
# else
|
@@ -53,7 +58,7 @@ module RuboCop
|
|
53
58
|
|
54
59
|
MSG = 'Redundant `return` detected.'
|
55
60
|
MULTI_RETURN_MSG = 'To return multiple values, use an array.'
|
56
|
-
RESTRICT_ON_SEND = %i[define_method define_singleton_method].freeze
|
61
|
+
RESTRICT_ON_SEND = %i[define_method define_singleton_method lambda].freeze
|
57
62
|
|
58
63
|
def on_send(node)
|
59
64
|
return unless (parent = node.parent) && parent.block_type?
|
@@ -108,6 +113,7 @@ module RuboCop
|
|
108
113
|
case node.type
|
109
114
|
when :return then check_return_node(node)
|
110
115
|
when :case then check_case_node(node)
|
116
|
+
when :case_match then check_case_match_node(node)
|
111
117
|
when :if then check_if_node(node)
|
112
118
|
when :rescue then check_rescue_node(node)
|
113
119
|
when :resbody then check_resbody_node(node)
|
@@ -135,8 +141,13 @@ module RuboCop
|
|
135
141
|
check_branch(node.else_branch)
|
136
142
|
end
|
137
143
|
|
144
|
+
def check_case_match_node(node)
|
145
|
+
node.in_pattern_branches.each { |in_pattern_node| check_branch(in_pattern_node.body) }
|
146
|
+
check_branch(node.else_branch)
|
147
|
+
end
|
148
|
+
|
138
149
|
def check_if_node(node)
|
139
|
-
return if node.
|
150
|
+
return if node.ternary?
|
140
151
|
|
141
152
|
check_branch(node.if_branch)
|
142
153
|
check_branch(node.else_branch)
|
@@ -17,7 +17,8 @@ module RuboCop
|
|
17
17
|
# protected scope, you cannot send private messages this way.
|
18
18
|
#
|
19
19
|
# Note we allow uses of `self` with operators because it would be awkward
|
20
|
-
# otherwise.
|
20
|
+
# otherwise. Also allows the use of `self.it` without arguments in blocks,
|
21
|
+
# as in `0.times { self.it }`, following `Lint/ItWithoutArgumentsInBlock` cop.
|
21
22
|
#
|
22
23
|
# @example
|
23
24
|
#
|
@@ -107,8 +108,8 @@ module RuboCop
|
|
107
108
|
def on_send(node)
|
108
109
|
return unless node.self_receiver? && regular_method_call?(node)
|
109
110
|
return if node.parent&.mlhs_type?
|
110
|
-
|
111
111
|
return if allowed_send_node?(node)
|
112
|
+
return if it_method_in_block?(node)
|
112
113
|
|
113
114
|
add_offense(node.receiver) do |corrector|
|
114
115
|
corrector.remove(node.receiver)
|
@@ -155,6 +156,20 @@ module RuboCop
|
|
155
156
|
KERNEL_METHODS.include?(node.method_name)
|
156
157
|
end
|
157
158
|
|
159
|
+
# Respects `Lint/ItWithoutArgumentsInBlock` cop and the following Ruby 3.3's warning:
|
160
|
+
#
|
161
|
+
# $ ruby -e '0.times { begin; it; end }'
|
162
|
+
# -e:1: warning: `it` calls without arguments will refer to the first block param in
|
163
|
+
# Ruby 3.4; use it() or self.it
|
164
|
+
#
|
165
|
+
def it_method_in_block?(node)
|
166
|
+
return false unless node.method?(:it)
|
167
|
+
return false unless (block_node = node.each_ancestor(:block).first)
|
168
|
+
return false unless block_node.arguments.empty_and_without_delimiters?
|
169
|
+
|
170
|
+
node.arguments.empty? && !node.block_literal?
|
171
|
+
end
|
172
|
+
|
158
173
|
def regular_method_call?(node)
|
159
174
|
!(node.operator_method? ||
|
160
175
|
KEYWORDS.include?(node.method_name) ||
|
@@ -62,7 +62,9 @@ module RuboCop
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def multiple_statements?(branch)
|
65
|
-
|
65
|
+
return false unless branch&.begin_type?
|
66
|
+
|
67
|
+
!branch.children.empty?
|
66
68
|
end
|
67
69
|
|
68
70
|
def self_assign?(variable, branch)
|
@@ -73,6 +75,11 @@ module RuboCop
|
|
73
75
|
add_offense(offense_branch) do |corrector|
|
74
76
|
assignment_value = opposite_branch ? opposite_branch.source : 'nil'
|
75
77
|
replacement = "#{assignment_value} #{keyword} #{if_node.condition.source}"
|
78
|
+
if opposite_branch.respond_to?(:heredoc?) && opposite_branch.heredoc?
|
79
|
+
replacement += opposite_branch.loc.heredoc_end.with(
|
80
|
+
begin_pos: opposite_branch.source_range.end_pos
|
81
|
+
).source
|
82
|
+
end
|
76
83
|
|
77
84
|
corrector.replace(if_node, replacement)
|
78
85
|
end
|