rubocop 1.50.2 → 1.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -3
- data/config/default.yml +153 -16
- data/config/obsoletion.yml +5 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
- data/lib/rubocop/cli/command/lsp.rb +19 -0
- data/lib/rubocop/cli.rb +4 -1
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_finder.rb +2 -2
- 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/cop/autocorrect_logic.rb +3 -1
- data/lib/rubocop/cop/base.rb +6 -2
- 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/correctors/alignment_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
- data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +32 -8
- data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -21
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
- 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 +7 -7
- data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +7 -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_line_after_guard_clause.rb +42 -9
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +27 -4
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +7 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -6
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -4
- 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/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_method_call_indentation.rb +18 -3
- data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -5
- 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_inside_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
- 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/duplicate_hash_key.rb +2 -1
- 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/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 +78 -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/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_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 +63 -4
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
- 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_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/to_enum_arguments.rb +5 -3
- 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/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +92 -11
- 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/class_length.rb +8 -3
- 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 +32 -4
- 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/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/heredoc.rb +6 -2
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
- 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/string_help.rb +4 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +3 -3
- 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/memoized_instance_variable_name.rb +26 -11
- 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/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 +342 -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 +4 -4
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/class_check.rb +1 -0
- data/lib/rubocop/cop/style/class_equality_comparison.rb +24 -39
- data/lib/rubocop/cop/style/collection_compact.rb +22 -11
- 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/concat_array_literals.rb +2 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
- data/lib/rubocop/cop/style/copyright.rb +5 -2
- 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/document_dynamic_eval_definition.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- 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 -8
- 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_read.rb +2 -2
- data/lib/rubocop/cop/style/for.rb +1 -1
- data/lib/rubocop/cop/style/format_string.rb +24 -3
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -1
- 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 +84 -32
- data/lib/rubocop/cop/style/hash_except.rb +21 -9
- 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 +31 -5
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +6 -5
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -6
- 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 +3 -2
- data/lib/rubocop/cop/style/map_to_hash.rb +10 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -5
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
- 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_ternary_operator.rb +1 -1
- 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/numeric_literals.rb +1 -1
- 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/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +9 -3
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
- 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 +38 -0
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
- data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +118 -0
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +9 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +54 -21
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
- data/lib/rubocop/cop/style/redundant_return.rb +8 -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 +3 -1
- 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 +2 -1
- 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 +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +6 -2
- 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/super_with_args_parentheses.rb +35 -0
- data/lib/rubocop/cop/style/symbol_array.rb +35 -15
- 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 +1 -1
- data/lib/rubocop/ext/regexp_parser.rb +4 -1
- data/lib/rubocop/file_finder.rb +4 -7
- data/lib/rubocop/formatter/html_formatter.rb +5 -4
- data/lib/rubocop/formatter/junit_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 +68 -0
- data/lib/rubocop/lsp/severity.rb +27 -0
- data/lib/rubocop/magic_comment.rb +12 -10
- data/lib/rubocop/options.rb +11 -1
- data/lib/rubocop/result_cache.rb +5 -2
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +2 -3
- data/lib/rubocop/runner.rb +6 -4
- data/lib/rubocop/server/cache.rb +1 -0
- data/lib/rubocop/server/client_command/exec.rb +3 -2
- data/lib/rubocop/string_interpreter.rb +3 -3
- data/lib/rubocop/target_finder.rb +7 -3
- data/lib/rubocop/target_ruby.rb +12 -7
- data/lib/rubocop/version.rb +10 -6
- data/lib/rubocop.rb +19 -0
- metadata +54 -15
@@ -4,12 +4,12 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Ensures that eval methods (`eval`, `instance_eval`, `class_eval`
|
7
|
-
# and `module_eval`) are given filename and line number values (`
|
8
|
-
# and `
|
7
|
+
# and `module_eval`) are given filename and line number values (`\_\_FILE\_\_`
|
8
|
+
# and `\_\_LINE\_\_`). This data is used to ensure that any errors raised
|
9
9
|
# within the evaluated code will be given the correct identification
|
10
10
|
# in a backtrace.
|
11
11
|
#
|
12
|
-
# The cop also checks that the line number given relative to `
|
12
|
+
# The cop also checks that the line number given relative to `\_\_LINE\_\_` is
|
13
13
|
# correct.
|
14
14
|
#
|
15
15
|
# This cop will autocorrect incorrect or missing filename and line number
|
@@ -57,7 +57,7 @@ module RuboCop
|
|
57
57
|
extend AutoCorrector
|
58
58
|
|
59
59
|
MSG = 'Pass `__FILE__` and `__LINE__` to `%<method_name>s`.'
|
60
|
-
MSG_EVAL = 'Pass a binding, `__FILE__
|
60
|
+
MSG_EVAL = 'Pass a binding, `__FILE__`, and `__LINE__` to `eval`.'
|
61
61
|
MSG_INCORRECT_FILE = 'Incorrect file for `%<method_name>s`; ' \
|
62
62
|
'use `%<expected>s` instead of `%<actual>s`.'
|
63
63
|
MSG_INCORRECT_LINE = 'Incorrect line number for `%<method_name>s`; ' \
|
@@ -84,7 +84,7 @@ module RuboCop
|
|
84
84
|
# are considered.
|
85
85
|
return if node.method?(:eval) && !valid_eval_receiver?(node.receiver)
|
86
86
|
|
87
|
-
code = node.
|
87
|
+
code = node.first_argument
|
88
88
|
return unless code && (code.str_type? || code.dstr_type?)
|
89
89
|
|
90
90
|
check_location(node, code)
|
@@ -165,7 +165,7 @@ module RuboCop
|
|
165
165
|
end
|
166
166
|
|
167
167
|
def check_line(node, code)
|
168
|
-
line_node = node.
|
168
|
+
line_node = node.last_argument
|
169
169
|
line_diff = line_difference(line_node, code)
|
170
170
|
if line_diff.zero?
|
171
171
|
add_offense_for_same_line(node, line_node)
|
@@ -210,7 +210,7 @@ module RuboCop
|
|
210
210
|
def add_offense_for_missing_line(node, code)
|
211
211
|
register_offense(node) do |corrector|
|
212
212
|
line_str = missing_line(node, code)
|
213
|
-
corrector.insert_after(node.source_range.end, ", #{line_str}")
|
213
|
+
corrector.insert_after(node.last_argument.source_range.end, ", #{line_str}")
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
@@ -227,7 +227,7 @@ module RuboCop
|
|
227
227
|
end
|
228
228
|
|
229
229
|
def missing_line(node, code)
|
230
|
-
line_diff = line_difference(node.
|
230
|
+
line_diff = line_difference(node.last_argument, code)
|
231
231
|
sign = line_diff.positive? ? :+ : :-
|
232
232
|
expected_line(sign, line_diff)
|
233
233
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for exact regexp match inside Regexp literals.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# string =~ /\Astring\z/
|
12
|
+
# string === /\Astring\z/
|
13
|
+
# string.match(/\Astring\z/)
|
14
|
+
# string.match?(/\Astring\z/)
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# string == 'string'
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# string !~ /\Astring\z/
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# string != 'string'
|
24
|
+
#
|
25
|
+
class ExactRegexpMatch < Base
|
26
|
+
extend AutoCorrector
|
27
|
+
|
28
|
+
MSG = 'Use `%<prefer>s`.'
|
29
|
+
RESTRICT_ON_SEND = %i[=~ === !~ match match?].freeze
|
30
|
+
|
31
|
+
# @!method exact_regexp_match(node)
|
32
|
+
def_node_matcher :exact_regexp_match, <<~PATTERN
|
33
|
+
(call
|
34
|
+
_ {:=~ :=== :!~ :match :match?}
|
35
|
+
(regexp
|
36
|
+
(str $_)
|
37
|
+
(regopt)))
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
def on_send(node)
|
41
|
+
return unless (regexp = exact_regexp_match(node))
|
42
|
+
|
43
|
+
parsed_regexp = Regexp::Parser.parse(regexp)
|
44
|
+
return unless exact_match_pattern?(parsed_regexp)
|
45
|
+
|
46
|
+
prefer = "#{node.receiver.source} #{new_method(node)} '#{parsed_regexp[1].text}'"
|
47
|
+
|
48
|
+
add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
|
49
|
+
corrector.replace(node, prefer)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
alias on_csend on_send
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def exact_match_pattern?(parsed_regexp)
|
57
|
+
tokens = parsed_regexp.map(&:token)
|
58
|
+
return false unless tokens[0] == :bos && tokens[1] == :literal && tokens[2] == :eos
|
59
|
+
|
60
|
+
!parsed_regexp[1].quantifier
|
61
|
+
end
|
62
|
+
|
63
|
+
def new_method(node)
|
64
|
+
node.method?(:!~) ? '!=' : '=='
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -86,7 +86,7 @@ module RuboCop
|
|
86
86
|
|
87
87
|
def extract_block_name(def_node)
|
88
88
|
if def_node.block_argument?
|
89
|
-
def_node.
|
89
|
+
def_node.last_argument.name
|
90
90
|
else
|
91
91
|
'block'
|
92
92
|
end
|
@@ -127,7 +127,7 @@ module RuboCop
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def insert_argument(node, corrector, block_name)
|
130
|
-
last_arg = node.
|
130
|
+
last_arg = node.last_argument
|
131
131
|
arg_range = range_with_surrounding_comma(last_arg.source_range, :right)
|
132
132
|
replacement = " &#{block_name}"
|
133
133
|
replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
|
64
64
|
# @!method block_read?(node)
|
65
65
|
def_node_matcher :block_read?, <<~PATTERN
|
66
|
-
(block _ (args (arg
|
66
|
+
(block _ (args (arg _name)) (send (lvar _name) :read))
|
67
67
|
PATTERN
|
68
68
|
|
69
69
|
def on_send(node)
|
@@ -100,7 +100,7 @@ module RuboCop
|
|
100
100
|
def file_open_read?(node)
|
101
101
|
return true if send_read?(node)
|
102
102
|
|
103
|
-
block_read?(node)
|
103
|
+
block_read?(node)
|
104
104
|
end
|
105
105
|
|
106
106
|
def read_method(mode)
|
@@ -4,13 +4,25 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# Enforces the use of a single string formatting utility.
|
7
|
-
# Valid options include Kernel#format
|
7
|
+
# Valid options include `Kernel#format`, `Kernel#sprintf`, and `String#%`.
|
8
8
|
#
|
9
|
-
# The detection of String
|
9
|
+
# The detection of `String#%` cannot be implemented in a reliable
|
10
10
|
# manner for all cases, so only two scenarios are considered -
|
11
11
|
# if the first argument is a string literal and if the second
|
12
12
|
# argument is an array literal.
|
13
13
|
#
|
14
|
+
# Autocorrection will be applied when using argument is a literal or known built-in conversion
|
15
|
+
# methods such as `to_d`, `to_f`, `to_h`, `to_i`, `to_r`, `to_s`, and `to_sym` on variables,
|
16
|
+
# provided that their return value is not an array. For example, when using `to_s`,
|
17
|
+
# `'%s' % [1, 2, 3].to_s` can be autocorrected without any incompatibility:
|
18
|
+
#
|
19
|
+
# [source,ruby]
|
20
|
+
# ----
|
21
|
+
# '%s' % [1, 2, 3] #=> '1'
|
22
|
+
# format('%s', [1, 2, 3]) #=> '[1, 2, 3]'
|
23
|
+
# '%s' % [1, 2, 3].to_s #=> '[1, 2, 3]'
|
24
|
+
# ----
|
25
|
+
#
|
14
26
|
# @example EnforcedStyle: format (default)
|
15
27
|
# # bad
|
16
28
|
# puts sprintf('%10s', 'hoge')
|
@@ -42,6 +54,9 @@ module RuboCop
|
|
42
54
|
MSG = 'Favor `%<prefer>s` over `%<current>s`.'
|
43
55
|
RESTRICT_ON_SEND = %i[format sprintf %].freeze
|
44
56
|
|
57
|
+
# Known conversion methods whose return value is not an array.
|
58
|
+
AUTOCORRECTABLE_METHODS = %i[to_d to_f to_h to_i to_r to_s to_sym].freeze
|
59
|
+
|
45
60
|
# @!method formatter(node)
|
46
61
|
def_node_matcher :formatter, <<~PATTERN
|
47
62
|
{
|
@@ -53,7 +68,7 @@ module RuboCop
|
|
53
68
|
|
54
69
|
# @!method variable_argument?(node)
|
55
70
|
def_node_matcher :variable_argument?, <<~PATTERN
|
56
|
-
(send {str dstr} :%
|
71
|
+
(send {str dstr} :% #autocorrectable?)
|
57
72
|
PATTERN
|
58
73
|
|
59
74
|
def on_send(node)
|
@@ -70,6 +85,12 @@ module RuboCop
|
|
70
85
|
|
71
86
|
private
|
72
87
|
|
88
|
+
def autocorrectable?(node)
|
89
|
+
return true if node.lvar_type?
|
90
|
+
|
91
|
+
node.send_type? && !AUTOCORRECTABLE_METHODS.include?(node.method_name)
|
92
|
+
end
|
93
|
+
|
73
94
|
def message(detected_style)
|
74
95
|
format(MSG, prefer: method_name(style), current: method_name(detected_style))
|
75
96
|
end
|
@@ -142,7 +142,9 @@ module RuboCop
|
|
142
142
|
end
|
143
143
|
|
144
144
|
next_token = processed_source.tokens[token_number]
|
145
|
-
|
145
|
+
if next_token&.text&.valid_encoding? && Encoding::ENCODING_PATTERN.match?(next_token.text)
|
146
|
+
token = next_token
|
147
|
+
end
|
146
148
|
|
147
149
|
token
|
148
150
|
end
|
@@ -55,6 +55,25 @@ module RuboCop
|
|
55
55
|
# foo || raise('exception') if something
|
56
56
|
# ok
|
57
57
|
#
|
58
|
+
# # bad
|
59
|
+
# define_method(:test) do
|
60
|
+
# if something
|
61
|
+
# work
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# # good
|
66
|
+
# define_method(:test) do
|
67
|
+
# return unless something
|
68
|
+
#
|
69
|
+
# work
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# # also good
|
73
|
+
# define_method(:test) do
|
74
|
+
# work if something
|
75
|
+
# end
|
76
|
+
#
|
58
77
|
# @example AllowConsecutiveConditionals: false (default)
|
59
78
|
# # bad
|
60
79
|
# def test
|
@@ -110,6 +129,13 @@ module RuboCop
|
|
110
129
|
end
|
111
130
|
alias on_defs on_def
|
112
131
|
|
132
|
+
def on_block(node)
|
133
|
+
return unless node.method?(:define_method) || node.method?(:define_singleton_method)
|
134
|
+
|
135
|
+
on_def(node)
|
136
|
+
end
|
137
|
+
alias on_numblock on_block
|
138
|
+
|
113
139
|
def on_if(node)
|
114
140
|
return if accepted_form?(node)
|
115
141
|
|
@@ -187,6 +213,8 @@ module RuboCop
|
|
187
213
|
if_branch = node.if_branch
|
188
214
|
else_branch = node.else_branch
|
189
215
|
|
216
|
+
corrector.replace(node.loc.begin, "\n") if node.loc.begin&.is?('then')
|
217
|
+
|
190
218
|
if if_branch&.send_type? && heredoc?(if_branch.last_argument)
|
191
219
|
autocorrect_heredoc_argument(corrector, node, if_branch, else_branch, guard)
|
192
220
|
elsif else_branch&.send_type? && heredoc?(else_branch.last_argument)
|
@@ -10,6 +10,16 @@ module RuboCop
|
|
10
10
|
# `Hash[*ary]` can be replaced with `ary.each_slice(2).to_h` but it will be complicated.
|
11
11
|
# So, `AllowSplatArgument` option is true by default to allow splat argument for simple code.
|
12
12
|
#
|
13
|
+
# @safety
|
14
|
+
# This cop's autocorrection is unsafe because `ArgumentError` occurs
|
15
|
+
# if the number of elements is odd:
|
16
|
+
#
|
17
|
+
# [source,ruby]
|
18
|
+
# ----
|
19
|
+
# Hash[[[1, 2], [3]]] #=> {1=>2, 3=>nil}
|
20
|
+
# [[1, 2], [5]].to_h #=> wrong array length at 1 (expected 2, was 1) (ArgumentError)
|
21
|
+
# ----
|
22
|
+
#
|
13
23
|
# @example
|
14
24
|
# # bad
|
15
25
|
# Hash[ary]
|
@@ -17,10 +17,16 @@ module RuboCop
|
|
17
17
|
# @example
|
18
18
|
# # bad
|
19
19
|
# hash.keys.each { |k| p k }
|
20
|
-
# hash.
|
20
|
+
# hash.each { |k, unused_value| p k }
|
21
21
|
#
|
22
22
|
# # good
|
23
23
|
# hash.each_key { |k| p k }
|
24
|
+
#
|
25
|
+
# # bad
|
26
|
+
# hash.values.each { |v| p v }
|
27
|
+
# hash.each { |unused_key, v| p v }
|
28
|
+
#
|
29
|
+
# # good
|
24
30
|
# hash.each_value { |v| p v }
|
25
31
|
#
|
26
32
|
# @example AllowedReceivers: ['execute']
|
@@ -28,26 +34,51 @@ module RuboCop
|
|
28
34
|
# execute(sql).keys.each { |v| p v }
|
29
35
|
# execute(sql).values.each { |v| p v }
|
30
36
|
class HashEachMethods < Base
|
37
|
+
include AllowedReceivers
|
31
38
|
include Lint::UnusedArgument
|
32
39
|
extend AutoCorrector
|
33
40
|
|
34
41
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
42
|
+
UNUSED_BLOCK_ARG_MSG = "#{MSG.chop} and remove the unused `%<unused_code>s` block argument."
|
35
43
|
|
36
44
|
# @!method kv_each(node)
|
37
45
|
def_node_matcher :kv_each, <<~PATTERN
|
38
|
-
({block numblock} $(
|
46
|
+
({block numblock} $(call (call _ ${:keys :values}) :each) ...)
|
47
|
+
PATTERN
|
48
|
+
|
49
|
+
# @!method each_arguments(node)
|
50
|
+
def_node_matcher :each_arguments, <<~PATTERN
|
51
|
+
(block (call _ :each)(args $_key $_value) ...)
|
39
52
|
PATTERN
|
40
53
|
|
41
54
|
# @!method kv_each_with_block_pass(node)
|
42
55
|
def_node_matcher :kv_each_with_block_pass, <<~PATTERN
|
43
|
-
(
|
56
|
+
(call $(call _ ${:keys :values}) :each (block_pass (sym _)))
|
44
57
|
PATTERN
|
45
58
|
|
59
|
+
# rubocop:disable Metrics/AbcSize
|
46
60
|
def on_block(node)
|
61
|
+
return unless handleable?(node)
|
62
|
+
|
47
63
|
kv_each(node) do |target, method|
|
48
|
-
register_kv_offense(target, method)
|
64
|
+
register_kv_offense(target, method) and return
|
65
|
+
end
|
66
|
+
|
67
|
+
return unless (key, value = each_arguments(node))
|
68
|
+
|
69
|
+
if unused_block_arg_exist?(node, value)
|
70
|
+
message = message('each_key', node.method_name, value.source)
|
71
|
+
unused_range = key.source_range.end.join(value.source_range.end)
|
72
|
+
|
73
|
+
register_each_args_offense(node, message, 'each_key', unused_range)
|
74
|
+
elsif unused_block_arg_exist?(node, key)
|
75
|
+
message = message('each_value', node.method_name, key.source)
|
76
|
+
unused_range = key.source_range.begin.join(value.source_range.begin)
|
77
|
+
|
78
|
+
register_each_args_offense(node, message, 'each_value', unused_range)
|
49
79
|
end
|
50
80
|
end
|
81
|
+
# rubocop:enable Metrics/AbcSize
|
51
82
|
|
52
83
|
alias on_numblock on_block
|
53
84
|
|
@@ -59,27 +90,70 @@ module RuboCop
|
|
59
90
|
|
60
91
|
private
|
61
92
|
|
93
|
+
def handleable?(node)
|
94
|
+
return false unless (root_receiver = root_receiver(node))
|
95
|
+
|
96
|
+
!root_receiver.literal? || root_receiver.hash_type?
|
97
|
+
end
|
98
|
+
|
62
99
|
def register_kv_offense(target, method)
|
63
100
|
return unless (parent_receiver = target.receiver.receiver)
|
64
101
|
return if allowed_receiver?(parent_receiver)
|
65
102
|
|
66
|
-
|
103
|
+
current = target.receiver.loc.selector.join(target.source_range.end).source
|
104
|
+
|
105
|
+
add_offense(kv_range(target), message: format_message(method, current)) do |corrector|
|
67
106
|
correct_key_value_each(target, corrector)
|
68
107
|
end
|
69
108
|
end
|
70
109
|
|
110
|
+
def unused_block_arg_exist?(node, block_arg)
|
111
|
+
lvar_sources = node.body.each_descendant(:lvar).map(&:source)
|
112
|
+
|
113
|
+
if block_arg.mlhs_type?
|
114
|
+
block_arg.each_descendant(:arg).all? do |block_arg|
|
115
|
+
lvar_sources.none?(block_arg.source)
|
116
|
+
end
|
117
|
+
else
|
118
|
+
lvar_sources.none?(block_arg.source)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def message(prefer, method_name, unused_code)
|
123
|
+
format(
|
124
|
+
UNUSED_BLOCK_ARG_MSG, prefer: prefer, current: method_name, unused_code: unused_code
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
def register_each_args_offense(node, message, prefer, unused_range)
|
129
|
+
add_offense(node, message: message) do |corrector|
|
130
|
+
corrector.replace(node.send_node.loc.selector, prefer)
|
131
|
+
corrector.remove(unused_range)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
71
135
|
def register_kv_with_block_pass_offense(node, target, method)
|
72
136
|
return unless (parent_receiver = node.parent.receiver.receiver)
|
73
137
|
return if allowed_receiver?(parent_receiver)
|
74
138
|
|
75
|
-
range = target.loc.selector.
|
76
|
-
|
139
|
+
range = target.loc.selector.join(node.parent.loc.selector.end)
|
140
|
+
|
141
|
+
add_offense(range, message: format_message(method, range.source)) do |corrector|
|
77
142
|
corrector.replace(range, "each_#{method[0..-2]}")
|
78
143
|
end
|
79
144
|
end
|
80
145
|
|
81
|
-
def
|
82
|
-
|
146
|
+
def root_receiver(node)
|
147
|
+
receiver = node.receiver
|
148
|
+
if receiver&.receiver
|
149
|
+
root_receiver(receiver)
|
150
|
+
else
|
151
|
+
receiver
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def format_message(method_name, current)
|
156
|
+
format(MSG, prefer: "each_#{method_name[0..-2]}", current: current)
|
83
157
|
end
|
84
158
|
|
85
159
|
def check_argument(variable)
|
@@ -102,7 +176,7 @@ module RuboCop
|
|
102
176
|
name = "each_#{node.receiver.method_name.to_s.chop}"
|
103
177
|
return correct_implicit(node, corrector, name) unless receiver
|
104
178
|
|
105
|
-
new_source = receiver.source + "
|
179
|
+
new_source = receiver.source + "#{node.loc.dot.source}#{name}"
|
106
180
|
corrector.replace(node, new_source)
|
107
181
|
end
|
108
182
|
|
@@ -116,28 +190,6 @@ module RuboCop
|
|
116
190
|
def kv_range(outer_node)
|
117
191
|
outer_node.receiver.loc.selector.join(outer_node.loc.selector)
|
118
192
|
end
|
119
|
-
|
120
|
-
def allowed_receiver?(receiver)
|
121
|
-
receiver_name = receiver_name(receiver)
|
122
|
-
|
123
|
-
allowed_receivers.include?(receiver_name)
|
124
|
-
end
|
125
|
-
|
126
|
-
def receiver_name(receiver)
|
127
|
-
if receiver.send_type?
|
128
|
-
if receiver.receiver
|
129
|
-
"#{receiver_name(receiver.receiver)}.#{receiver.method_name}"
|
130
|
-
else
|
131
|
-
receiver.method_name.to_s
|
132
|
-
end
|
133
|
-
else
|
134
|
-
receiver.source
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def allowed_receivers
|
139
|
-
cop_config.fetch('AllowedReceivers', [])
|
140
|
-
end
|
141
193
|
end
|
142
194
|
end
|
143
195
|
end
|
@@ -43,15 +43,15 @@ module RuboCop
|
|
43
43
|
# @!method bad_method_with_poro?(node)
|
44
44
|
def_node_matcher :bad_method_with_poro?, <<~PATTERN
|
45
45
|
(block
|
46
|
-
(
|
46
|
+
(call _ _)
|
47
47
|
(args
|
48
|
-
(arg _)
|
48
|
+
$(arg _)
|
49
49
|
(arg _))
|
50
50
|
{
|
51
|
-
(send
|
51
|
+
$(send
|
52
52
|
_ {:== :!= :eql? :include?} _)
|
53
53
|
(send
|
54
|
-
(send
|
54
|
+
$(send
|
55
55
|
_ {:== :!= :eql? :include?} _) :!)
|
56
56
|
})
|
57
57
|
PATTERN
|
@@ -61,13 +61,13 @@ module RuboCop
|
|
61
61
|
(block
|
62
62
|
(send _ _)
|
63
63
|
(args
|
64
|
-
(arg _)
|
64
|
+
$(arg _)
|
65
65
|
(arg _))
|
66
66
|
{
|
67
|
-
(send
|
67
|
+
$(send
|
68
68
|
_ {:== :!= :eql? :in? :include? :exclude?} _)
|
69
69
|
(send
|
70
|
-
(send
|
70
|
+
$(send
|
71
71
|
_ {:== :!= :eql? :in? :include? :exclude?} _) :!)
|
72
72
|
})
|
73
73
|
PATTERN
|
@@ -86,16 +86,28 @@ module RuboCop
|
|
86
86
|
corrector.replace(range, preferred_method)
|
87
87
|
end
|
88
88
|
end
|
89
|
+
alias on_csend on_send
|
89
90
|
|
90
91
|
private
|
91
92
|
|
93
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
92
94
|
def bad_method?(block)
|
93
95
|
if active_support_extensions_enabled?
|
94
|
-
bad_method_with_active_support?(block)
|
96
|
+
bad_method_with_active_support?(block) do |key_arg, send_node|
|
97
|
+
if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
|
101
|
+
|
102
|
+
send_node.first_argument&.source == key_arg.source
|
103
|
+
end
|
95
104
|
else
|
96
|
-
bad_method_with_poro?(block)
|
105
|
+
bad_method_with_poro?(block) do |key_arg, send_node|
|
106
|
+
!send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
|
107
|
+
end
|
97
108
|
end
|
98
109
|
end
|
110
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
99
111
|
|
100
112
|
def semantically_except_method?(send, block)
|
101
113
|
body = block.body
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Looks for uses of
|
7
|
-
#
|
6
|
+
# Looks for uses of `\_.each_with_object({}) {...}`,
|
7
|
+
# `\_.map {...}.to_h`, and `Hash[\_.map {...}]` that are actually just
|
8
8
|
# transforming the keys of a hash, and tries to use a simpler & faster
|
9
9
|
# call to `transform_keys` instead.
|
10
10
|
# It should only be enabled on Ruby version 2.5 or newer.
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Looks for uses of
|
7
|
-
#
|
6
|
+
# Looks for uses of `\_.each_with_object({}) {...}`,
|
7
|
+
# `\_.map {...}.to_h`, and `Hash[\_.map {...}]` that are actually just
|
8
8
|
# transforming the values of a hash, and tries to use a simpler & faster
|
9
9
|
# call to `transform_values` instead.
|
10
10
|
#
|
@@ -136,7 +136,7 @@ module RuboCop
|
|
136
136
|
|
137
137
|
private
|
138
138
|
|
139
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
139
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
140
140
|
def check_branches(node, branches)
|
141
141
|
# return if any branch is empty. An empty branch can be an `if`
|
142
142
|
# without an `else` or a branch that contains only comments.
|
@@ -149,22 +149,47 @@ module RuboCop
|
|
149
149
|
branches.any? { |branch| single_child_branch?(branch) }
|
150
150
|
|
151
151
|
heads = branches.map { |branch| head(branch) }
|
152
|
-
|
152
|
+
|
153
|
+
return unless duplicated_expressions?(node, heads)
|
154
|
+
|
155
|
+
condition_variable = assignable_condition_value(node)
|
156
|
+
|
157
|
+
head = heads.first
|
158
|
+
if head.assignment?
|
159
|
+
# The `send` node is used instead of the `indexasgn` node, so `name` cannot be used.
|
160
|
+
# https://github.com/rubocop/rubocop-ast/blob/v1.29.0/lib/rubocop/ast/node/indexasgn_node.rb
|
161
|
+
assigned_value = head.send_type? ? head.receiver.source : head.name.to_s
|
162
|
+
|
163
|
+
return if condition_variable == assigned_value
|
164
|
+
end
|
165
|
+
|
166
|
+
check_expressions(node, heads, :before_condition)
|
153
167
|
end
|
154
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
168
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
155
169
|
|
156
170
|
def duplicated_expressions?(node, expressions)
|
157
171
|
unique_expressions = expressions.uniq
|
158
172
|
return false unless expressions.size >= 1 && unique_expressions.one?
|
159
173
|
|
160
174
|
unique_expression = unique_expressions.first
|
161
|
-
return true unless unique_expression
|
175
|
+
return true unless unique_expression&.assignment?
|
162
176
|
|
163
177
|
lhs = unique_expression.child_nodes.first
|
164
178
|
node.condition.child_nodes.none? { |n| n.source == lhs.source if n.variable? }
|
165
179
|
end
|
166
180
|
|
167
|
-
def
|
181
|
+
def assignable_condition_value(node)
|
182
|
+
if node.condition.call_type?
|
183
|
+
(receiver = node.condition.receiver) ? receiver.source : node.condition.source
|
184
|
+
elsif node.condition.variable?
|
185
|
+
node.condition.source
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
190
|
+
def check_expressions(node, expressions, insert_position)
|
191
|
+
return if expressions.any?(&:nil?)
|
192
|
+
|
168
193
|
inserted_expression = false
|
169
194
|
|
170
195
|
expressions.each do |expression|
|
@@ -184,6 +209,7 @@ module RuboCop
|
|
184
209
|
end
|
185
210
|
end
|
186
211
|
end
|
212
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
187
213
|
|
188
214
|
def last_child_of_parent?(node)
|
189
215
|
return true unless (parent = node.parent)
|