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
|
@@ -17,12 +17,11 @@ module RuboCop
|
|
|
17
17
|
include Parentheses
|
|
18
18
|
extend AutoCorrector
|
|
19
19
|
|
|
20
|
+
ALLOWED_NODE_TYPES = %i[and or send splat kwsplat].freeze
|
|
21
|
+
|
|
20
22
|
# @!method square_brackets?(node)
|
|
21
23
|
def_node_matcher :square_brackets?, '(send {(send _recv _msg) str array hash} :[] ...)'
|
|
22
24
|
|
|
23
|
-
# @!method range_end?(node)
|
|
24
|
-
def_node_matcher :range_end?, '^^{irange erange}'
|
|
25
|
-
|
|
26
25
|
# @!method method_node_and_args(node)
|
|
27
26
|
def_node_matcher :method_node_and_args, '$(call _recv _msg $...)'
|
|
28
27
|
|
|
@@ -54,7 +53,7 @@ module RuboCop
|
|
|
54
53
|
def ignore_syntax?(node)
|
|
55
54
|
return false unless (parent = node.parent)
|
|
56
55
|
|
|
57
|
-
parent.while_post_type? || parent.until_post_type? ||
|
|
56
|
+
parent.while_post_type? || parent.until_post_type? || parent.match_with_lvasgn_type? ||
|
|
58
57
|
like_method_argument_parentheses?(parent)
|
|
59
58
|
end
|
|
60
59
|
|
|
@@ -62,7 +61,8 @@ module RuboCop
|
|
|
62
61
|
allowed_ancestor?(node) ||
|
|
63
62
|
allowed_method_call?(node) ||
|
|
64
63
|
allowed_multiple_expression?(node) ||
|
|
65
|
-
allowed_ternary?(node)
|
|
64
|
+
allowed_ternary?(node) ||
|
|
65
|
+
node.parent&.range_type?
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def allowed_ancestor?(node)
|
|
@@ -98,7 +98,9 @@ module RuboCop
|
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
def like_method_argument_parentheses?(node)
|
|
101
|
-
node.send_type? && node.
|
|
101
|
+
return false if !node.send_type? && !node.super_type? && !node.yield_type?
|
|
102
|
+
|
|
103
|
+
node.arguments.one? && !node.parenthesized? &&
|
|
102
104
|
!node.arithmetic_operation? && node.first_argument.begin_type?
|
|
103
105
|
end
|
|
104
106
|
|
|
@@ -109,34 +111,69 @@ module RuboCop
|
|
|
109
111
|
|
|
110
112
|
def first_arg_begins_with_hash_literal?(node)
|
|
111
113
|
# Don't flag `method ({key: value})` or `method ({key: value}.method)`
|
|
112
|
-
method_chain_begins_with_hash_literal
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
hash_literal = method_chain_begins_with_hash_literal(node.children.first)
|
|
115
|
+
if (root_method = node.each_ancestor(:send).to_a.last)
|
|
116
|
+
parenthesized = root_method.parenthesized_call?
|
|
117
|
+
end
|
|
118
|
+
hash_literal && first_argument?(node) && !parentheses?(hash_literal) && !parenthesized
|
|
115
119
|
end
|
|
116
120
|
|
|
117
|
-
def method_chain_begins_with_hash_literal
|
|
118
|
-
return
|
|
119
|
-
return
|
|
120
|
-
return
|
|
121
|
+
def method_chain_begins_with_hash_literal(node)
|
|
122
|
+
return if node.nil?
|
|
123
|
+
return node if node.hash_type?
|
|
124
|
+
return unless node.send_type?
|
|
121
125
|
|
|
122
|
-
method_chain_begins_with_hash_literal
|
|
126
|
+
method_chain_begins_with_hash_literal(node.children.first)
|
|
123
127
|
end
|
|
124
128
|
|
|
125
129
|
def check(begin_node)
|
|
126
130
|
node = begin_node.children.first
|
|
127
|
-
return offense(begin_node, 'a keyword') if keyword_with_redundant_parentheses?(node)
|
|
128
|
-
return offense(begin_node, 'a literal') if disallowed_literal?(begin_node, node)
|
|
129
|
-
return offense(begin_node, 'a variable') if node.variable?
|
|
130
|
-
return offense(begin_node, 'a constant') if node.const_type?
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
if (message = find_offense_message(begin_node, node))
|
|
133
|
+
return offense(begin_node, message)
|
|
134
|
+
end
|
|
133
135
|
|
|
134
136
|
check_send(begin_node, node) if node.call_type?
|
|
135
137
|
end
|
|
136
138
|
|
|
139
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
140
|
+
def find_offense_message(begin_node, node)
|
|
141
|
+
return 'a keyword' if keyword_with_redundant_parentheses?(node)
|
|
142
|
+
return 'a literal' if disallowed_literal?(begin_node, node)
|
|
143
|
+
return 'a variable' if node.variable?
|
|
144
|
+
return 'a constant' if node.const_type?
|
|
145
|
+
if node.lambda_or_proc? && (node.braces? || node.send_node.lambda_literal?)
|
|
146
|
+
return 'an expression'
|
|
147
|
+
end
|
|
148
|
+
return 'an interpolated expression' if interpolation?(begin_node)
|
|
149
|
+
|
|
150
|
+
return if begin_node.chained?
|
|
151
|
+
|
|
152
|
+
if node.and_type? || node.or_type?
|
|
153
|
+
return if node.semantic_operator? && begin_node.parent
|
|
154
|
+
return if node.multiline? && allow_in_multiline_conditions?
|
|
155
|
+
return if ALLOWED_NODE_TYPES.include?(begin_node.parent&.type)
|
|
156
|
+
return if begin_node.parent&.if_type? && begin_node.parent&.ternary?
|
|
157
|
+
|
|
158
|
+
'a logical expression'
|
|
159
|
+
elsif node.respond_to?(:comparison_method?) && node.comparison_method?
|
|
160
|
+
return unless begin_node.parent.nil?
|
|
161
|
+
|
|
162
|
+
'a comparison expression'
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
166
|
+
|
|
137
167
|
# @!method interpolation?(node)
|
|
138
168
|
def_node_matcher :interpolation?, '[^begin ^^dstr]'
|
|
139
169
|
|
|
170
|
+
def allow_in_multiline_conditions?
|
|
171
|
+
parentheses_around_condition_config = config.for_cop('Style/ParenthesesAroundCondition')
|
|
172
|
+
return false unless parentheses_around_condition_config['Enabled']
|
|
173
|
+
|
|
174
|
+
!!parentheses_around_condition_config['AllowInMultilineConditions']
|
|
175
|
+
end
|
|
176
|
+
|
|
140
177
|
def check_send(begin_node, node)
|
|
141
178
|
return check_unary(begin_node, node) if node.unary_operation?
|
|
142
179
|
|
|
@@ -201,7 +238,6 @@ module RuboCop
|
|
|
201
238
|
def method_call_with_redundant_parentheses?(node)
|
|
202
239
|
return false unless node.call_type?
|
|
203
240
|
return false if node.prefix_not?
|
|
204
|
-
return false if range_end?(node)
|
|
205
241
|
|
|
206
242
|
send_node, args = method_node_and_args(node)
|
|
207
243
|
|
|
@@ -213,7 +249,13 @@ module RuboCop
|
|
|
213
249
|
end
|
|
214
250
|
|
|
215
251
|
def first_argument?(node)
|
|
216
|
-
first_send_argument?(node) ||
|
|
252
|
+
if first_send_argument?(node) ||
|
|
253
|
+
first_super_argument?(node) ||
|
|
254
|
+
first_yield_argument?(node)
|
|
255
|
+
return true
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
node.each_ancestor.any? { |ancestor| first_argument?(ancestor) }
|
|
217
259
|
end
|
|
218
260
|
|
|
219
261
|
# @!method first_send_argument?(node)
|
|
@@ -40,7 +40,9 @@ module RuboCop
|
|
|
40
40
|
byteindex byterindex gsub gsub! partition rpartition scan split start_with? sub sub!
|
|
41
41
|
].freeze
|
|
42
42
|
DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze
|
|
43
|
-
STR_SPECIAL_CHARS = %w[
|
|
43
|
+
STR_SPECIAL_CHARS = %w[
|
|
44
|
+
\a \c \C \e \f \M \n \" \' \\\\ \t \b \f \r \u \v \x \0 \1 \2 \3 \4 \5 \6 \7
|
|
45
|
+
].freeze
|
|
44
46
|
|
|
45
47
|
def on_send(node)
|
|
46
48
|
return unless (regexp_node = node.first_argument)
|
|
@@ -48,15 +50,14 @@ module RuboCop
|
|
|
48
50
|
return if !regexp_node.regopt.children.empty? || regexp_node.content == ' '
|
|
49
51
|
return unless determinist_regexp?(regexp_node)
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
quote = new_argument.include?('"') ? "'" : '"'
|
|
53
|
-
prefer = "#{quote}#{new_argument}#{quote}"
|
|
53
|
+
prefer = preferred_argument(regexp_node)
|
|
54
54
|
message = format(MSG, prefer: prefer, current: regexp_node.source)
|
|
55
55
|
|
|
56
56
|
add_offense(regexp_node, message: message) do |corrector|
|
|
57
57
|
corrector.replace(regexp_node, prefer)
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
|
+
alias on_csend on_send
|
|
60
61
|
|
|
61
62
|
private
|
|
62
63
|
|
|
@@ -64,6 +65,19 @@ module RuboCop
|
|
|
64
65
|
DETERMINISTIC_REGEX.match?(regexp_node.source)
|
|
65
66
|
end
|
|
66
67
|
|
|
68
|
+
def preferred_argument(regexp_node)
|
|
69
|
+
new_argument = replacement(regexp_node)
|
|
70
|
+
|
|
71
|
+
if new_argument.include?('"')
|
|
72
|
+
new_argument.gsub!("'", "\\\\'")
|
|
73
|
+
quote = "'"
|
|
74
|
+
else
|
|
75
|
+
quote = '"'
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
"#{quote}#{new_argument}#{quote}"
|
|
79
|
+
end
|
|
80
|
+
|
|
67
81
|
def replacement(regexp_node)
|
|
68
82
|
regexp_content = regexp_node.content
|
|
69
83
|
stack = []
|
|
@@ -22,13 +22,18 @@ module RuboCop
|
|
|
22
22
|
# return something
|
|
23
23
|
# end
|
|
24
24
|
#
|
|
25
|
-
# #
|
|
25
|
+
# # bad
|
|
26
26
|
# def test
|
|
27
27
|
# return something if something_else
|
|
28
28
|
# end
|
|
29
29
|
#
|
|
30
30
|
# # good
|
|
31
31
|
# def test
|
|
32
|
+
# something if something_else
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# # good
|
|
36
|
+
# def test
|
|
32
37
|
# if x
|
|
33
38
|
# elsif y
|
|
34
39
|
# else
|
|
@@ -53,7 +58,7 @@ module RuboCop
|
|
|
53
58
|
|
|
54
59
|
MSG = 'Redundant `return` detected.'
|
|
55
60
|
MULTI_RETURN_MSG = 'To return multiple values, use an array.'
|
|
56
|
-
RESTRICT_ON_SEND = %i[define_method define_singleton_method].freeze
|
|
61
|
+
RESTRICT_ON_SEND = %i[define_method define_singleton_method lambda].freeze
|
|
57
62
|
|
|
58
63
|
def on_send(node)
|
|
59
64
|
return unless (parent = node.parent) && parent.block_type?
|
|
@@ -136,7 +141,7 @@ module RuboCop
|
|
|
136
141
|
end
|
|
137
142
|
|
|
138
143
|
def check_if_node(node)
|
|
139
|
-
return if node.
|
|
144
|
+
return if node.ternary?
|
|
140
145
|
|
|
141
146
|
check_branch(node.if_branch)
|
|
142
147
|
check_branch(node.else_branch)
|
|
@@ -17,7 +17,8 @@ module RuboCop
|
|
|
17
17
|
# protected scope, you cannot send private messages this way.
|
|
18
18
|
#
|
|
19
19
|
# Note we allow uses of `self` with operators because it would be awkward
|
|
20
|
-
# otherwise.
|
|
20
|
+
# otherwise. Also allows the use of `self.it` without arguments in blocks,
|
|
21
|
+
# as in `0.times { self.it }`, following `Lint/ItWithoutArgumentsInBlock` cop.
|
|
21
22
|
#
|
|
22
23
|
# @example
|
|
23
24
|
#
|
|
@@ -107,8 +108,8 @@ module RuboCop
|
|
|
107
108
|
def on_send(node)
|
|
108
109
|
return unless node.self_receiver? && regular_method_call?(node)
|
|
109
110
|
return if node.parent&.mlhs_type?
|
|
110
|
-
|
|
111
111
|
return if allowed_send_node?(node)
|
|
112
|
+
return if it_method_in_block?(node)
|
|
112
113
|
|
|
113
114
|
add_offense(node.receiver) do |corrector|
|
|
114
115
|
corrector.remove(node.receiver)
|
|
@@ -155,6 +156,20 @@ module RuboCop
|
|
|
155
156
|
KERNEL_METHODS.include?(node.method_name)
|
|
156
157
|
end
|
|
157
158
|
|
|
159
|
+
# Respects `Lint/ItWithoutArgumentsInBlock` cop and the following Ruby 3.3's warning:
|
|
160
|
+
#
|
|
161
|
+
# $ ruby -e '0.times { begin; it; end }'
|
|
162
|
+
# -e:1: warning: `it` calls without arguments will refer to the first block param in
|
|
163
|
+
# Ruby 3.4; use it() or self.it
|
|
164
|
+
#
|
|
165
|
+
def it_method_in_block?(node)
|
|
166
|
+
return false unless node.method?(:it)
|
|
167
|
+
return false unless (block_node = node.each_ancestor(:block).first)
|
|
168
|
+
return false unless block_node.arguments.empty_and_without_delimiters?
|
|
169
|
+
|
|
170
|
+
node.arguments.empty? && !node.block_literal?
|
|
171
|
+
end
|
|
172
|
+
|
|
158
173
|
def regular_method_call?(node)
|
|
159
174
|
!(node.operator_method? ||
|
|
160
175
|
KEYWORDS.include?(node.method_name) ||
|
|
@@ -75,6 +75,11 @@ module RuboCop
|
|
|
75
75
|
add_offense(offense_branch) do |corrector|
|
|
76
76
|
assignment_value = opposite_branch ? opposite_branch.source : 'nil'
|
|
77
77
|
replacement = "#{assignment_value} #{keyword} #{if_node.condition.source}"
|
|
78
|
+
if opposite_branch.respond_to?(:heredoc?) && opposite_branch.heredoc?
|
|
79
|
+
replacement += opposite_branch.loc.heredoc_end.with(
|
|
80
|
+
begin_pos: opposite_branch.source_range.end_pos
|
|
81
|
+
).source
|
|
82
|
+
end
|
|
78
83
|
|
|
79
84
|
corrector.replace(if_node, replacement)
|
|
80
85
|
end
|
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
|
16
16
|
# This cop is unsafe, because `sort...last` and `max` may not return the
|
|
17
17
|
# same element in all cases.
|
|
18
18
|
#
|
|
19
|
-
# In an enumerable where there are multiple elements where
|
|
19
|
+
# In an enumerable where there are multiple elements where ``a <=> b == 0``,
|
|
20
20
|
# or where the transformation done by the `sort_by` block has the
|
|
21
21
|
# same result, `sort.last` and `max` (or `sort_by.last` and `max_by`)
|
|
22
22
|
# will return different elements. `sort.last` will return the last
|
|
@@ -87,15 +87,15 @@ module RuboCop
|
|
|
87
87
|
# @!method redundant_sort?(node)
|
|
88
88
|
def_node_matcher :redundant_sort?, <<~MATCHER
|
|
89
89
|
{
|
|
90
|
-
(
|
|
91
|
-
(
|
|
90
|
+
(call $(call _ $:sort) ${:last :first})
|
|
91
|
+
(call $(call _ $:sort) ${:[] :at :slice} {(int 0) (int -1)})
|
|
92
92
|
|
|
93
|
-
(
|
|
93
|
+
(call $(call _ $:sort_by _) ${:last :first})
|
|
94
94
|
(send $(send _ $:sort_by _) ${:[] :at :slice} {(int 0) (int -1)})
|
|
95
95
|
|
|
96
|
-
(
|
|
97
|
-
(
|
|
98
|
-
({block numblock} $(
|
|
96
|
+
(call ({block numblock} $(call _ ${:sort_by :sort}) ...) ${:last :first})
|
|
97
|
+
(call
|
|
98
|
+
({block numblock} $(call _ ${:sort_by :sort}) ...)
|
|
99
99
|
${:[] :at :slice} {(int 0) (int -1)}
|
|
100
100
|
)
|
|
101
101
|
}
|
|
@@ -108,6 +108,7 @@ module RuboCop
|
|
|
108
108
|
|
|
109
109
|
register_offense(ancestor, sort_node, sorter, accessor)
|
|
110
110
|
end
|
|
111
|
+
alias on_csend on_send
|
|
111
112
|
|
|
112
113
|
private
|
|
113
114
|
|
|
@@ -180,7 +181,7 @@ module RuboCop
|
|
|
180
181
|
end
|
|
181
182
|
|
|
182
183
|
def arg_node(node)
|
|
183
|
-
node.
|
|
184
|
+
node.first_argument
|
|
184
185
|
end
|
|
185
186
|
|
|
186
187
|
def arg_value(node)
|
|
@@ -46,12 +46,12 @@ module RuboCop
|
|
|
46
46
|
|
|
47
47
|
# @!method redundant_sort_by_block(node)
|
|
48
48
|
def_node_matcher :redundant_sort_by_block, <<~PATTERN
|
|
49
|
-
(block $(
|
|
49
|
+
(block $(call _ :sort_by) (args (arg $_x)) (lvar _x))
|
|
50
50
|
PATTERN
|
|
51
51
|
|
|
52
52
|
# @!method redundant_sort_by_numblock(node)
|
|
53
53
|
def_node_matcher :redundant_sort_by_numblock, <<~PATTERN
|
|
54
|
-
(numblock $(
|
|
54
|
+
(numblock $(call _ :sort_by) 1 (lvar :_1))
|
|
55
55
|
PATTERN
|
|
56
56
|
|
|
57
57
|
def sort_by_range(send, node)
|
|
@@ -133,7 +133,7 @@ module RuboCop
|
|
|
133
133
|
end
|
|
134
134
|
|
|
135
135
|
def percent_array_literal?(node)
|
|
136
|
-
|
|
136
|
+
percent_w_literal?(node) || percent_w_upper_literal?(node)
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
def heredoc_with_disabled_interpolation?(node)
|
|
@@ -3,9 +3,13 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Enforces consistency between
|
|
6
|
+
# Enforces consistency between `return nil` and `return`.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
8
|
+
# This cop is disabled by default. Because there seems to be a perceived semantic difference
|
|
9
|
+
# between `return` and `return nil`. The former can be seen as just halting evaluation,
|
|
10
|
+
# while the latter might be used when the return value is of specific concern.
|
|
11
|
+
#
|
|
12
|
+
# Supported styles are `return` and `return_nil`.
|
|
9
13
|
#
|
|
10
14
|
# @example EnforcedStyle: return (default)
|
|
11
15
|
# # bad
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
|
31
31
|
# do_something?
|
|
32
32
|
# end
|
|
33
33
|
#
|
|
34
|
-
# @example
|
|
34
|
+
# @example AllowedMethods: ['foo?']
|
|
35
35
|
# # good
|
|
36
36
|
# def foo?
|
|
37
37
|
# return if condition
|
|
@@ -39,7 +39,7 @@ module RuboCop
|
|
|
39
39
|
# do_something?
|
|
40
40
|
# end
|
|
41
41
|
#
|
|
42
|
-
# @example
|
|
42
|
+
# @example AllowedPatterns: [/foo/]
|
|
43
43
|
# # good
|
|
44
44
|
# def foo?
|
|
45
45
|
# return if condition
|
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
|
52
52
|
include AllowedMethods
|
|
53
53
|
include AllowedPattern
|
|
54
54
|
|
|
55
|
-
MSG = '
|
|
55
|
+
MSG = 'Return `false` instead of `nil` in predicate methods.'
|
|
56
56
|
|
|
57
57
|
# @!method return_nil?(node)
|
|
58
58
|
def_node_matcher :return_nil?, <<~PATTERN
|
|
@@ -65,16 +65,30 @@ module RuboCop
|
|
|
65
65
|
return unless (body = node.body)
|
|
66
66
|
|
|
67
67
|
body.each_descendant(:return) do |return_node|
|
|
68
|
-
|
|
68
|
+
register_offense(return_node, 'return false') if return_nil?(return_node)
|
|
69
|
+
end
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
return unless (nil_node = nil_node_at_the_end_of_method_body(body))
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
corrector.replace(return_node, 'return false')
|
|
74
|
-
end
|
|
75
|
-
end
|
|
73
|
+
register_offense(nil_node, 'false')
|
|
76
74
|
end
|
|
77
75
|
alias on_defs on_def
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def nil_node_at_the_end_of_method_body(body)
|
|
80
|
+
return body if body.nil_type?
|
|
81
|
+
return unless body.begin_type?
|
|
82
|
+
return unless (last_child = body.children.last)
|
|
83
|
+
|
|
84
|
+
last_child if last_child.is_a?(AST::Node) && last_child.nil_type?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def register_offense(offense_node, replacement)
|
|
88
|
+
add_offense(offense_node) do |corrector|
|
|
89
|
+
corrector.replace(offense_node, replacement)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
78
92
|
end
|
|
79
93
|
end
|
|
80
94
|
end
|
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
|
35
35
|
|
|
36
36
|
# @!method sample_candidate?(node)
|
|
37
37
|
def_node_matcher :sample_candidate?, <<~PATTERN
|
|
38
|
-
(
|
|
38
|
+
(call $(call _ :shuffle $...) ${:#{RESTRICT_ON_SEND.join(' :')}} $...)
|
|
39
39
|
PATTERN
|
|
40
40
|
|
|
41
41
|
def on_send(node)
|
|
@@ -52,6 +52,7 @@ module RuboCop
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
|
+
alias on_csend on_send
|
|
55
56
|
|
|
56
57
|
private
|
|
57
58
|
|
|
@@ -55,8 +55,8 @@ module RuboCop
|
|
|
55
55
|
# @!method regexp_match?(node)
|
|
56
56
|
def_node_matcher :regexp_match?, <<~PATTERN
|
|
57
57
|
{
|
|
58
|
-
(block
|
|
59
|
-
(numblock
|
|
58
|
+
(block call (args (arg $_)) ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
|
59
|
+
(numblock call $1 ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
|
60
60
|
}
|
|
61
61
|
PATTERN
|
|
62
62
|
|
|
@@ -64,9 +64,9 @@ module RuboCop
|
|
|
64
64
|
# @!method creates_hash?(node)
|
|
65
65
|
def_node_matcher :creates_hash?, <<~PATTERN
|
|
66
66
|
{
|
|
67
|
-
(
|
|
68
|
-
(block (
|
|
69
|
-
(
|
|
67
|
+
(call (const _ :Hash) {:new :[]} ...)
|
|
68
|
+
(block (call (const _ :Hash) :new ...) ...)
|
|
69
|
+
(call _ { :to_h :to_hash } ...)
|
|
70
70
|
}
|
|
71
71
|
PATTERN
|
|
72
72
|
|
|
@@ -100,6 +100,7 @@ module RuboCop
|
|
|
100
100
|
register_offense(node, block_node, regexp, replacement)
|
|
101
101
|
end
|
|
102
102
|
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
103
|
+
alias on_csend on_send
|
|
103
104
|
|
|
104
105
|
private
|
|
105
106
|
|
|
@@ -146,7 +147,7 @@ module RuboCop
|
|
|
146
147
|
return node.child_nodes.first if node.match_with_lvasgn_type?
|
|
147
148
|
|
|
148
149
|
if node.receiver.lvar_type? &&
|
|
149
|
-
(block.numblock_type? || node.receiver.source == block.
|
|
150
|
+
(block.numblock_type? || node.receiver.source == block.first_argument.source)
|
|
150
151
|
node.first_argument
|
|
151
152
|
elsif node.first_argument.lvar_type?
|
|
152
153
|
node.receiver
|
|
@@ -62,9 +62,6 @@ module RuboCop
|
|
|
62
62
|
private
|
|
63
63
|
|
|
64
64
|
def check_for_line_terminator_or_opener
|
|
65
|
-
# Make the obvious check first
|
|
66
|
-
return unless processed_source.raw_source.include?(';')
|
|
67
|
-
|
|
68
65
|
each_semicolon do |line, column, token_before_semicolon|
|
|
69
66
|
register_semicolon(line, column, false, token_before_semicolon)
|
|
70
67
|
end
|
|
@@ -83,6 +80,7 @@ module RuboCop
|
|
|
83
80
|
processed_source.tokens.group_by(&:line)
|
|
84
81
|
end
|
|
85
82
|
|
|
83
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
86
84
|
def semicolon_position(tokens)
|
|
87
85
|
if tokens.last.semicolon?
|
|
88
86
|
-1
|
|
@@ -93,10 +91,13 @@ module RuboCop
|
|
|
93
91
|
elsif exist_semicolon_after_left_curly_brace?(tokens) ||
|
|
94
92
|
exist_semicolon_after_left_string_interpolation_brace?(tokens)
|
|
95
93
|
2
|
|
94
|
+
elsif exist_semicolon_after_left_lambda_curly_brace?(tokens)
|
|
95
|
+
3
|
|
96
96
|
elsif exist_semicolon_before_right_string_interpolation_brace?(tokens)
|
|
97
97
|
-4
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
100
101
|
|
|
101
102
|
def exist_semicolon_before_right_curly_brace?(tokens)
|
|
102
103
|
tokens[-2]&.right_curly_brace? && tokens[-3]&.semicolon?
|
|
@@ -106,6 +107,10 @@ module RuboCop
|
|
|
106
107
|
tokens[1]&.left_curly_brace? && tokens[2]&.semicolon?
|
|
107
108
|
end
|
|
108
109
|
|
|
110
|
+
def exist_semicolon_after_left_lambda_curly_brace?(tokens)
|
|
111
|
+
tokens[2]&.type == :tLAMBEG && tokens[3]&.semicolon?
|
|
112
|
+
end
|
|
113
|
+
|
|
109
114
|
def exist_semicolon_before_right_string_interpolation_brace?(tokens)
|
|
110
115
|
tokens[-3]&.type == :tSTRING_DEND && tokens[-4]&.semicolon?
|
|
111
116
|
end
|
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
# Sometimes using dig method ends up with just a single
|
|
7
|
-
# argument. In such cases, dig should be replaced with []
|
|
6
|
+
# Sometimes using `dig` method ends up with just a single
|
|
7
|
+
# argument. In such cases, dig should be replaced with `[]`.
|
|
8
|
+
#
|
|
9
|
+
# Since replacing `hash&.dig(:key)` with `hash[:key]` could potentially lead to error,
|
|
10
|
+
# calls to the `dig` method using safe navigation will be ignored.
|
|
8
11
|
#
|
|
9
12
|
# @safety
|
|
10
13
|
# This cop is unsafe because it cannot be guaranteed that the receiver
|
|
@@ -33,6 +36,7 @@ module RuboCop
|
|
|
33
36
|
|
|
34
37
|
MSG = 'Use `%<receiver>s[%<argument>s]` instead of `%<original>s`.'
|
|
35
38
|
RESTRICT_ON_SEND = %i[dig].freeze
|
|
39
|
+
IGNORED_ARGUMENT_TYPES = %i[block_pass forwarded_restarg forwarded_args hash].freeze
|
|
36
40
|
|
|
37
41
|
# @!method single_argument_dig?(node)
|
|
38
42
|
def_node_matcher :single_argument_dig?, <<~PATTERN
|
|
@@ -44,7 +48,7 @@ module RuboCop
|
|
|
44
48
|
|
|
45
49
|
expression = single_argument_dig?(node)
|
|
46
50
|
return unless expression
|
|
47
|
-
return if expression.
|
|
51
|
+
return if IGNORED_ARGUMENT_TYPES.include?(expression.type)
|
|
48
52
|
|
|
49
53
|
receiver = node.receiver.source
|
|
50
54
|
argument = expression.source
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for single-line `do`...`end` block.
|
|
7
|
+
#
|
|
8
|
+
# In practice a single line `do`...`end` is autocorrected when `EnforcedStyle: semantic`
|
|
9
|
+
# in `Style/BlockDelimiters`. The autocorrection maintains the `do` ... `end` syntax to
|
|
10
|
+
# preserve semantics and does not change it to `{`...`}` block.
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
#
|
|
14
|
+
# # bad
|
|
15
|
+
# foo do |arg| bar(arg) end
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# foo do |arg|
|
|
19
|
+
# bar(arg)
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# # bad
|
|
23
|
+
# ->(arg) do bar(arg) end
|
|
24
|
+
#
|
|
25
|
+
# # good
|
|
26
|
+
# ->(arg) { bar(arg) }
|
|
27
|
+
#
|
|
28
|
+
class SingleLineDoEndBlock < Base
|
|
29
|
+
extend AutoCorrector
|
|
30
|
+
|
|
31
|
+
MSG = 'Prefer multiline `do`...`end` block.'
|
|
32
|
+
|
|
33
|
+
# rubocop:disable Metrics/AbcSize
|
|
34
|
+
def on_block(node)
|
|
35
|
+
return if !node.single_line? || node.braces?
|
|
36
|
+
|
|
37
|
+
add_offense(node) do |corrector|
|
|
38
|
+
corrector.insert_after(do_line(node), "\n")
|
|
39
|
+
|
|
40
|
+
node_body = node.body
|
|
41
|
+
|
|
42
|
+
if node_body.respond_to?(:heredoc?) && node_body.heredoc?
|
|
43
|
+
corrector.remove(node.loc.end)
|
|
44
|
+
corrector.insert_after(node_body.loc.heredoc_end, "\nend")
|
|
45
|
+
else
|
|
46
|
+
corrector.insert_before(node.loc.end, "\n")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
# rubocop:enable Metrics/AbcSize
|
|
51
|
+
alias on_numblock on_block
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def do_line(node)
|
|
56
|
+
if node.numblock_type? || node.arguments.children.empty? || node.send_node.lambda_literal?
|
|
57
|
+
node.loc.begin
|
|
58
|
+
else
|
|
59
|
+
node.arguments
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def x(corrector, node); end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|