rubocop 1.91.0 → 1.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +3 -1
- data/lib/rubocop/cached_data.rb +47 -7
- data/lib/rubocop/changed_files.rb +35 -13
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +2 -2
- data/lib/rubocop/cli/command/explain.rb +34 -0
- data/lib/rubocop/cli/command/show_cops.rb +6 -0
- data/lib/rubocop/cli/command/show_docs_url.rb +6 -4
- data/lib/rubocop/cli.rb +3 -2
- data/lib/rubocop/comment_config.rb +17 -8
- data/lib/rubocop/config_loader.rb +6 -3
- data/lib/rubocop/config_loader_resolver.rb +37 -12
- data/lib/rubocop/config_obsoletion/removed_cop.rb +1 -1
- data/lib/rubocop/config_validator.rb +11 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/base.rb +42 -21
- data/lib/rubocop/cop/bundler/gem_comment.rb +0 -1
- data/lib/rubocop/cop/bundler/ordered_gems.rb +0 -8
- data/lib/rubocop/cop/cop_documentation.rb +81 -0
- data/lib/rubocop/cop/cop_explanation.rb +140 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +13 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +23 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +45 -8
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +0 -6
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -5
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
- data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
- data/lib/rubocop/cop/layout/block_alignment.rb +27 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/class_structure.rb +9 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +16 -10
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -3
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +16 -12
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -0
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +8 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/line_length.rb +52 -18
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +12 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +8 -1
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +7 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +14 -0
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
- data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +6 -11
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +2 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +15 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +63 -19
- data/lib/rubocop/cop/lint/loop.rb +24 -2
- data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +71 -11
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +18 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +14 -7
- data/lib/rubocop/cop/lint/void.rb +8 -1
- data/lib/rubocop/cop/metrics/class_length.rb +4 -2
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
- data/lib/rubocop/cop/metrics/module_length.rb +4 -2
- data/lib/rubocop/cop/mixin/alignment.rb +4 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +17 -14
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -1
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +26 -2
- data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +17 -2
- data/lib/rubocop/cop/mixin/project_index_help.rb +15 -0
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +13 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +22 -2
- data/lib/rubocop/cop/mixin.rb +2 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_prefix.rb +7 -22
- data/lib/rubocop/cop/offense.rb +59 -3
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/security/json_load.rb +16 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +7 -0
- data/lib/rubocop/cop/style/alias.rb +18 -5
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
- data/lib/rubocop/cop/style/and_or.rb +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +4 -1
- data/lib/rubocop/cop/style/attr.rb +3 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +6 -4
- data/lib/rubocop/cop/style/block_delimiters.rb +29 -3
- data/lib/rubocop/cop/style/case_like_if.rb +6 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +54 -16
- data/lib/rubocop/cop/style/class_methods_definitions.rb +8 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +85 -11
- data/lib/rubocop/cop/style/concat_array_literals.rb +46 -7
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +65 -9
- data/lib/rubocop/cop/style/double_negation.rb +11 -0
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +3 -1
- data/lib/rubocop/cop/style/endless_method.rb +67 -6
- data/lib/rubocop/cop/style/exact_regexp_match.rb +45 -8
- data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
- data/lib/rubocop/cop/style/float_division.rb +22 -2
- data/lib/rubocop/cop/style/for.rb +40 -2
- data/lib/rubocop/cop/style/format_string.rb +28 -6
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +9 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +32 -9
- data/lib/rubocop/cop/style/hash_syntax.rb +16 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +21 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +19 -20
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +47 -4
- data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
- data/lib/rubocop/cop/style/it_block_parameter.rb +32 -3
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
- data/lib/rubocop/cop/style/lambda.rb +18 -0
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/map_into_array.rb +1 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +45 -10
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
- data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -3
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -5
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
- data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
- data/lib/rubocop/cop/style/mutable_constant.rb +28 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +2 -1
- data/lib/rubocop/cop/style/negative_array_index.rb +9 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +27 -8
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
- data/lib/rubocop/cop/style/next.rb +24 -10
- data/lib/rubocop/cop/style/nil_comparison.rb +16 -4
- data/lib/rubocop/cop/style/non_nil_check.rb +1 -1
- data/lib/rubocop/cop/style/not.rb +10 -5
- data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +13 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +20 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +30 -13
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -0
- data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +12 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +20 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +4 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
- data/lib/rubocop/cop/style/require_order.rb +9 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +5 -9
- data/lib/rubocop/cop/style/return_nil.rb +17 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
- data/lib/rubocop/cop/style/sample.rb +9 -8
- data/lib/rubocop/cop/style/self_assignment.rb +12 -15
- data/lib/rubocop/cop/style/semicolon.rb +16 -5
- data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +9 -3
- data/lib/rubocop/cop/style/super_arguments.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +23 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +23 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -19
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -9
- data/lib/rubocop/cop/style/yoda_expression.rb +10 -1
- data/lib/rubocop/cop/team.rb +10 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -1
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/formatter_set.rb +4 -0
- data/lib/rubocop/formatter/json_formatter.rb +71 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +3 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
- data/lib/rubocop/formatter/sarif_formatter.rb +12 -7
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
- data/lib/rubocop/lsp/runtime.rb +47 -11
- data/lib/rubocop/lsp/stdin_runner.rb +11 -5
- data/lib/rubocop/lsp.rb +5 -2
- data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
- data/lib/rubocop/mcp/explain_tool.rb +68 -0
- data/lib/rubocop/mcp/scope.rb +65 -0
- data/lib/rubocop/mcp/server.rb +184 -76
- data/lib/rubocop/mcp/source_files.rb +35 -0
- data/lib/rubocop/offense_limit.rb +30 -0
- data/lib/rubocop/options.rb +45 -10
- data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
- data/lib/rubocop/remote_config.rb +4 -1
- data/lib/rubocop/result_cache.rb +20 -13
- data/lib/rubocop/runner.rb +109 -41
- data/lib/rubocop/server/cache.rb +2 -2
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +16 -5
|
@@ -21,6 +21,10 @@ module RuboCop
|
|
|
21
21
|
MSG_NEWLINE = 'Do not use `%<keyword>s %<expr>s;` - use a newline instead.'
|
|
22
22
|
MSG_TERNARY = 'Do not use `%<keyword>s %<expr>s;` - use a ternary operator instead.'
|
|
23
23
|
|
|
24
|
+
LOWER_PRECEDENCE_THAN_TERNARY_TYPES = %i[
|
|
25
|
+
and or if rescue any_match_pattern while until while_post until_post
|
|
26
|
+
].freeze
|
|
27
|
+
|
|
24
28
|
def on_normal_if_unless(node)
|
|
25
29
|
return if node.parent&.if_type?
|
|
26
30
|
return if part_of_ignored_node?(node)
|
|
@@ -77,12 +81,14 @@ module RuboCop
|
|
|
77
81
|
def replacement(node)
|
|
78
82
|
return correct_elsif(node) if node.else_branch&.if_type?
|
|
79
83
|
|
|
80
|
-
then_code = node.if_branch ?
|
|
81
|
-
else_code = node.else_branch ?
|
|
84
|
+
then_code = node.if_branch ? ternary_operand(node.if_branch) : 'nil'
|
|
85
|
+
else_code = node.else_branch ? ternary_operand(node.else_branch) : 'nil'
|
|
82
86
|
|
|
83
87
|
then_code, else_code = else_code, then_code if node.unless?
|
|
84
88
|
|
|
85
|
-
"#{ternary_condition(node)} ? #{then_code} : #{else_code}"
|
|
89
|
+
ternary = "#{ternary_condition(node)} ? #{then_code} : #{else_code}"
|
|
90
|
+
|
|
91
|
+
operand_of_parent?(node) ? "(#{ternary})" : ternary
|
|
86
92
|
end
|
|
87
93
|
|
|
88
94
|
def correct_elsif(node)
|
|
@@ -108,7 +114,34 @@ module RuboCop
|
|
|
108
114
|
# `(a = b) ? c : d`), changing what gets assigned.
|
|
109
115
|
def ternary_condition(node)
|
|
110
116
|
condition = node.condition
|
|
111
|
-
condition.assignment? ? "(#{condition.source})" : condition
|
|
117
|
+
condition.assignment? ? "(#{condition.source})" : ternary_operand(condition)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def ternary_operand(expr)
|
|
121
|
+
lower_precedence_than_ternary?(expr) ? "(#{expr.source})" : build_expression(expr)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Expressions that bind looser than `?:` (or cannot appear unparenthesized
|
|
125
|
+
# inside it) would otherwise absorb or break the ternary.
|
|
126
|
+
def lower_precedence_than_ternary?(node)
|
|
127
|
+
return true if node.type?(*LOWER_PRECEDENCE_THAN_TERNARY_TYPES)
|
|
128
|
+
return true if node.send_type? && (node.prefix_not? || prefix_bang_on_command?(node))
|
|
129
|
+
|
|
130
|
+
node.type?(:yield, :super, :defined?) && node.arguments.any? && !node.parenthesized?
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def operand_of_parent?(node)
|
|
134
|
+
return false unless (parent = node.parent)
|
|
135
|
+
return true if parent.operator_keyword?
|
|
136
|
+
|
|
137
|
+
parent.call_type? && call_operand?(parent, node)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def call_operand?(call, node)
|
|
141
|
+
return false if call.prefix_not?
|
|
142
|
+
return true if call.receiver.equal?(node)
|
|
143
|
+
|
|
144
|
+
call.operator_method? && !call.method?(:[]) && !call.method?(:[]=)
|
|
112
145
|
end
|
|
113
146
|
|
|
114
147
|
def build_else_branch(second_condition)
|
|
@@ -131,6 +164,16 @@ module RuboCop
|
|
|
131
164
|
result
|
|
132
165
|
end
|
|
133
166
|
|
|
167
|
+
# `!foo a` leaves the arguments of `foo` unparenthesized at the end of the operand,
|
|
168
|
+
# where they would absorb the rest of the ternary.
|
|
169
|
+
def prefix_bang_on_command?(node)
|
|
170
|
+
return false unless node.prefix_bang?
|
|
171
|
+
|
|
172
|
+
receiver = node.receiver
|
|
173
|
+
|
|
174
|
+
require_argument_parentheses?(receiver) || lower_precedence_than_ternary?(receiver)
|
|
175
|
+
end
|
|
176
|
+
|
|
134
177
|
def require_argument_parentheses?(node)
|
|
135
178
|
return false if !node.call_type? || node.arithmetic_operation?
|
|
136
179
|
|
|
@@ -114,9 +114,31 @@ module RuboCop
|
|
|
114
114
|
method_call, _lhs, method, _rhs = inverse_candidate?(node)
|
|
115
115
|
return unless method_call && method
|
|
116
116
|
|
|
117
|
-
corrector
|
|
117
|
+
remove_negation(corrector, node, method, method_call)
|
|
118
118
|
corrector.replace(method_call.loc.selector, inverse_methods[method].to_s)
|
|
119
|
-
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def remove_negation(corrector, node, method, method_call)
|
|
122
|
+
if !keep_parentheses?(node, method_call)
|
|
123
|
+
corrector.remove(not_to_receiver(node, method_call))
|
|
124
|
+
remove_end_parenthesis(corrector, node, method, method_call)
|
|
125
|
+
elsif node.parenthesized?
|
|
126
|
+
corrector.remove(node.loc.selector)
|
|
127
|
+
else
|
|
128
|
+
corrector.remove(node.loc.selector.join(node.receiver.source_range.begin))
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def keep_parentheses?(node, method_call)
|
|
133
|
+
return false unless node.receiver.begin_type? || node.parenthesized?
|
|
134
|
+
return false unless method_call.operator_method?
|
|
135
|
+
return false unless (parent = node.parent)&.call_type?
|
|
136
|
+
|
|
137
|
+
binary_operator?(parent) || parent.receiver.equal?(node)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def binary_operator?(node)
|
|
141
|
+
node.operator_method? && !node.loc.dot && !node.method?(:[]) && !node.method?(:[]=)
|
|
120
142
|
end
|
|
121
143
|
|
|
122
144
|
def correct_inverse_block(corrector, node)
|
|
@@ -61,6 +61,12 @@ module RuboCop
|
|
|
61
61
|
|
|
62
62
|
minimum_target_ruby_version 3.4
|
|
63
63
|
|
|
64
|
+
# `Style/StabbyLambdaParentheses` wraps the parameter this cop removes in the same pass,
|
|
65
|
+
# which would leave an empty parameter list that forbids `it`.
|
|
66
|
+
def self.autocorrect_incompatible_with
|
|
67
|
+
[Style::Lambda, Style::StabbyLambdaParentheses]
|
|
68
|
+
end
|
|
69
|
+
|
|
64
70
|
def on_block(node)
|
|
65
71
|
return unless style == :always
|
|
66
72
|
return unless node.arguments.one?
|
|
@@ -68,9 +74,10 @@ module RuboCop
|
|
|
68
74
|
# `restarg`, `kwrestarg`, `blockarg` nodes can return early.
|
|
69
75
|
return unless node.first_argument.arg_type?
|
|
70
76
|
|
|
71
|
-
|
|
77
|
+
block_argument_name = node.first_argument.source
|
|
78
|
+
return if used_within_inner_block?(node.body, block_argument_name)
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
find_block_variables(node, block_argument_name).each do |variable|
|
|
74
81
|
add_offense(variable, message: MSG_USE_IT_PARAMETER) do |corrector|
|
|
75
82
|
corrector.remove(node.arguments)
|
|
76
83
|
corrector.replace(variable, 'it')
|
|
@@ -111,7 +118,29 @@ module RuboCop
|
|
|
111
118
|
def find_block_variables(node, block_argument_name)
|
|
112
119
|
return [] unless node.body
|
|
113
120
|
|
|
114
|
-
node.body
|
|
121
|
+
ranges = inner_block_ranges(node.body)
|
|
122
|
+
|
|
123
|
+
block_variables(node.body, block_argument_name).reject do |variable|
|
|
124
|
+
ranges.any? { |range| range.contains?(variable.source_range) }
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def inner_block_ranges(body)
|
|
129
|
+
body.each_node(:any_block).map { |block| block.loc.begin.join(block.loc.end) }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def used_within_inner_block?(body, block_argument_name)
|
|
133
|
+
return false unless body
|
|
134
|
+
|
|
135
|
+
ranges = inner_block_ranges(body)
|
|
136
|
+
|
|
137
|
+
block_variables(body, block_argument_name).any? do |variable|
|
|
138
|
+
ranges.any? { |range| range.contains?(variable.source_range) }
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def block_variables(body, block_argument_name)
|
|
143
|
+
body.each_descendant(:lvar).select do |descendant|
|
|
115
144
|
descendant.source == block_argument_name
|
|
116
145
|
end
|
|
117
146
|
end
|
|
@@ -75,7 +75,9 @@ module RuboCop
|
|
|
75
75
|
|
|
76
76
|
def remove_kwargs(kwarg_nodes, corrector)
|
|
77
77
|
kwarg_nodes.each do |kwarg|
|
|
78
|
-
|
|
78
|
+
range = range_with_surrounding_space(kwarg.source_range, side: :left, whitespace: true)
|
|
79
|
+
with_space = range_with_surrounding_space(range, side: :right)
|
|
80
|
+
|
|
79
81
|
corrector.remove(range_with_surrounding_comma(with_space, :left))
|
|
80
82
|
end
|
|
81
83
|
end
|
|
@@ -48,6 +48,8 @@ module RuboCop
|
|
|
48
48
|
# end
|
|
49
49
|
class Lambda < Base
|
|
50
50
|
include ConfigurableEnforcedStyle
|
|
51
|
+
include PatternMatchingHelp
|
|
52
|
+
include RescueNode
|
|
51
53
|
extend AutoCorrector
|
|
52
54
|
|
|
53
55
|
LITERAL_MESSAGE = 'Use the `-> { ... }` lambda literal syntax for %<modifier>s lambdas.'
|
|
@@ -71,6 +73,7 @@ module RuboCop
|
|
|
71
73
|
selector = node.send_node.source
|
|
72
74
|
|
|
73
75
|
return unless offending_selector?(node, selector)
|
|
76
|
+
return if uncorrectable_lambda_literal?(node)
|
|
74
77
|
|
|
75
78
|
add_offense(node.send_node, message: message(node, selector)) do |corrector|
|
|
76
79
|
if node.send_node.lambda_literal?
|
|
@@ -91,6 +94,21 @@ module RuboCop
|
|
|
91
94
|
selector == OFFENDING_SELECTORS[:style][style][lines]
|
|
92
95
|
end
|
|
93
96
|
|
|
97
|
+
def uncorrectable_lambda_literal?(node)
|
|
98
|
+
return false unless node.send_node.lambda_literal?
|
|
99
|
+
return true if in_pattern?(node)
|
|
100
|
+
return false unless rescue_or_ensure_clause?(node.body)
|
|
101
|
+
|
|
102
|
+
LambdaLiteralToMethodCorrector.new(node).replace_delimiters?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def rescue_or_ensure_clause?(body)
|
|
106
|
+
return false unless body
|
|
107
|
+
return true if body.ensure_type?
|
|
108
|
+
|
|
109
|
+
body.rescue_type? && !rescue_modifier?(body.resbody_branches.first)
|
|
110
|
+
end
|
|
111
|
+
|
|
94
112
|
def message(node, selector)
|
|
95
113
|
message = selector == '->' ? METHOD_MESSAGE : LITERAL_MESSAGE
|
|
96
114
|
|
|
@@ -28,8 +28,9 @@ module RuboCop
|
|
|
28
28
|
def on_send(node)
|
|
29
29
|
return unless node.receiver
|
|
30
30
|
# Rewriting the call rebuilds it as a single expression, which would drop
|
|
31
|
-
# any comments inside the argument list, so leave it to be
|
|
32
|
-
|
|
31
|
+
# any comments or heredoc bodies inside the argument list, so leave it to be
|
|
32
|
+
# fixed manually.
|
|
33
|
+
return if comments_in_node?(node) || heredoc_argument?(node)
|
|
33
34
|
|
|
34
35
|
if offense?(node)
|
|
35
36
|
prefer = prefer(node)
|
|
@@ -59,6 +60,10 @@ module RuboCop
|
|
|
59
60
|
end
|
|
60
61
|
end
|
|
61
62
|
|
|
63
|
+
def heredoc_argument?(node)
|
|
64
|
+
node.arguments.any? { |argument| argument.each_node(:any_str).any?(&:heredoc?) }
|
|
65
|
+
end
|
|
66
|
+
|
|
62
67
|
def offense?(node)
|
|
63
68
|
(explicit_style? && node.implicit_call?) || (implicit_style? && !node.implicit_call?)
|
|
64
69
|
end
|
|
@@ -112,8 +112,7 @@ module RuboCop
|
|
|
112
112
|
|
|
113
113
|
def on_block(node)
|
|
114
114
|
return unless each_block_with_push?(node)
|
|
115
|
-
|
|
116
|
-
dest_var = find_dest_var(node)
|
|
115
|
+
return unless (dest_var = find_dest_var(node))
|
|
117
116
|
|
|
118
117
|
if offending_empty_array_tap?(node, dest_var)
|
|
119
118
|
asgn = dest_var.declaration_node
|
|
@@ -40,6 +40,8 @@ module RuboCop
|
|
|
40
40
|
return if legitimate_call_with_parentheses?(node)
|
|
41
41
|
return if allowed_camel_case_method_call?(node)
|
|
42
42
|
return if allowed_string_interpolation_method_call?(node)
|
|
43
|
+
return if code_after_closing_parenthesis_on_its_own_line?(node)
|
|
44
|
+
return if comment_before_first_argument?(node)
|
|
43
45
|
|
|
44
46
|
(@pending_omit_offenses ||= []) << node
|
|
45
47
|
end
|
|
@@ -104,11 +106,30 @@ module RuboCop
|
|
|
104
106
|
inside_string_interpolation?(node)
|
|
105
107
|
end
|
|
106
108
|
|
|
109
|
+
def code_after_closing_parenthesis_on_its_own_line?(node)
|
|
110
|
+
closing = node.loc.end
|
|
111
|
+
return false if node.arguments.none? || node.last_argument.last_line == closing.line
|
|
112
|
+
|
|
113
|
+
rest = closing.source_line[(closing.column + 1)..].strip
|
|
114
|
+
|
|
115
|
+
!rest.empty? && !rest.start_with?('#')
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Without the parentheses, a comment before the first argument would end the call there,
|
|
119
|
+
# and a line continuation can't carry the call past a comment.
|
|
120
|
+
def comment_before_first_argument?(node)
|
|
121
|
+
return false unless (first_argument = node.first_argument)
|
|
122
|
+
|
|
123
|
+
lines = node.loc.begin.line...first_argument.first_line
|
|
124
|
+
processed_source.each_comment_in_lines(lines).any?
|
|
125
|
+
end
|
|
126
|
+
|
|
107
127
|
def parentheses_at_the_end_of_multiline_call?(node)
|
|
108
|
-
node.multiline?
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
128
|
+
return false unless node.multiline?
|
|
129
|
+
|
|
130
|
+
opening = node.loc.begin
|
|
131
|
+
|
|
132
|
+
opening.source_line[(opening.column + 1)..].gsub(TRAILING_WHITESPACE_REGEX, '').empty?
|
|
112
133
|
end
|
|
113
134
|
|
|
114
135
|
def legitimate_call_with_parentheses?(node) # rubocop:disable Metrics/PerceivedComplexity
|
|
@@ -137,9 +158,13 @@ module RuboCop
|
|
|
137
158
|
parent = node.parent&.any_block_type? ? node.parent.parent : node.parent
|
|
138
159
|
return false unless parent
|
|
139
160
|
|
|
140
|
-
logical_operator?(parent) ||
|
|
141
|
-
|
|
142
|
-
|
|
161
|
+
if logical_operator?(parent) || command_assignment_before_keyword_operator?(parent)
|
|
162
|
+
return true
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
parent.send_type? && parent.arguments.any? do |argument|
|
|
166
|
+
logical_operator?(argument)
|
|
167
|
+
end
|
|
143
168
|
end
|
|
144
169
|
|
|
145
170
|
def call_in_optional_arguments?(node)
|
|
@@ -229,6 +254,15 @@ module RuboCop
|
|
|
229
254
|
node.operator_keyword? && node.logical_operator?
|
|
230
255
|
end
|
|
231
256
|
|
|
257
|
+
def command_assignment_before_keyword_operator?(node)
|
|
258
|
+
return false unless node.assignment?
|
|
259
|
+
|
|
260
|
+
node = node.parent while node.parent&.assignment?
|
|
261
|
+
return false unless (operator = node.parent)
|
|
262
|
+
|
|
263
|
+
operator.operator_keyword? && operator.semantic_operator?
|
|
264
|
+
end
|
|
265
|
+
|
|
232
266
|
def hash_literal?(node)
|
|
233
267
|
node.hash_type? && node.braces?
|
|
234
268
|
end
|
|
@@ -262,10 +296,11 @@ module RuboCop
|
|
|
262
296
|
end
|
|
263
297
|
|
|
264
298
|
def forwards_anonymous_rest_arguments?(node)
|
|
265
|
-
|
|
266
|
-
|
|
299
|
+
node.arguments.any? do |argument|
|
|
300
|
+
next true if argument.forwarded_restarg_type?
|
|
267
301
|
|
|
268
|
-
|
|
302
|
+
argument.hash_type? && argument.children.any?(&:forwarded_kwrestarg_type?)
|
|
303
|
+
end
|
|
269
304
|
end
|
|
270
305
|
end
|
|
271
306
|
end
|
|
@@ -242,7 +242,13 @@ module RuboCop
|
|
|
242
242
|
extend AutoCorrector
|
|
243
243
|
|
|
244
244
|
def self.autocorrect_incompatible_with
|
|
245
|
-
[
|
|
245
|
+
[
|
|
246
|
+
Style::NestedParenthesizedCalls,
|
|
247
|
+
Style::RedundantParentheses,
|
|
248
|
+
Style::RescueModifier,
|
|
249
|
+
Style::TernaryParentheses,
|
|
250
|
+
Style::TrailingCommaInArguments
|
|
251
|
+
]
|
|
246
252
|
end
|
|
247
253
|
|
|
248
254
|
def on_send(node)
|
|
@@ -269,7 +275,24 @@ module RuboCop
|
|
|
269
275
|
return false unless node.arguments.one?
|
|
270
276
|
|
|
271
277
|
first_node = node.first_argument
|
|
272
|
-
first_node.begin_type? && first_node.parenthesized_call?
|
|
278
|
+
return false unless first_node.begin_type? && first_node.parenthesized_call?
|
|
279
|
+
|
|
280
|
+
first_node.children.one? && mergeable_parentheses?(first_node.children.first)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def mergeable_parentheses?(node)
|
|
284
|
+
case node.type
|
|
285
|
+
when :and, :or
|
|
286
|
+
!node.semantic_operator?
|
|
287
|
+
when :if, :while, :until
|
|
288
|
+
!node.modifier_form?
|
|
289
|
+
when :send
|
|
290
|
+
!node.keyword?
|
|
291
|
+
when :rescue, :masgn, :match_pattern, :match_pattern_p
|
|
292
|
+
false
|
|
293
|
+
else
|
|
294
|
+
true
|
|
295
|
+
end
|
|
273
296
|
end
|
|
274
297
|
end
|
|
275
298
|
end
|
|
@@ -29,10 +29,16 @@ module RuboCop
|
|
|
29
29
|
class MethodCallWithoutArgsParentheses < Base
|
|
30
30
|
include AllowedMethods
|
|
31
31
|
include AllowedPattern
|
|
32
|
+
include ReparsedEquivalence
|
|
32
33
|
extend AutoCorrector
|
|
33
34
|
|
|
34
35
|
MSG = 'Do not use parentheses for method calls with no arguments.'
|
|
35
36
|
|
|
37
|
+
def on_new_investigation
|
|
38
|
+
@pending_ranges = []
|
|
39
|
+
super
|
|
40
|
+
end
|
|
41
|
+
|
|
36
42
|
# rubocop:disable-next Metrics/CyclomaticComplexity
|
|
37
43
|
def on_send(node)
|
|
38
44
|
return unless !node.arguments? && node.parenthesized?
|
|
@@ -46,15 +52,32 @@ module RuboCop
|
|
|
46
52
|
end
|
|
47
53
|
alias on_csend on_send
|
|
48
54
|
|
|
55
|
+
# The parentheses are significant when removing them changes how the
|
|
56
|
+
# code parses, e.g. when a local variable with the same name is in
|
|
57
|
+
# scope (`foo = 1; foo()`) or an operator follows (`foo() -1`). The
|
|
58
|
+
# candidates are verified together, since outside a method definition
|
|
59
|
+
# each one would otherwise reparse the whole file.
|
|
60
|
+
def on_investigation_end
|
|
61
|
+
verified_by_reparse(@pending_ranges).each do |range|
|
|
62
|
+
add_offense(range) do |corrector|
|
|
63
|
+
apply_reparse_correction(corrector, range)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
super
|
|
68
|
+
end
|
|
69
|
+
|
|
49
70
|
private
|
|
50
71
|
|
|
51
72
|
def register_offense(node)
|
|
52
73
|
range = offense_range(node)
|
|
53
74
|
return if processed_source.contains_comment?(range)
|
|
54
75
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
76
|
+
@pending_ranges << range
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def apply_reparse_correction(corrector, range)
|
|
80
|
+
corrector.remove(range)
|
|
58
81
|
end
|
|
59
82
|
|
|
60
83
|
def ineligible_node?(node)
|
|
@@ -127,7 +127,19 @@ module RuboCop
|
|
|
127
127
|
|
|
128
128
|
def correct_arguments(arg_node, corrector)
|
|
129
129
|
corrector.replace(arg_node.loc.begin, ' ')
|
|
130
|
-
|
|
130
|
+
|
|
131
|
+
if code_after_arguments?(arg_node)
|
|
132
|
+
corrector.replace(arg_node.loc.end, ';')
|
|
133
|
+
else
|
|
134
|
+
corrector.remove(arg_node.loc.end)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def code_after_arguments?(arg_node)
|
|
139
|
+
closing = arg_node.loc.end
|
|
140
|
+
rest = closing.source_line[(closing.column + 1)..].strip
|
|
141
|
+
|
|
142
|
+
!rest.empty? && !rest.start_with?(';', '#')
|
|
131
143
|
end
|
|
132
144
|
|
|
133
145
|
def forced_parentheses?(node)
|
|
@@ -137,8 +149,11 @@ module RuboCop
|
|
|
137
149
|
# 3. Argument lists containing an anonymous rest arguments forwarding (`*`)
|
|
138
150
|
# 4. Argument lists containing an anonymous keyword rest arguments forwarding (`**`)
|
|
139
151
|
# 5. Argument lists containing an anonymous block forwarding (`&`)
|
|
140
|
-
#
|
|
141
|
-
|
|
152
|
+
# 6. Argument lists that begin on a line below the method name
|
|
153
|
+
# 7. Argument lists that begin with a destructuring parameter (`(a, b)`)
|
|
154
|
+
# Removing the parens would be a syntax error, or a change of the parameters, here.
|
|
155
|
+
node.endless? || anonymous_arguments?(node) || arguments_on_own_line?(node) ||
|
|
156
|
+
destructuring_first_argument?(node)
|
|
142
157
|
end
|
|
143
158
|
|
|
144
159
|
def require_parentheses?(args)
|
|
@@ -176,6 +191,17 @@ module RuboCop
|
|
|
176
191
|
|
|
177
192
|
last_argument.blockarg_type? && last_argument.name.nil?
|
|
178
193
|
end
|
|
194
|
+
|
|
195
|
+
def arguments_on_own_line?(node)
|
|
196
|
+
return false unless (first_argument = node.first_argument)
|
|
197
|
+
return false unless parentheses?(node.arguments)
|
|
198
|
+
|
|
199
|
+
node.arguments.loc.begin.line != first_argument.first_line
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def destructuring_first_argument?(node)
|
|
203
|
+
node.first_argument&.mlhs_type?
|
|
204
|
+
end
|
|
179
205
|
end
|
|
180
206
|
end
|
|
181
207
|
end
|
|
@@ -125,13 +125,19 @@ module RuboCop
|
|
|
125
125
|
private
|
|
126
126
|
|
|
127
127
|
def check(node)
|
|
128
|
-
return if node.else?
|
|
128
|
+
return if node.else? || guard_clause_cop_conflict?(node)
|
|
129
129
|
|
|
130
130
|
add_offense(node, message: format(message_template, type: node.type)) do |corrector|
|
|
131
131
|
autocorrect(corrector, node)
|
|
132
132
|
end
|
|
133
133
|
end
|
|
134
134
|
|
|
135
|
+
def guard_clause_cop_conflict?(node)
|
|
136
|
+
return false unless node.if_type? && @config.cop_enabled?('Style/GuardClause')
|
|
137
|
+
|
|
138
|
+
[node.if_branch, node.else_branch].compact.any?(&:guard_clause?)
|
|
139
|
+
end
|
|
140
|
+
|
|
135
141
|
def message_template
|
|
136
142
|
case empty_else_style
|
|
137
143
|
when :empty
|
|
@@ -17,6 +17,7 @@ module RuboCop
|
|
|
17
17
|
class MultilineIfModifier < Base
|
|
18
18
|
include StatementModifier
|
|
19
19
|
include Alignment
|
|
20
|
+
include RangeHelp
|
|
20
21
|
extend AutoCorrector
|
|
21
22
|
|
|
22
23
|
MSG = 'Favor a normal %<keyword>s-statement over a modifier ' \
|
|
@@ -27,31 +28,70 @@ module RuboCop
|
|
|
27
28
|
return unless node.modifier_form? && node.body.multiline?
|
|
28
29
|
|
|
29
30
|
add_offense(node, message: format(MSG, keyword: node.keyword)) do |corrector|
|
|
30
|
-
corrector
|
|
31
|
+
autocorrect(corrector, node)
|
|
31
32
|
end
|
|
32
33
|
ignore_node(node)
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
private
|
|
36
37
|
|
|
37
|
-
def
|
|
38
|
+
def autocorrect(corrector, node)
|
|
39
|
+
condition_heredoc, body_heredoc = [node.condition, node.body].map do |part|
|
|
40
|
+
next unless (range = heredoc_after(part, node))
|
|
41
|
+
|
|
42
|
+
corrector.remove(range)
|
|
43
|
+
range.source.chomp
|
|
44
|
+
end
|
|
45
|
+
corrector.replace(node, to_normal_if(node, condition_heredoc, body_heredoc))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Heredocs opened on the modifier line have their bodies after it, so
|
|
49
|
+
# they are moved along with the part of the `if` they belong to.
|
|
50
|
+
def heredoc_after(part, node)
|
|
51
|
+
ranges = part.each_node(:any_str).select(&:heredoc?).map do |heredoc|
|
|
52
|
+
heredoc.loc.heredoc_body.join(heredoc.loc.heredoc_end)
|
|
53
|
+
end
|
|
54
|
+
ranges.select! { |range| range.line > node.last_line }
|
|
55
|
+
return if ranges.empty?
|
|
56
|
+
|
|
57
|
+
range_by_whole_lines(ranges.reduce(:join), include_final_newline: true)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def to_normal_if(node, condition_heredoc, body_heredoc)
|
|
38
61
|
indented_body = indented_body(node.body, node)
|
|
39
62
|
condition = "#{node.keyword} #{node.condition.source}"
|
|
40
63
|
indented_end = "#{offset(node)}end"
|
|
41
64
|
|
|
42
|
-
[condition, indented_body, indented_end]
|
|
65
|
+
lines = [condition, condition_heredoc, indented_body, body_heredoc, indented_end]
|
|
66
|
+
lines.compact.join("\n")
|
|
43
67
|
end
|
|
44
68
|
|
|
45
69
|
def indented_body(body, node)
|
|
46
70
|
body_source = "#{offset(node)}#{body.source}"
|
|
47
|
-
|
|
48
|
-
|
|
71
|
+
verbatim_lines = verbatim_lines_in(body)
|
|
72
|
+
body_source.each_line.with_index(body.first_line).map do |line, line_number|
|
|
73
|
+
if line == "\n" || verbatim_lines.include?(line_number)
|
|
49
74
|
line
|
|
50
75
|
else
|
|
51
76
|
line.sub(/^\s{#{offset(node).length}}/, indentation(node))
|
|
52
77
|
end
|
|
53
78
|
end.join
|
|
54
79
|
end
|
|
80
|
+
|
|
81
|
+
def verbatim_lines_in(body)
|
|
82
|
+
body.each_node(:any_str).filter_map { |str| verbatim_line_range(str) }.flat_map(&:to_a)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# The indentation of a line that starts inside a string is part of the
|
|
86
|
+
# string. Only squiggly heredocs strip it from their bodies, and a `<<`
|
|
87
|
+
# terminator has to stay at the start of its line.
|
|
88
|
+
def verbatim_line_range(str)
|
|
89
|
+
if str.heredoc?
|
|
90
|
+
str.loc.heredoc_body.line..str.loc.heredoc_end.line unless str.source.start_with?('<<~')
|
|
91
|
+
elsif str.loc?(:begin) && str.loc?(:end)
|
|
92
|
+
(str.first_line + 1)..str.last_line
|
|
93
|
+
end
|
|
94
|
+
end
|
|
55
95
|
end
|
|
56
96
|
end
|
|
57
97
|
end
|
|
@@ -50,10 +50,17 @@ module RuboCop
|
|
|
50
50
|
# Requires `then` for write `in` and its body on the same line.
|
|
51
51
|
def require_then?(in_pattern_node)
|
|
52
52
|
return true unless in_pattern_node.pattern.single_line?
|
|
53
|
+
return true if ends_with_endless_range?(in_pattern_node.pattern)
|
|
53
54
|
return false unless in_pattern_node.body
|
|
54
55
|
|
|
55
56
|
same_line?(in_pattern_node, in_pattern_node.body)
|
|
56
57
|
end
|
|
58
|
+
|
|
59
|
+
def ends_with_endless_range?(node)
|
|
60
|
+
node.each_node(:range).any? do |range|
|
|
61
|
+
range.end.nil? && range.source_range.end_pos == node.source_range.end_pos
|
|
62
|
+
end
|
|
63
|
+
end
|
|
57
64
|
end
|
|
58
65
|
end
|
|
59
66
|
end
|
|
@@ -27,6 +27,7 @@ module RuboCop
|
|
|
27
27
|
def on_def(node)
|
|
28
28
|
return unless node.arguments?
|
|
29
29
|
return if opening_line(node) == closing_line(node)
|
|
30
|
+
return if node.arguments.any?(&:multiline?)
|
|
30
31
|
return if correction_exceeds_max_line_length?(node)
|
|
31
32
|
return unless (begin_of_arguments = node.arguments.loc.begin)
|
|
32
33
|
|
|
@@ -78,11 +79,7 @@ module RuboCop
|
|
|
78
79
|
def correction_exceeds_max_line_length?(node)
|
|
79
80
|
return false unless max_line_length
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def indentation_width(node)
|
|
85
|
-
processed_source.line_indentation(node.source_range.line)
|
|
82
|
+
node.source_range.column + definition_width(node) > max_line_length
|
|
86
83
|
end
|
|
87
84
|
|
|
88
85
|
def definition_width(node)
|
|
@@ -7,7 +7,8 @@ module RuboCop
|
|
|
7
7
|
#
|
|
8
8
|
# NOTE: `return if ... else ... end` is syntax error. If `return` is used before
|
|
9
9
|
# multiline ternary operator expression, it will be autocorrected to single-line
|
|
10
|
-
# ternary operator. The same is true for `break`, `next`,
|
|
10
|
+
# ternary operator. The same is true for `break`, `next`, `yield`, `super`,
|
|
11
|
+
# `defined?` without parentheses, and method call.
|
|
11
12
|
#
|
|
12
13
|
# @example
|
|
13
14
|
# # bad
|
|
@@ -39,7 +40,7 @@ module RuboCop
|
|
|
39
40
|
|
|
40
41
|
MSG_IF = 'Avoid multi-line ternary operators, use `if` or `unless` instead.'
|
|
41
42
|
MSG_SINGLE_LINE = 'Avoid multi-line ternary operators, use single-line instead.'
|
|
42
|
-
SINGLE_LINE_TYPES = %i[return break next send csend].freeze
|
|
43
|
+
SINGLE_LINE_TYPES = %i[return break next send csend super yield].freeze
|
|
43
44
|
|
|
44
45
|
def on_if(node)
|
|
45
46
|
return unless offense?(node)
|
|
@@ -90,7 +91,10 @@ module RuboCop
|
|
|
90
91
|
end
|
|
91
92
|
|
|
92
93
|
def enforce_single_line_ternary_operator?(node)
|
|
93
|
-
|
|
94
|
+
return false unless (parent = node.parent)
|
|
95
|
+
return !parent.parenthesized? if parent.defined_type?
|
|
96
|
+
|
|
97
|
+
SINGLE_LINE_TYPES.include?(parent.type) && !use_assignment_method?(parent)
|
|
94
98
|
end
|
|
95
99
|
|
|
96
100
|
def use_assignment_method?(node)
|