rubocop 1.53.0 → 1.60.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/LICENSE.txt +1 -1
- data/README.md +5 -3
- data/config/default.yml +80 -11
- data/config/obsoletion.yml +5 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config.rb +0 -2
- data/lib/rubocop/config_finder.rb +2 -2
- data/lib/rubocop/config_loader.rb +0 -1
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
- data/lib/rubocop/config_obsoletion.rb +11 -8
- data/lib/rubocop/config_validator.rb +0 -2
- data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
- data/lib/rubocop/cop/base.rb +7 -1
- 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 +2 -2
- data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
- data/lib/rubocop/cop/exclude_limit.rb +1 -1
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
- 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/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 +2 -2
- 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/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 +26 -3
- data/lib/rubocop/cop/layout/end_alignment.rb +12 -2
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +22 -7
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_width.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_method_call_indentation.rb +18 -3
- data/lib/rubocop/cop/layout/redundant_line_break.rb +15 -4
- 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_parens.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
- 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 +18 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -3
- 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/it_without_arguments_in_block.rb +56 -0
- 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/mixed_case_range.rb +3 -1
- 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 +9 -4
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +10 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +63 -4
- 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/shadowed_argument.rb +1 -0
- 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 +1 -1
- 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 +5 -3
- 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 +38 -12
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +46 -21
- 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/code_length_calculator.rb +32 -4
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +16 -12
- 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/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/preceding_following_alignment.rb +6 -8
- 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 +12 -4
- data/lib/rubocop/cop/naming/constant_name.rb +1 -2
- 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 +1 -1
- data/lib/rubocop/cop/registry.rb +4 -4
- 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 +1 -1
- data/lib/rubocop/cop/style/alias.rb +9 -8
- data/lib/rubocop/cop/style/arguments_forwarding.rb +355 -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/auto_resource_cleanup.rb +21 -14
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
- data/lib/rubocop/cop/style/case_like_if.rb +4 -4
- data/lib/rubocop/cop/style/class_check.rb +1 -0
- data/lib/rubocop/cop/style/class_equality_comparison.rb +7 -0
- data/lib/rubocop/cop/style/collection_compact.rb +7 -6
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +17 -9
- data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
- data/lib/rubocop/cop/style/date_time.rb +5 -4
- 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 +3 -14
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
- data/lib/rubocop/cop/style/explicit_block_argument.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 +26 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +83 -10
- data/lib/rubocop/cop/style/hash_except.rb +2 -1
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +28 -3
- 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 +39 -2
- 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 +17 -7
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +22 -6
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -4
- 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 +2 -4
- 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_literal_prefix.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/parallel_assignment.rb +2 -2
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +9 -3
- data/lib/rubocop/cop/style/redundant_begin.rb +9 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -9
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
- 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 +3 -3
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +22 -5
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +63 -21
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +18 -4
- 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 +5 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +9 -8
- data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
- data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -1
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +23 -9
- data/lib/rubocop/cop/style/sample.rb +2 -1
- data/lib/rubocop/cop/style/select_by_regexp.rb +7 -6
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +8 -3
- 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/slicing_with_range.rb +76 -10
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- 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/symbol_proc.rb +36 -0
- data/lib/rubocop/cop/style/unpack_first.rb +11 -14
- data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
- data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
- data/lib/rubocop/cop/utils/regexp_ranges.rb +26 -13
- data/lib/rubocop/cop/variable_force/assignment.rb +14 -5
- data/lib/rubocop/cops_documentation_generator.rb +11 -1
- data/lib/rubocop/ext/regexp_node.rb +9 -4
- 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 +5 -4
- data/lib/rubocop/formatter/json_formatter.rb +0 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +42 -19
- data/lib/rubocop/lsp/runtime.rb +22 -2
- data/lib/rubocop/lsp/server.rb +10 -4
- data/lib/rubocop/magic_comment.rb +12 -10
- data/lib/rubocop/options.rb +0 -8
- data/lib/rubocop/result_cache.rb +4 -1
- data/lib/rubocop/rspec/shared_contexts.rb +8 -3
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/runner.rb +6 -4
- data/lib/rubocop/server/client_command/exec.rb +1 -1
- data/lib/rubocop/string_interpreter.rb +3 -3
- data/lib/rubocop/target_finder.rb +7 -3
- data/lib/rubocop/target_ruby.rb +9 -5
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +6 -0
- metadata +20 -13
- /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
|
@@ -27,24 +27,16 @@ module RuboCop
|
|
|
27
27
|
|
|
28
28
|
node.each_descendant(:if).select(&:ternary?).each do |nested_ternary|
|
|
29
29
|
add_offense(nested_ternary) do |corrector|
|
|
30
|
-
|
|
31
|
-
next if part_of_ignored_node?(if_node)
|
|
30
|
+
next if part_of_ignored_node?(node)
|
|
32
31
|
|
|
33
|
-
autocorrect(corrector,
|
|
34
|
-
ignore_node(
|
|
32
|
+
autocorrect(corrector, node)
|
|
33
|
+
ignore_node(node)
|
|
35
34
|
end
|
|
36
35
|
end
|
|
37
36
|
end
|
|
38
37
|
|
|
39
38
|
private
|
|
40
39
|
|
|
41
|
-
def if_node(node)
|
|
42
|
-
node = node.parent
|
|
43
|
-
return node if node.if_type?
|
|
44
|
-
|
|
45
|
-
if_node(node)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
40
|
def autocorrect(corrector, if_node)
|
|
49
41
|
replace_loc_and_whitespace(corrector, if_node.loc.question, "\n")
|
|
50
42
|
replace_loc_and_whitespace(corrector, if_node.loc.colon, "\nelse\n")
|
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
|
45
45
|
MSG = 'Avoid using `OpenStruct`; use `Struct`, `Hash`, a class or test doubles instead.'
|
|
46
46
|
|
|
47
47
|
# @!method uses_open_struct?(node)
|
|
48
|
-
def_node_matcher :uses_open_struct?,
|
|
48
|
+
def_node_matcher :uses_open_struct?, <<~PATTERN
|
|
49
49
|
(const {nil? (cbase)} :OpenStruct)
|
|
50
50
|
PATTERN
|
|
51
51
|
|
|
@@ -4,8 +4,8 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
6
|
# Checks for redundant dot before operator method call.
|
|
7
|
-
# The target operator methods are `|`, `^`, `&`,
|
|
8
|
-
#
|
|
7
|
+
# The target operator methods are `|`, `^`, `&`, ``<=>``, `==`, `===`, `=~`, `>`, `>=`, `<`,
|
|
8
|
+
# ``<=``, `<<`, `>>`, `+`, `-`, `*`, `/`, `%`, `**`, `~`, `!`, `!=`, and `!~`.
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
11
|
#
|
|
@@ -23,6 +23,7 @@ module RuboCop
|
|
|
23
23
|
MSG = 'Redundant dot detected.'
|
|
24
24
|
RESTRICT_ON_SEND = %i[| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ ! != !~].freeze
|
|
25
25
|
|
|
26
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
26
27
|
def on_send(node)
|
|
27
28
|
return unless (dot = node.loc.dot)
|
|
28
29
|
return if node.receiver.const_type? || !node.arguments.one?
|
|
@@ -33,8 +34,12 @@ module RuboCop
|
|
|
33
34
|
add_offense(dot) do |corrector|
|
|
34
35
|
wrap_in_parentheses_if_chained(corrector, node)
|
|
35
36
|
corrector.replace(dot, ' ')
|
|
37
|
+
|
|
38
|
+
selector = node.loc.selector
|
|
39
|
+
corrector.insert_after(selector, ' ') if selector.end_pos == rhs.source_range.begin_pos
|
|
36
40
|
end
|
|
37
41
|
end
|
|
42
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
38
43
|
|
|
39
44
|
private
|
|
40
45
|
|
|
@@ -54,6 +59,7 @@ module RuboCop
|
|
|
54
59
|
|
|
55
60
|
def wrap_in_parentheses_if_chained(corrector, node)
|
|
56
61
|
return unless node.parent&.call_type?
|
|
62
|
+
return if node.parent.first_argument == node
|
|
57
63
|
|
|
58
64
|
operator = node.loc.selector
|
|
59
65
|
|
|
@@ -81,6 +81,7 @@ module RuboCop
|
|
|
81
81
|
cond = node.condition
|
|
82
82
|
|
|
83
83
|
control_op_condition(cond) do |first_child, rest_children|
|
|
84
|
+
return if require_parentheses?(node, first_child)
|
|
84
85
|
return if semicolon_separated_expressions?(first_child, rest_children)
|
|
85
86
|
return if modifier_op?(first_child)
|
|
86
87
|
return if parens_allowed?(cond)
|
|
@@ -92,6 +93,13 @@ module RuboCop
|
|
|
92
93
|
end
|
|
93
94
|
end
|
|
94
95
|
|
|
96
|
+
def require_parentheses?(node, condition_body)
|
|
97
|
+
return false if !node.while_type? && !node.until_type?
|
|
98
|
+
return false if !condition_body.block_type? && !condition_body.numblock_type?
|
|
99
|
+
|
|
100
|
+
condition_body.send_node.block_literal? && condition_body.keywords?
|
|
101
|
+
end
|
|
102
|
+
|
|
95
103
|
def semicolon_separated_expressions?(first_exp, rest_exps)
|
|
96
104
|
return false unless (second_exp = rest_exps.first)
|
|
97
105
|
|
|
@@ -35,6 +35,8 @@ module RuboCop
|
|
|
35
35
|
# array.join('')
|
|
36
36
|
# [1, 2, 3].join("")
|
|
37
37
|
# array.sum(0)
|
|
38
|
+
# exit(true)
|
|
39
|
+
# exit!(false)
|
|
38
40
|
# string.split(" ")
|
|
39
41
|
# "first\nsecond".split(" ")
|
|
40
42
|
# string.chomp("\n")
|
|
@@ -45,6 +47,8 @@ module RuboCop
|
|
|
45
47
|
# array.join
|
|
46
48
|
# [1, 2, 3].join
|
|
47
49
|
# array.sum
|
|
50
|
+
# exit
|
|
51
|
+
# exit!
|
|
48
52
|
# string.split
|
|
49
53
|
# "first second".split
|
|
50
54
|
# string.chomp
|
|
@@ -55,19 +59,21 @@ module RuboCop
|
|
|
55
59
|
extend AutoCorrector
|
|
56
60
|
|
|
57
61
|
MSG = 'Argument %<arg>s is redundant because it is implied by default.'
|
|
62
|
+
NO_RECEIVER_METHODS = %i[exit exit!].freeze
|
|
58
63
|
|
|
59
64
|
def on_send(node)
|
|
60
|
-
return if node.receiver.nil?
|
|
65
|
+
return if !NO_RECEIVER_METHODS.include?(node.method_name) && node.receiver.nil?
|
|
61
66
|
return if node.arguments.count != 1
|
|
62
67
|
return unless redundant_argument?(node)
|
|
63
68
|
|
|
64
69
|
offense_range = argument_range(node)
|
|
65
|
-
message = format(MSG, arg: node.
|
|
70
|
+
message = format(MSG, arg: node.first_argument.source)
|
|
66
71
|
|
|
67
72
|
add_offense(offense_range, message: message) do |corrector|
|
|
68
73
|
corrector.remove(offense_range)
|
|
69
74
|
end
|
|
70
75
|
end
|
|
76
|
+
alias on_csend on_send
|
|
71
77
|
|
|
72
78
|
private
|
|
73
79
|
|
|
@@ -75,7 +81,7 @@ module RuboCop
|
|
|
75
81
|
redundant_argument = redundant_arg_for_method(node.method_name.to_s)
|
|
76
82
|
return false if redundant_argument.nil?
|
|
77
83
|
|
|
78
|
-
node.
|
|
84
|
+
node.first_argument == redundant_argument
|
|
79
85
|
end
|
|
80
86
|
|
|
81
87
|
def redundant_arg_for_method(method_name)
|
|
@@ -114,7 +114,7 @@ module RuboCop
|
|
|
114
114
|
if node.parent&.assignment?
|
|
115
115
|
replace_begin_with_statement(corrector, offense_range, node)
|
|
116
116
|
else
|
|
117
|
-
corrector
|
|
117
|
+
remove_begin(corrector, offense_range, node)
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
if use_modifier_form_after_multiline_begin_block?(node)
|
|
@@ -136,6 +136,14 @@ module RuboCop
|
|
|
136
136
|
restore_removed_comments(corrector, offense_range, node, first_child)
|
|
137
137
|
end
|
|
138
138
|
|
|
139
|
+
def remove_begin(corrector, offense_range, node)
|
|
140
|
+
if node.parent.respond_to?(:endless?) && node.parent.endless?
|
|
141
|
+
offense_range = range_with_surrounding_space(offense_range, newlines: true)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
corrector.remove(offense_range)
|
|
145
|
+
end
|
|
146
|
+
|
|
139
147
|
# Restore comments that occur between "begin" and "first_child".
|
|
140
148
|
# These comments will be moved to above the assignment line.
|
|
141
149
|
def restore_removed_comments(corrector, offense_range, node, first_child)
|
|
@@ -70,19 +70,11 @@ module RuboCop
|
|
|
70
70
|
|
|
71
71
|
def replacement_condition(node)
|
|
72
72
|
condition = node.condition.source
|
|
73
|
-
expression =
|
|
73
|
+
expression = redundant_condition_inverted?(node) ? "!(#{condition})" : condition
|
|
74
74
|
|
|
75
75
|
node.elsif? ? indented_else_node(expression, node) : expression
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
def invert_expression?(node)
|
|
79
|
-
(
|
|
80
|
-
(node.if? || node.elsif? || node.ternary?) && redundant_condition_inverted?(node)
|
|
81
|
-
) || (
|
|
82
|
-
node.unless? && redundant_condition?(node)
|
|
83
|
-
)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
78
|
def indented_else_node(expression, node)
|
|
87
79
|
"else\n#{indentation(node)}#{expression}"
|
|
88
80
|
end
|
|
@@ -22,7 +22,7 @@ module RuboCop
|
|
|
22
22
|
|
|
23
23
|
def on_send(node)
|
|
24
24
|
return unless node.method?(:require_relative)
|
|
25
|
-
return unless node.first_argument.str_content
|
|
25
|
+
return unless node.first_argument.str_content&.start_with?(CURRENT_DIRECTORY_PATH)
|
|
26
26
|
return unless (index = node.first_argument.source.index(CURRENT_DIRECTORY_PATH))
|
|
27
27
|
|
|
28
28
|
begin_pos = node.first_argument.source_range.begin.begin_pos + index
|
|
@@ -13,25 +13,71 @@ module RuboCop
|
|
|
13
13
|
# # good
|
|
14
14
|
# do_something(foo: bar, baz: qux)
|
|
15
15
|
#
|
|
16
|
+
# # bad
|
|
17
|
+
# do_something(**{foo: bar, baz: qux}.merge(options))
|
|
18
|
+
#
|
|
19
|
+
# # good
|
|
20
|
+
# do_something(foo: bar, baz: qux, **options)
|
|
21
|
+
#
|
|
16
22
|
class RedundantDoubleSplatHashBraces < Base
|
|
17
23
|
extend AutoCorrector
|
|
18
24
|
|
|
19
25
|
MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
|
|
26
|
+
MERGE_METHODS = %i[merge merge!].freeze
|
|
20
27
|
|
|
28
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
21
29
|
def on_hash(node)
|
|
22
30
|
return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
|
|
23
31
|
return unless (parent = node.parent)
|
|
24
|
-
return unless parent.kwsplat_type?
|
|
32
|
+
return unless parent.call_type? || parent.kwsplat_type?
|
|
33
|
+
return unless mergeable?(parent)
|
|
34
|
+
return unless (kwsplat = node.each_ancestor(:kwsplat).first)
|
|
35
|
+
return if !node.braces? || allowed_double_splat_receiver?(kwsplat)
|
|
25
36
|
|
|
26
|
-
add_offense(
|
|
27
|
-
corrector
|
|
28
|
-
corrector.remove(opening_brace(node))
|
|
29
|
-
corrector.remove(closing_brace(node))
|
|
37
|
+
add_offense(kwsplat) do |corrector|
|
|
38
|
+
autocorrect(corrector, node, kwsplat)
|
|
30
39
|
end
|
|
31
40
|
end
|
|
41
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
32
42
|
|
|
33
43
|
private
|
|
34
44
|
|
|
45
|
+
def allowed_double_splat_receiver?(kwsplat)
|
|
46
|
+
first_child = kwsplat.children.first
|
|
47
|
+
return true if first_child.block_type? || first_child.numblock_type?
|
|
48
|
+
return false unless first_child.call_type?
|
|
49
|
+
|
|
50
|
+
root_receiver = root_receiver(first_child)
|
|
51
|
+
|
|
52
|
+
!root_receiver&.hash_type?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def autocorrect(corrector, node, kwsplat)
|
|
56
|
+
corrector.remove(kwsplat.loc.operator)
|
|
57
|
+
corrector.remove(opening_brace(node))
|
|
58
|
+
corrector.remove(closing_brace(node))
|
|
59
|
+
|
|
60
|
+
merge_methods = select_merge_method_nodes(kwsplat)
|
|
61
|
+
return if merge_methods.empty?
|
|
62
|
+
|
|
63
|
+
autocorrect_merge_methods(corrector, merge_methods, kwsplat)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def root_receiver(node)
|
|
67
|
+
receiver = node.receiver
|
|
68
|
+
if receiver&.receiver
|
|
69
|
+
root_receiver(receiver)
|
|
70
|
+
else
|
|
71
|
+
receiver
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def select_merge_method_nodes(kwsplat)
|
|
76
|
+
extract_send_methods(kwsplat).select do |node|
|
|
77
|
+
mergeable?(node)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
35
81
|
def opening_brace(node)
|
|
36
82
|
node.loc.begin.join(node.children.first.source_range.begin)
|
|
37
83
|
end
|
|
@@ -39,6 +85,48 @@ module RuboCop
|
|
|
39
85
|
def closing_brace(node)
|
|
40
86
|
node.children.last.source_range.end.join(node.loc.end)
|
|
41
87
|
end
|
|
88
|
+
|
|
89
|
+
def autocorrect_merge_methods(corrector, merge_methods, kwsplat)
|
|
90
|
+
range = range_of_merge_methods(merge_methods)
|
|
91
|
+
|
|
92
|
+
new_kwsplat_arguments = extract_send_methods(kwsplat).map do |descendant|
|
|
93
|
+
convert_to_new_arguments(descendant)
|
|
94
|
+
end
|
|
95
|
+
new_source = new_kwsplat_arguments.compact.reverse.unshift('').join(', ')
|
|
96
|
+
|
|
97
|
+
corrector.replace(range, new_source)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def range_of_merge_methods(merge_methods)
|
|
101
|
+
begin_merge_method = merge_methods.last
|
|
102
|
+
end_merge_method = merge_methods.first
|
|
103
|
+
|
|
104
|
+
begin_merge_method.loc.dot.begin.join(end_merge_method.source_range.end)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def extract_send_methods(kwsplat)
|
|
108
|
+
kwsplat.each_descendant(:send, :csend)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def convert_to_new_arguments(node)
|
|
112
|
+
return unless mergeable?(node)
|
|
113
|
+
|
|
114
|
+
node.arguments.map do |arg|
|
|
115
|
+
if arg.hash_type?
|
|
116
|
+
arg.source
|
|
117
|
+
else
|
|
118
|
+
"**#{arg.source}"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def mergeable?(node)
|
|
124
|
+
return true unless node.call_type?
|
|
125
|
+
return false unless MERGE_METHODS.include?(node.method_name)
|
|
126
|
+
return true unless (parent = node.parent)
|
|
127
|
+
|
|
128
|
+
mergeable?(parent)
|
|
129
|
+
end
|
|
42
130
|
end
|
|
43
131
|
end
|
|
44
132
|
end
|
|
@@ -56,6 +56,7 @@ module RuboCop
|
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
|
+
alias on_csend on_send
|
|
59
60
|
|
|
60
61
|
private
|
|
61
62
|
|
|
@@ -64,7 +65,7 @@ module RuboCop
|
|
|
64
65
|
return if node.last_argument&.block_pass_type?
|
|
65
66
|
|
|
66
67
|
if node.method?(:each) && !node.parent&.block_type?
|
|
67
|
-
ancestor_node = node.each_ancestor(:send).detect do |ancestor|
|
|
68
|
+
ancestor_node = node.each_ancestor(:send, :csend).detect do |ancestor|
|
|
68
69
|
ancestor.receiver == node &&
|
|
69
70
|
(RESTRICT_ON_SEND.include?(ancestor.method_name) || ancestor.method?(:reverse_each))
|
|
70
71
|
end
|
|
@@ -83,10 +84,12 @@ module RuboCop
|
|
|
83
84
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
84
85
|
|
|
85
86
|
def range(node)
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
return node.selector unless node.method?(:each)
|
|
88
|
+
|
|
89
|
+
if node.parent.call_type?
|
|
90
|
+
node.selector.join(node.parent.loc.dot)
|
|
88
91
|
else
|
|
89
|
-
node.loc.selector
|
|
92
|
+
node.loc.dot.join(node.selector)
|
|
90
93
|
end
|
|
91
94
|
end
|
|
92
95
|
|
|
@@ -5,17 +5,21 @@ module RuboCop
|
|
|
5
5
|
module Style
|
|
6
6
|
# Checks for RuntimeError as the argument of raise/fail.
|
|
7
7
|
#
|
|
8
|
-
# It checks for code like this:
|
|
9
|
-
#
|
|
10
8
|
# @example
|
|
11
|
-
# #
|
|
9
|
+
# # bad
|
|
12
10
|
# raise RuntimeError, 'message'
|
|
13
|
-
#
|
|
14
|
-
# # Bad
|
|
15
11
|
# raise RuntimeError.new('message')
|
|
16
12
|
#
|
|
17
|
-
# #
|
|
13
|
+
# # good
|
|
18
14
|
# raise 'message'
|
|
15
|
+
#
|
|
16
|
+
# # bad - message is not a string
|
|
17
|
+
# raise RuntimeError, Object.new
|
|
18
|
+
# raise RuntimeError.new(Object.new)
|
|
19
|
+
#
|
|
20
|
+
# # good
|
|
21
|
+
# raise Object.new.to_s
|
|
22
|
+
#
|
|
19
23
|
class RedundantException < Base
|
|
20
24
|
extend AutoCorrector
|
|
21
25
|
|
|
@@ -30,26 +34,42 @@ module RuboCop
|
|
|
30
34
|
fix_exploded(node) || fix_compact(node)
|
|
31
35
|
end
|
|
32
36
|
|
|
37
|
+
private
|
|
38
|
+
|
|
33
39
|
def fix_exploded(node)
|
|
34
40
|
exploded?(node) do |command, message|
|
|
35
41
|
add_offense(node, message: MSG_1) do |corrector|
|
|
36
|
-
|
|
37
|
-
corrector.replace(node, "#{command}(#{message.source})")
|
|
38
|
-
else
|
|
39
|
-
corrector.replace(node, "#{command} #{message.source}")
|
|
40
|
-
end
|
|
42
|
+
corrector.replace(node, replaced_exploded(node, command, message))
|
|
41
43
|
end
|
|
42
44
|
end
|
|
43
45
|
end
|
|
44
46
|
|
|
47
|
+
def replaced_exploded(node, command, message)
|
|
48
|
+
arg = string_message?(message) ? message.source : "#{message.source}.to_s"
|
|
49
|
+
arg = node.parenthesized? ? "(#{arg})" : " #{arg}"
|
|
50
|
+
"#{command}#{arg}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def string_message?(message)
|
|
54
|
+
message.str_type? || message.dstr_type? || message.xstr_type?
|
|
55
|
+
end
|
|
56
|
+
|
|
45
57
|
def fix_compact(node)
|
|
46
58
|
compact?(node) do |new_call, message|
|
|
47
59
|
add_offense(node, message: MSG_2) do |corrector|
|
|
48
|
-
corrector.replace(new_call, message
|
|
60
|
+
corrector.replace(new_call, replaced_compact(message))
|
|
49
61
|
end
|
|
50
62
|
end
|
|
51
63
|
end
|
|
52
64
|
|
|
65
|
+
def replaced_compact(message)
|
|
66
|
+
if string_message?(message)
|
|
67
|
+
message.source
|
|
68
|
+
else
|
|
69
|
+
"#{message.source}.to_s"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
53
73
|
# @!method exploded?(node)
|
|
54
74
|
def_node_matcher :exploded?, <<~PATTERN
|
|
55
75
|
(send nil? ${:raise :fail} (const {nil? cbase} :RuntimeError) $_)
|
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
|
47
47
|
# @!method redundant_fetch_block_candidate?(node)
|
|
48
48
|
def_node_matcher :redundant_fetch_block_candidate?, <<~PATTERN
|
|
49
49
|
(block
|
|
50
|
-
$(
|
|
50
|
+
$(call _ :fetch _)
|
|
51
51
|
(args)
|
|
52
52
|
${nil? #basic_literal? #const_type?})
|
|
53
53
|
PATTERN
|
|
@@ -61,10 +61,10 @@ module RuboCop
|
|
|
61
61
|
bad = build_bad_method(send, body)
|
|
62
62
|
|
|
63
63
|
add_offense(range, message: format(MSG, good: good, bad: bad)) do |corrector|
|
|
64
|
-
|
|
64
|
+
_, _, key = send.children
|
|
65
65
|
default_value = body ? body.source : 'nil'
|
|
66
66
|
|
|
67
|
-
corrector.replace(
|
|
67
|
+
corrector.replace(range, "fetch(#{key.source}, #{default_value})")
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
end
|
|
@@ -6,6 +6,12 @@ module RuboCop
|
|
|
6
6
|
# Identifies usages of `any?`, `empty?` or `none?` predicate methods
|
|
7
7
|
# chained to `select`/`filter`/`find_all` and change them to use predicate method instead.
|
|
8
8
|
#
|
|
9
|
+
# @safety
|
|
10
|
+
# This cop's autocorrection is unsafe because `array.select.any?` evaluates all elements
|
|
11
|
+
# through the `select` method, while `array.any?` uses short-circuit evaluation.
|
|
12
|
+
# In other words, `array.select.any?` guarantees the evaluation of every element,
|
|
13
|
+
# but `array.any?` does not necessarily evaluate all of them.
|
|
14
|
+
#
|
|
9
15
|
# @example
|
|
10
16
|
# # bad
|
|
11
17
|
# arr.select { |x| x > 1 }.any?
|
|
@@ -28,6 +34,9 @@ module RuboCop
|
|
|
28
34
|
# # good
|
|
29
35
|
# arr.select { |x| x > 1 }.many?
|
|
30
36
|
#
|
|
37
|
+
# # good
|
|
38
|
+
# arr.select { |x| x > 1 }.present?
|
|
39
|
+
#
|
|
31
40
|
# @example AllCops:ActiveSupportExtensionsEnabled: true
|
|
32
41
|
# # bad
|
|
33
42
|
# arr.select { |x| x > 1 }.many?
|
|
@@ -35,20 +44,26 @@ module RuboCop
|
|
|
35
44
|
# # good
|
|
36
45
|
# arr.many? { |x| x > 1 }
|
|
37
46
|
#
|
|
47
|
+
# # bad
|
|
48
|
+
# arr.select { |x| x > 1 }.present?
|
|
49
|
+
#
|
|
50
|
+
# # good
|
|
51
|
+
# arr.any? { |x| x > 1 }
|
|
52
|
+
#
|
|
38
53
|
class RedundantFilterChain < Base
|
|
39
54
|
extend AutoCorrector
|
|
40
55
|
|
|
41
56
|
MSG = 'Use `%<prefer>s` instead of `%<first_method>s.%<second_method>s`.'
|
|
42
57
|
|
|
43
|
-
RAILS_METHODS = %i[many?].freeze
|
|
58
|
+
RAILS_METHODS = %i[many? present?].freeze
|
|
44
59
|
RESTRICT_ON_SEND = (%i[any? empty? none? one?] + RAILS_METHODS).freeze
|
|
45
60
|
|
|
46
61
|
# @!method select_predicate?(node)
|
|
47
62
|
def_node_matcher :select_predicate?, <<~PATTERN
|
|
48
|
-
(
|
|
63
|
+
(call
|
|
49
64
|
{
|
|
50
|
-
(block $(
|
|
51
|
-
$(
|
|
65
|
+
(block $(call _ {:select :filter :find_all}) ...)
|
|
66
|
+
$(call _ {:select :filter :find_all} block_pass_type?)
|
|
52
67
|
}
|
|
53
68
|
${:#{RESTRICT_ON_SEND.join(' :')}})
|
|
54
69
|
PATTERN
|
|
@@ -58,7 +73,8 @@ module RuboCop
|
|
|
58
73
|
empty?: :none?,
|
|
59
74
|
none?: :none?,
|
|
60
75
|
one?: :one?,
|
|
61
|
-
many?: :many
|
|
76
|
+
many?: :many?,
|
|
77
|
+
present?: :any?
|
|
62
78
|
}.freeze
|
|
63
79
|
private_constant :REPLACEMENT_METHODS
|
|
64
80
|
|
|
@@ -71,6 +87,7 @@ module RuboCop
|
|
|
71
87
|
register_offense(select_node, node)
|
|
72
88
|
end
|
|
73
89
|
end
|
|
90
|
+
alias on_csend on_send
|
|
74
91
|
|
|
75
92
|
private
|
|
76
93
|
|
|
@@ -94,7 +94,8 @@ module RuboCop
|
|
|
94
94
|
!ends_with_backslash_without_comment?(range.source_line) ||
|
|
95
95
|
string_concatenation?(range.source_line) ||
|
|
96
96
|
start_with_arithmetic_operator?(processed_source[range.line]) ||
|
|
97
|
-
inside_string_literal_or_method_with_argument?(range)
|
|
97
|
+
inside_string_literal_or_method_with_argument?(range) ||
|
|
98
|
+
leading_dot_method_chain_with_blank_line?(range)
|
|
98
99
|
end
|
|
99
100
|
|
|
100
101
|
def ends_with_backslash_without_comment?(source_line)
|
|
@@ -107,10 +108,18 @@ module RuboCop
|
|
|
107
108
|
|
|
108
109
|
def inside_string_literal_or_method_with_argument?(range)
|
|
109
110
|
processed_source.tokens.each_cons(2).any? do |token, next_token|
|
|
111
|
+
next if token.line == next_token.line
|
|
112
|
+
|
|
110
113
|
inside_string_literal?(range, token) || method_with_argument?(token, next_token)
|
|
111
114
|
end
|
|
112
115
|
end
|
|
113
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
|
+
|
|
114
123
|
def redundant_line_continuation?(range)
|
|
115
124
|
return true unless (node = find_node_for_line(range.line))
|
|
116
125
|
return false if argument_newline?(node)
|