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
|
@@ -45,10 +45,9 @@ module RuboCop
|
|
|
45
45
|
bad_method?(node) do |safe_nav, method|
|
|
46
46
|
return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
node.source_range.end_pos)
|
|
48
|
+
begin_range = node.loc.dot || safe_nav.source_range.end
|
|
49
|
+
location = begin_range.join(node.source_range.end)
|
|
50
|
+
|
|
52
51
|
add_offense(location) do |corrector|
|
|
53
52
|
autocorrect(corrector, offense_range: location, send_node: node)
|
|
54
53
|
end
|
|
@@ -82,16 +81,23 @@ module RuboCop
|
|
|
82
81
|
def autocorrect(corrector, offense_range:, send_node:)
|
|
83
82
|
corrector.replace(
|
|
84
83
|
offense_range,
|
|
85
|
-
add_safe_navigation_operator(
|
|
86
|
-
offense_range: offense_range,
|
|
87
|
-
send_node: send_node
|
|
88
|
-
)
|
|
84
|
+
add_safe_navigation_operator(offense_range: offense_range, send_node: send_node)
|
|
89
85
|
)
|
|
86
|
+
|
|
87
|
+
corrector.wrap(send_node, '(', ')') if require_parentheses?(send_node)
|
|
90
88
|
end
|
|
91
89
|
|
|
92
90
|
def brackets?(send_node)
|
|
93
91
|
send_node.method?(:[]) || send_node.method?(:[]=)
|
|
94
92
|
end
|
|
93
|
+
|
|
94
|
+
def require_parentheses?(send_node)
|
|
95
|
+
return false unless send_node.comparison_method?
|
|
96
|
+
return false unless (node = send_node.parent)
|
|
97
|
+
|
|
98
|
+
(node.respond_to?(:logical_operator?) && node.logical_operator?) ||
|
|
99
|
+
(node.respond_to?(:comparison_method?) && node.comparison_method?)
|
|
100
|
+
end
|
|
95
101
|
end
|
|
96
102
|
end
|
|
97
103
|
end
|
|
@@ -10,11 +10,18 @@ module RuboCop
|
|
|
10
10
|
# foo = foo
|
|
11
11
|
# foo, bar = foo, bar
|
|
12
12
|
# Foo = Foo
|
|
13
|
+
# hash['foo'] = hash['foo']
|
|
14
|
+
# obj.attr = obj.attr
|
|
13
15
|
#
|
|
14
16
|
# # good
|
|
15
17
|
# foo = bar
|
|
16
18
|
# foo, bar = bar, foo
|
|
17
19
|
# Foo = Bar
|
|
20
|
+
# hash['foo'] = hash['bar']
|
|
21
|
+
# obj.attr = obj.attr2
|
|
22
|
+
#
|
|
23
|
+
# # good (method calls possibly can return different results)
|
|
24
|
+
# hash[foo] = hash[foo]
|
|
18
25
|
#
|
|
19
26
|
class SelfAssignment < Base
|
|
20
27
|
MSG = 'Self-assignment detected.'
|
|
@@ -26,6 +33,15 @@ module RuboCop
|
|
|
26
33
|
gvasgn: :gvar
|
|
27
34
|
}.freeze
|
|
28
35
|
|
|
36
|
+
def on_send(node)
|
|
37
|
+
if node.method?(:[]=)
|
|
38
|
+
handle_key_assignment(node) if node.arguments.size == 2
|
|
39
|
+
elsif node.assignment_method?
|
|
40
|
+
handle_attribute_assignment(node) if node.arguments.size == 1
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
alias on_csend on_send
|
|
44
|
+
|
|
29
45
|
def on_lvasgn(node)
|
|
30
46
|
lhs, rhs = *node
|
|
31
47
|
return unless rhs
|
|
@@ -72,6 +88,28 @@ module RuboCop
|
|
|
72
88
|
rhs.type == ASSIGNMENT_TYPE_TO_RHS_TYPE[lhs.type] &&
|
|
73
89
|
rhs.children.first == lhs.children.first
|
|
74
90
|
end
|
|
91
|
+
|
|
92
|
+
def handle_key_assignment(node)
|
|
93
|
+
value_node = node.arguments[1]
|
|
94
|
+
|
|
95
|
+
if value_node.send_type? && value_node.method?(:[]) &&
|
|
96
|
+
node.receiver == value_node.receiver &&
|
|
97
|
+
!node.first_argument.call_type? &&
|
|
98
|
+
node.first_argument == value_node.first_argument
|
|
99
|
+
add_offense(node)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def handle_attribute_assignment(node)
|
|
104
|
+
first_argument = node.first_argument
|
|
105
|
+
return unless first_argument.respond_to?(:arguments) && first_argument.arguments.empty?
|
|
106
|
+
|
|
107
|
+
if first_argument.call_type? &&
|
|
108
|
+
node.receiver == first_argument.receiver &&
|
|
109
|
+
first_argument.method_name.to_s == node.method_name.to_s.delete_suffix('=')
|
|
110
|
+
add_offense(node)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
75
113
|
end
|
|
76
114
|
end
|
|
77
115
|
end
|
|
@@ -123,6 +123,7 @@ module RuboCop
|
|
|
123
123
|
|
|
124
124
|
# Shorthand assignments always use their arguments
|
|
125
125
|
next false if assignment_node.shorthand_asgn?
|
|
126
|
+
next false unless assignment_node.parent
|
|
126
127
|
|
|
127
128
|
node_within_block_or_conditional =
|
|
128
129
|
node_within_block_or_conditional?(assignment_node.parent, argument.scope.node)
|
|
@@ -68,7 +68,7 @@ module RuboCop
|
|
|
68
68
|
|
|
69
69
|
def same_conditions_node_different_branch?(variable, outer_local_variable)
|
|
70
70
|
variable_node = variable_node(variable)
|
|
71
|
-
return false unless variable_node
|
|
71
|
+
return false unless node_or_its_ascendant_conditional?(variable_node)
|
|
72
72
|
|
|
73
73
|
outer_local_variable_node =
|
|
74
74
|
find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
|
|
@@ -96,6 +96,12 @@ module RuboCop
|
|
|
96
96
|
|
|
97
97
|
find_conditional_node_from_ascendant(parent)
|
|
98
98
|
end
|
|
99
|
+
|
|
100
|
+
def node_or_its_ascendant_conditional?(node)
|
|
101
|
+
return true if node.conditional?
|
|
102
|
+
|
|
103
|
+
!!find_conditional_node_from_ascendant(node)
|
|
104
|
+
end
|
|
99
105
|
end
|
|
100
106
|
end
|
|
101
107
|
end
|
|
@@ -32,25 +32,25 @@ module RuboCop
|
|
|
32
32
|
# @!method struct_new(node)
|
|
33
33
|
def_node_matcher :struct_new, <<~PATTERN
|
|
34
34
|
(send
|
|
35
|
-
(const
|
|
35
|
+
(const {nil? cbase} :Struct) :new ...)
|
|
36
36
|
PATTERN
|
|
37
37
|
|
|
38
38
|
def on_send(node)
|
|
39
|
-
return unless struct_new(node)
|
|
40
|
-
node.arguments.each_with_index do |arg, index|
|
|
41
|
-
# Ignore if the first argument is a class name
|
|
42
|
-
next if index.zero? && arg.str_type?
|
|
39
|
+
return unless struct_new(node)
|
|
43
40
|
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
node.arguments.each_with_index do |arg, index|
|
|
42
|
+
# Ignore if the first argument is a class name
|
|
43
|
+
next if index.zero? && arg.str_type?
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
# Ignore if the argument is not a member name
|
|
46
|
+
next unless STRUCT_MEMBER_NAME_TYPES.include?(arg.type)
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
member_name = arg.value
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
next unless STRUCT_METHOD_NAMES.include?(member_name.to_sym)
|
|
51
|
+
|
|
52
|
+
message = format(MSG, member_name: member_name.inspect, method_name: member_name.to_s)
|
|
53
|
+
add_offense(arg, message: message)
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
end
|
|
@@ -119,7 +119,7 @@ module RuboCop
|
|
|
119
119
|
ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block, :numblock).first
|
|
120
120
|
return false unless ancestor
|
|
121
121
|
|
|
122
|
-
end_line = ancestor.loc.end.
|
|
122
|
+
end_line = ancestor.loc.end&.line || ancestor.loc.last_line
|
|
123
123
|
processed_source[node.first_line...end_line].any? { |line| comment_line?(line) }
|
|
124
124
|
end
|
|
125
125
|
|
|
@@ -19,6 +19,7 @@ module RuboCop
|
|
|
19
19
|
# 'underscored_string'.to_sym
|
|
20
20
|
# :'underscored_symbol'
|
|
21
21
|
# 'hyphenated-string'.to_sym
|
|
22
|
+
# "string_#{interpolation}".to_sym
|
|
22
23
|
#
|
|
23
24
|
# # good
|
|
24
25
|
# :string
|
|
@@ -26,6 +27,7 @@ module RuboCop
|
|
|
26
27
|
# :underscored_string
|
|
27
28
|
# :underscored_symbol
|
|
28
29
|
# :'hyphenated-string'
|
|
30
|
+
# :"string_#{interpolation}"
|
|
29
31
|
#
|
|
30
32
|
# @example EnforcedStyle: strict (default)
|
|
31
33
|
#
|
|
@@ -75,9 +77,12 @@ module RuboCop
|
|
|
75
77
|
|
|
76
78
|
def on_send(node)
|
|
77
79
|
return unless node.receiver
|
|
78
|
-
return unless node.receiver.str_type? || node.receiver.sym_type?
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
if node.receiver.str_type? || node.receiver.sym_type?
|
|
82
|
+
register_offense(node, correction: node.receiver.value.to_sym.inspect)
|
|
83
|
+
elsif node.receiver.dstr_type?
|
|
84
|
+
register_offense(node, correction: ":\"#{node.receiver.value.to_sym}\"")
|
|
85
|
+
end
|
|
81
86
|
end
|
|
82
87
|
|
|
83
88
|
def on_sym(node)
|
|
@@ -124,7 +129,7 @@ module RuboCop
|
|
|
124
129
|
source == value ||
|
|
125
130
|
# `Symbol#inspect` uses double quotes, but allow single-quoted
|
|
126
131
|
# symbols to work as well.
|
|
127
|
-
source.tr("'", '"') == value
|
|
132
|
+
source.gsub('"', '\"').tr("'", '"') == value
|
|
128
133
|
end
|
|
129
134
|
|
|
130
135
|
def requires_quotes?(sym_node)
|
|
@@ -17,9 +17,12 @@ module RuboCop
|
|
|
17
17
|
private
|
|
18
18
|
|
|
19
19
|
def add_offense_from_diagnostic(diagnostic, ruby_version)
|
|
20
|
-
message =
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
message = if lsp_mode?
|
|
21
|
+
diagnostic.message
|
|
22
|
+
else
|
|
23
|
+
"#{diagnostic.message}\n(Using Ruby #{ruby_version} parser; " \
|
|
24
|
+
'configure using `TargetRubyVersion` parameter, under `AllCops`)'
|
|
25
|
+
end
|
|
23
26
|
add_offense(diagnostic.location, message: message, severity: diagnostic.level)
|
|
24
27
|
end
|
|
25
28
|
|
|
@@ -74,7 +74,7 @@ module RuboCop
|
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
77
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
78
78
|
def argument_match?(send_arg, def_arg)
|
|
79
79
|
def_arg_name = def_arg.children[0]
|
|
80
80
|
|
|
@@ -87,12 +87,14 @@ module RuboCop
|
|
|
87
87
|
send_arg.hash_type? &&
|
|
88
88
|
send_arg.pairs.any? { |pair| passing_keyword_arg?(pair, def_arg_name) }
|
|
89
89
|
when :kwrestarg
|
|
90
|
-
send_arg.each_child_node(:kwsplat).any?
|
|
90
|
+
send_arg.each_child_node(:kwsplat, :forwarded_kwrestarg).any? do |child|
|
|
91
|
+
child.source == def_arg.source
|
|
92
|
+
end
|
|
91
93
|
when :forward_arg
|
|
92
94
|
send_arg.forwarded_args_type?
|
|
93
95
|
end
|
|
94
96
|
end
|
|
95
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
97
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
96
98
|
end
|
|
97
99
|
end
|
|
98
100
|
end
|
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
|
34
34
|
MSG = 'Avoid leaving a trailing comma in attribute declarations.'
|
|
35
35
|
|
|
36
36
|
def on_send(node)
|
|
37
|
-
return unless node.attribute_accessor? && node.
|
|
37
|
+
return unless node.attribute_accessor? && node.last_argument.def_type?
|
|
38
38
|
|
|
39
39
|
trailing_comma = trailing_comma_range(node)
|
|
40
40
|
|
|
@@ -69,8 +69,8 @@ module RuboCop
|
|
|
69
69
|
# @!method reduce_with_block?(node)
|
|
70
70
|
def_node_matcher :reduce_with_block?, <<~PATTERN
|
|
71
71
|
{
|
|
72
|
-
(block (
|
|
73
|
-
(numblock (
|
|
72
|
+
(block (call _recv {:reduce :inject} ...) args ...)
|
|
73
|
+
(numblock (call _recv {:reduce :inject} ...) ...)
|
|
74
74
|
}
|
|
75
75
|
PATTERN
|
|
76
76
|
|
|
@@ -256,7 +256,7 @@ module RuboCop
|
|
|
256
256
|
|
|
257
257
|
def any_method_definition?(child)
|
|
258
258
|
cop_config.fetch('MethodCreatingMethods', []).any? do |m|
|
|
259
|
-
matcher_name = "#{m}_method?"
|
|
259
|
+
matcher_name = :"#{m}_method?"
|
|
260
260
|
unless respond_to?(matcher_name)
|
|
261
261
|
self.class.def_node_matcher matcher_name, <<~PATTERN
|
|
262
262
|
{def (send nil? :#{m} ...)}
|
|
@@ -279,7 +279,7 @@ module RuboCop
|
|
|
279
279
|
|
|
280
280
|
def any_context_creating_methods?(child)
|
|
281
281
|
cop_config.fetch('ContextCreatingMethods', []).any? do |m|
|
|
282
|
-
matcher_name = "#{m}_block?"
|
|
282
|
+
matcher_name = :"#{m}_block?"
|
|
283
283
|
unless respond_to?(matcher_name)
|
|
284
284
|
self.class.def_node_matcher matcher_name, <<~PATTERN
|
|
285
285
|
({block numblock} (send {nil? const} {:#{m}} ...) ...)
|
|
@@ -7,12 +7,18 @@ module RuboCop
|
|
|
7
7
|
# scope.
|
|
8
8
|
# The basic idea for this cop was from the warning of `ruby -cw`:
|
|
9
9
|
#
|
|
10
|
-
#
|
|
10
|
+
# [source,console]
|
|
11
|
+
# ----
|
|
12
|
+
# assigned but unused variable - foo
|
|
13
|
+
# ----
|
|
11
14
|
#
|
|
12
15
|
# Currently this cop has advanced logic that detects unreferenced
|
|
13
16
|
# reassignments and properly handles varied cases such as branch, loop,
|
|
14
17
|
# rescue, ensure, etc.
|
|
15
18
|
#
|
|
19
|
+
# NOTE: Given the assignment `foo = 1, bar = 2`, removing unused variables
|
|
20
|
+
# can lead to a syntax error, so this case is not autocorrected.
|
|
21
|
+
#
|
|
16
22
|
# @safety
|
|
17
23
|
# This cop's autocorrection is unsafe because removing assignment from
|
|
18
24
|
# operator assignment can cause NameError if this assignment has been used to declare
|
|
@@ -51,25 +57,24 @@ module RuboCop
|
|
|
51
57
|
scope.variables.each_value { |variable| check_for_unused_assignments(variable) }
|
|
52
58
|
end
|
|
53
59
|
|
|
60
|
+
# rubocop:disable Metrics/AbcSize
|
|
54
61
|
def check_for_unused_assignments(variable)
|
|
55
62
|
return if variable.should_be_unused?
|
|
56
63
|
|
|
57
64
|
variable.assignments.each do |assignment|
|
|
58
|
-
next if assignment.used?
|
|
65
|
+
next if assignment.used? || part_of_ignored_node?(assignment.node)
|
|
59
66
|
|
|
60
67
|
message = message_for_useless_assignment(assignment)
|
|
68
|
+
range = offense_range(assignment)
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
else
|
|
65
|
-
assignment.node.loc.name
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
add_offense(location, message: message) do |corrector|
|
|
69
|
-
autocorrect(corrector, assignment)
|
|
70
|
+
add_offense(range, message: message) do |corrector|
|
|
71
|
+
autocorrect(corrector, assignment) unless sequential_assignment?(assignment.node)
|
|
70
72
|
end
|
|
73
|
+
|
|
74
|
+
ignore_node(assignment.node) if chained_assignment?(assignment.node)
|
|
71
75
|
end
|
|
72
76
|
end
|
|
77
|
+
# rubocop:enable Metrics/AbcSize
|
|
73
78
|
|
|
74
79
|
def message_for_useless_assignment(assignment)
|
|
75
80
|
variable = assignment.variable
|
|
@@ -77,6 +82,28 @@ module RuboCop
|
|
|
77
82
|
format(MSG, variable: variable.name) + message_specification(assignment, variable).to_s
|
|
78
83
|
end
|
|
79
84
|
|
|
85
|
+
def offense_range(assignment)
|
|
86
|
+
if assignment.regexp_named_capture?
|
|
87
|
+
assignment.node.children.first.source_range
|
|
88
|
+
else
|
|
89
|
+
assignment.node.loc.name
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def sequential_assignment?(node)
|
|
94
|
+
if node.lvasgn_type? && node.expression&.array_type? &&
|
|
95
|
+
node.each_descendant.any?(&:assignment?)
|
|
96
|
+
return true
|
|
97
|
+
end
|
|
98
|
+
return false unless node.parent
|
|
99
|
+
|
|
100
|
+
sequential_assignment?(node.parent)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def chained_assignment?(node)
|
|
104
|
+
node.respond_to?(:expression) && node.expression&.lvasgn_type?
|
|
105
|
+
end
|
|
106
|
+
|
|
80
107
|
def message_specification(assignment, variable)
|
|
81
108
|
if assignment.multiple_assignment?
|
|
82
109
|
multiple_assignment_message(variable.name)
|
|
@@ -96,8 +123,7 @@ module RuboCop
|
|
|
96
123
|
return_value_node = return_value_node_of_scope(scope)
|
|
97
124
|
return unless assignment.meta_assignment_node.equal?(return_value_node)
|
|
98
125
|
|
|
99
|
-
" Use `#{assignment.operator.
|
|
100
|
-
"instead of `#{assignment.operator}`."
|
|
126
|
+
" Use `#{assignment.operator.delete_suffix('=')}` instead of `#{assignment.operator}`."
|
|
101
127
|
end
|
|
102
128
|
|
|
103
129
|
def similar_name_message(variable)
|
|
@@ -6,6 +6,16 @@ module RuboCop
|
|
|
6
6
|
# Checks for operators, variables, literals, lambda, proc and nonmutating
|
|
7
7
|
# methods used in void context.
|
|
8
8
|
#
|
|
9
|
+
# `each` blocks are allowed to prevent false positives.
|
|
10
|
+
# For example, the expression inside the `each` block below.
|
|
11
|
+
# It's not void, especially when the receiver is an `Enumerator`:
|
|
12
|
+
#
|
|
13
|
+
# [source,ruby]
|
|
14
|
+
# ----
|
|
15
|
+
# enumerator = [1, 2, 3].filter
|
|
16
|
+
# enumerator.each { |item| item >= 2 } #=> [2, 3]
|
|
17
|
+
# ----
|
|
18
|
+
#
|
|
9
19
|
# @example CheckForMethodsWithNoSideEffects: false (default)
|
|
10
20
|
# # bad
|
|
11
21
|
# def some_method
|
|
@@ -47,6 +57,7 @@ module RuboCop
|
|
|
47
57
|
|
|
48
58
|
OP_MSG = 'Operator `%<op>s` used in void context.'
|
|
49
59
|
VAR_MSG = 'Variable `%<var>s` used in void context.'
|
|
60
|
+
CONST_MSG = 'Constant `%<var>s` used in void context.'
|
|
50
61
|
LIT_MSG = 'Literal `%<lit>s` used in void context.'
|
|
51
62
|
SELF_MSG = '`self` used in void context.'
|
|
52
63
|
EXPRESSION_MSG = '`%<expression>s` used in void context.'
|
|
@@ -72,6 +83,7 @@ module RuboCop
|
|
|
72
83
|
return unless node.body && !node.body.begin_type?
|
|
73
84
|
return unless in_void_context?(node.body)
|
|
74
85
|
|
|
86
|
+
check_void_op(node.body) { node.method?(:each) }
|
|
75
87
|
check_expression(node.body)
|
|
76
88
|
end
|
|
77
89
|
|
|
@@ -87,11 +99,13 @@ module RuboCop
|
|
|
87
99
|
def check_begin(node)
|
|
88
100
|
expressions = *node
|
|
89
101
|
expressions.pop unless in_void_context?(node)
|
|
90
|
-
expressions.each
|
|
102
|
+
expressions.each do |expr|
|
|
103
|
+
check_void_op(expr)
|
|
104
|
+
check_expression(expr)
|
|
105
|
+
end
|
|
91
106
|
end
|
|
92
107
|
|
|
93
108
|
def check_expression(expr)
|
|
94
|
-
check_void_op(expr)
|
|
95
109
|
check_literal(expr)
|
|
96
110
|
check_var(expr)
|
|
97
111
|
check_self(expr)
|
|
@@ -101,8 +115,9 @@ module RuboCop
|
|
|
101
115
|
check_nonmutating(expr)
|
|
102
116
|
end
|
|
103
117
|
|
|
104
|
-
def check_void_op(node)
|
|
118
|
+
def check_void_op(node, &block)
|
|
105
119
|
return unless node.send_type? && OPERATORS.include?(node.method_name)
|
|
120
|
+
return if block && yield(node)
|
|
106
121
|
|
|
107
122
|
add_offense(node.loc.selector,
|
|
108
123
|
message: format(OP_MSG, op: node.method_name)) do |corrector|
|
|
@@ -113,17 +128,26 @@ module RuboCop
|
|
|
113
128
|
def check_var(node)
|
|
114
129
|
return unless node.variable? || node.const_type?
|
|
115
130
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
if node.const_type?
|
|
132
|
+
template = node.special_keyword? ? VAR_MSG : CONST_MSG
|
|
133
|
+
|
|
134
|
+
offense_range = node
|
|
135
|
+
message = format(template, var: node.source)
|
|
136
|
+
else
|
|
137
|
+
offense_range = node.loc.name
|
|
138
|
+
message = format(VAR_MSG, var: node.loc.name.source)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
add_offense(offense_range, message: message) do |corrector|
|
|
142
|
+
autocorrect_void_expression(corrector, node)
|
|
119
143
|
end
|
|
120
144
|
end
|
|
121
145
|
|
|
122
146
|
def check_literal(node)
|
|
123
|
-
return if !node
|
|
147
|
+
return if !entirely_literal?(node) || node.xstr_type? || node.range_type?
|
|
124
148
|
|
|
125
149
|
add_offense(node, message: format(LIT_MSG, lit: node.source)) do |corrector|
|
|
126
|
-
|
|
150
|
+
autocorrect_void_expression(corrector, node)
|
|
127
151
|
end
|
|
128
152
|
end
|
|
129
153
|
|
|
@@ -131,7 +155,7 @@ module RuboCop
|
|
|
131
155
|
return unless node.self_type?
|
|
132
156
|
|
|
133
157
|
add_offense(node, message: SELF_MSG) do |corrector|
|
|
134
|
-
|
|
158
|
+
autocorrect_void_expression(corrector, node)
|
|
135
159
|
end
|
|
136
160
|
end
|
|
137
161
|
|
|
@@ -181,18 +205,6 @@ module RuboCop
|
|
|
181
205
|
end
|
|
182
206
|
end
|
|
183
207
|
|
|
184
|
-
def autocorrect_void_var(corrector, node)
|
|
185
|
-
corrector.remove(range_with_surrounding_space(range: node.loc.name, side: :left))
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
def autocorrect_void_literal(corrector, node)
|
|
189
|
-
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
def autocorrect_void_self(corrector, node)
|
|
193
|
-
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
|
194
|
-
end
|
|
195
|
-
|
|
196
208
|
def autocorrect_void_expression(corrector, node)
|
|
197
209
|
corrector.remove(range_with_surrounding_space(range: node.source_range, side: :left))
|
|
198
210
|
end
|
|
@@ -205,6 +217,19 @@ module RuboCop
|
|
|
205
217
|
end
|
|
206
218
|
corrector.replace(send_node.loc.selector, suggestion)
|
|
207
219
|
end
|
|
220
|
+
|
|
221
|
+
def entirely_literal?(node)
|
|
222
|
+
case node.type
|
|
223
|
+
when :array
|
|
224
|
+
node.each_value.all? { |value| entirely_literal?(value) }
|
|
225
|
+
when :hash
|
|
226
|
+
return false unless node.each_key.all? { |key| entirely_literal?(key) }
|
|
227
|
+
|
|
228
|
+
node.each_value.all? { |value| entirely_literal?(value) }
|
|
229
|
+
else
|
|
230
|
+
node.literal?
|
|
231
|
+
end
|
|
232
|
+
end
|
|
208
233
|
end
|
|
209
234
|
end
|
|
210
235
|
end
|
|
@@ -10,9 +10,9 @@ module RuboCop
|
|
|
10
10
|
#
|
|
11
11
|
# Interpreting ABC size:
|
|
12
12
|
#
|
|
13
|
-
# *
|
|
14
|
-
# * 18..30 unsatisfactory
|
|
15
|
-
# *
|
|
13
|
+
# * ``<= 17`` satisfactory
|
|
14
|
+
# * `18..30` unsatisfactory
|
|
15
|
+
# * `>` 30 dangerous
|
|
16
16
|
#
|
|
17
17
|
# You can have repeated "attributes" calls count as a single "branch".
|
|
18
18
|
# For this purpose, attributes are any method with no argument; no attempt
|
|
@@ -12,6 +12,7 @@ module RuboCop
|
|
|
12
12
|
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
|
13
13
|
# will be counted as one line regardless of its actual size.
|
|
14
14
|
#
|
|
15
|
+
# NOTE: This cop does not apply for `Struct` definitions.
|
|
15
16
|
#
|
|
16
17
|
# NOTE: The `ExcludedMethods` configuration is deprecated and only kept
|
|
17
18
|
# for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns`
|
|
@@ -40,7 +41,6 @@ module RuboCop
|
|
|
40
41
|
# )
|
|
41
42
|
# end # 6 points
|
|
42
43
|
#
|
|
43
|
-
# NOTE: This cop does not apply for `Struct` definitions.
|
|
44
44
|
class BlockLength < Base
|
|
45
45
|
include CodeLength
|
|
46
46
|
include AllowedMethods
|
|
@@ -11,6 +11,8 @@ module RuboCop
|
|
|
11
11
|
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
|
12
12
|
# will be counted as one line regardless of its actual size.
|
|
13
13
|
#
|
|
14
|
+
# NOTE: This cop also applies for `Struct` definitions.
|
|
15
|
+
#
|
|
14
16
|
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
|
15
17
|
#
|
|
16
18
|
# class Foo
|
|
@@ -34,15 +36,18 @@ module RuboCop
|
|
|
34
36
|
# )
|
|
35
37
|
# end # 6 points
|
|
36
38
|
#
|
|
37
|
-
#
|
|
38
|
-
# NOTE: This cop also applies for `Struct` definitions.
|
|
39
39
|
class ClassLength < Base
|
|
40
40
|
include CodeLength
|
|
41
41
|
|
|
42
42
|
def on_class(node)
|
|
43
43
|
check_code_length(node)
|
|
44
44
|
end
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
def on_sclass(node)
|
|
47
|
+
return if node.each_ancestor(:class).any?
|
|
48
|
+
|
|
49
|
+
on_class(node)
|
|
50
|
+
end
|
|
46
51
|
|
|
47
52
|
def on_casgn(node)
|
|
48
53
|
parent = node.parent
|