rubocop 1.91.0 → 1.92.2
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 +4 -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.rb +0 -4
- 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_obsoletion.rb +9 -0
- data/lib/rubocop/config_validator.rb +11 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/badge.rb +1 -1
- 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 +37 -7
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +25 -4
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +34 -0
- 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/argument_alignment.rb +5 -1
- 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 +29 -7
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/dot_position.rb +25 -15
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +21 -8
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +9 -3
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +21 -25
- data/lib/rubocop/cop/layout/extra_spacing.rb +21 -6
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +27 -1
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +15 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +16 -8
- 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 +7 -3
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
- data/lib/rubocop/cop/layout/indentation_consistency.rb +22 -5
- 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 +176 -26
- 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 +9 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +30 -5
- 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 +16 -3
- 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_around_operators.rb +31 -4
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +16 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +32 -9
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +29 -11
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -12
- 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/ambiguous_regexp_literal.rb +6 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +4 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +20 -17
- 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/nested_percent_literal.rb +3 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +3 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +22 -1
- data/lib/rubocop/cop/lint/percent_string_array.rb +75 -9
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +39 -9
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +11 -4
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +47 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -0
- 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/useless_setter_call.rb +7 -4
- 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 +23 -19
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +8 -2
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +105 -0
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +41 -6
- 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 +39 -5
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/mixin/visibility_help.rb +2 -1
- 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/naming/rescued_exceptions_variable_name.rb +1 -1
- 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 +37 -2
- 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 +37 -10
- data/lib/rubocop/cop/style/arguments_forwarding.rb +32 -3
- 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 +35 -3
- data/lib/rubocop/cop/style/case_equality.rb +14 -3
- data/lib/rubocop/cop/style/case_like_if.rb +6 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +57 -16
- data/lib/rubocop/cop/style/class_methods_definitions.rb +15 -0
- data/lib/rubocop/cop/style/collection_querying.rb +79 -46
- data/lib/rubocop/cop/style/combinable_loops.rb +89 -11
- data/lib/rubocop/cop/style/concat_array_literals.rb +58 -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/empty_string_inside_interpolation.rb +53 -11
- data/lib/rubocop/cop/style/endless_method.rb +104 -11
- 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 +37 -2
- data/lib/rubocop/cop/style/for.rb +53 -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 +31 -22
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +4 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +42 -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 +32 -26
- 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 +94 -4
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
- data/lib/rubocop/cop/style/lambda.rb +34 -1
- 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 +80 -13
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +26 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
- data/lib/rubocop/cop/style/method_def_parentheses.rb +38 -4
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- data/lib/rubocop/cop/style/mixin_grouping.rb +12 -3
- 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 +52 -7
- 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 +28 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +13 -2
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +19 -1
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/quoted_symbols.rb +5 -7
- data/lib/rubocop/cop/style/raise_args.rb +80 -11
- data/lib/rubocop/cop/style/reduce_to_hash.rb +47 -33
- data/lib/rubocop/cop/style/redundant_begin.rb +45 -5
- 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 +27 -11
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +11 -3
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +24 -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/redundant_self.rb +9 -1
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +28 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +38 -4
- data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
- data/lib/rubocop/cop/style/require_order.rb +25 -8
- data/lib/rubocop/cop/style/rescue_modifier.rb +11 -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/send_with_literal_method_name.rb +4 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +42 -4
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +21 -4
- data/lib/rubocop/cop/style/struct_inheritance.rb +6 -0
- data/lib/rubocop/cop/style/super_arguments.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +24 -6
- 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/routes.rb +23 -23
- 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 +36 -8
- data/lib/rubocop/remote_config.rb +4 -1
- data/lib/rubocop/result_cache.rb +20 -13
- data/lib/rubocop/runner.rb +110 -42
- data/lib/rubocop/server/cache.rb +6 -6
- data/lib/rubocop/target_ruby.rb +21 -9
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +16 -5
|
@@ -102,6 +102,7 @@ module RuboCop
|
|
|
102
102
|
return replaced_node unless node.parent
|
|
103
103
|
return "(#{replaced_node})" if node.parent.operator_keyword?
|
|
104
104
|
return "(#{replaced_node})" if node.parent.send_type? && node.parent.operator_method?
|
|
105
|
+
return "(#{replaced_node})" if parent_binds_tighter_than_ternary?(node)
|
|
105
106
|
|
|
106
107
|
replaced_node
|
|
107
108
|
end
|
|
@@ -124,6 +125,14 @@ module RuboCop
|
|
|
124
125
|
"#{expr_replacement(else_branch)}"
|
|
125
126
|
end
|
|
126
127
|
|
|
128
|
+
def parent_binds_tighter_than_ternary?(node)
|
|
129
|
+
parent = node.parent
|
|
130
|
+
return parent.receiver.equal?(node) if parent.call_type?
|
|
131
|
+
return parent.namespace.equal?(node) if parent.type?(:const, :casgn)
|
|
132
|
+
|
|
133
|
+
parent.if_type? && parent.ternary? && parent.condition.equal?(node)
|
|
134
|
+
end
|
|
135
|
+
|
|
127
136
|
def expr_replacement(node)
|
|
128
137
|
return 'nil' if node.nil?
|
|
129
138
|
|
|
@@ -131,7 +140,9 @@ module RuboCop
|
|
|
131
140
|
end
|
|
132
141
|
|
|
133
142
|
def requires_parentheses?(node)
|
|
134
|
-
return true if
|
|
143
|
+
return true if node.type?(
|
|
144
|
+
:and, :or, :if, :rescue, :while, :until, :while_post, :until_post, :any_match_pattern
|
|
145
|
+
)
|
|
135
146
|
return true if node.assignment?
|
|
136
147
|
return true if method_call_with_changed_precedence?(node)
|
|
137
148
|
|
|
@@ -139,7 +150,7 @@ module RuboCop
|
|
|
139
150
|
end
|
|
140
151
|
|
|
141
152
|
def method_call_with_changed_precedence?(node)
|
|
142
|
-
return false unless node.
|
|
153
|
+
return false unless node.call_type? && node.arguments?
|
|
143
154
|
return false if node.parenthesized_call?
|
|
144
155
|
|
|
145
156
|
!node.operator_method?
|
|
@@ -83,7 +83,8 @@ module RuboCop
|
|
|
83
83
|
control_op_condition(cond) do |first_child, rest_children|
|
|
84
84
|
return if require_parentheses?(node, first_child)
|
|
85
85
|
return if semicolon_separated_expressions?(first_child, rest_children)
|
|
86
|
-
return if modifier_op?(first_child)
|
|
86
|
+
return if modifier_op?(first_child) || first_child.masgn_type?
|
|
87
|
+
return if command_call_assignment?(first_child)
|
|
87
88
|
return if parens_allowed?(cond)
|
|
88
89
|
|
|
89
90
|
message = message(cond)
|
|
@@ -115,6 +116,23 @@ module RuboCop
|
|
|
115
116
|
node.basic_conditional? && node.modifier_form?
|
|
116
117
|
end
|
|
117
118
|
|
|
119
|
+
def command_call_assignment?(node)
|
|
120
|
+
return false if !node.assignment? && !setter_method?(node)
|
|
121
|
+
|
|
122
|
+
value = node.children.last
|
|
123
|
+
value = value.body if value.rescue_type?
|
|
124
|
+
|
|
125
|
+
command_call_assignment?(value) || command_call?(value)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def command_call?(node)
|
|
129
|
+
node = node.send_node if node.any_block_type?
|
|
130
|
+
return false if !node.type?(:call, :super, :yield) || !node.arguments?
|
|
131
|
+
return false if node.parenthesized? || node.operator_method? || node.setter_method?
|
|
132
|
+
|
|
133
|
+
!node.method?(:[])
|
|
134
|
+
end
|
|
135
|
+
|
|
118
136
|
def message(node)
|
|
119
137
|
kw = node.parent.keyword
|
|
120
138
|
article = kw == 'while' ? 'a' : 'an'
|
|
@@ -86,10 +86,21 @@ module RuboCop
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
def include_same_character_as_used_for_delimiter?(node, type)
|
|
89
|
-
return false unless %w[%w %i].include?(type)
|
|
90
|
-
|
|
91
89
|
used_delimiters = matchpairs(begin_source(node)[-1])
|
|
92
|
-
contains_delimiter?(node, used_delimiters)
|
|
90
|
+
return contains_delimiter?(node, used_delimiters) if %w[%w %i].include?(type)
|
|
91
|
+
return false unless %w[%q %s %r].include?(type)
|
|
92
|
+
|
|
93
|
+
contains_escaped_delimiter?(node, used_delimiters)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Without interpolation an escaped delimiter means something different
|
|
97
|
+
# once the delimiters change (`%q!it\!s!` is `"it!s"`, but `%q(it\!s)`
|
|
98
|
+
# is `"it\\!s"`). For a regexp the match stays the same, but its source
|
|
99
|
+
# changes. Interpolating literals read `\!` as `!` with any delimiter.
|
|
100
|
+
def contains_escaped_delimiter?(node, delimiters)
|
|
101
|
+
body = node.loc.begin.end.join(node.loc.end.begin).source
|
|
102
|
+
|
|
103
|
+
body.scan(/\\./m).any? { |escape| delimiters.include?(escape[1]) }
|
|
93
104
|
end
|
|
94
105
|
|
|
95
106
|
def contains_delimiter?(node, delimiters)
|
|
@@ -86,14 +86,12 @@ module RuboCop
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
def correct_quotes(str)
|
|
89
|
-
correction = if style == :single_quotes
|
|
90
|
-
to_string_literal(str)
|
|
91
|
-
else
|
|
92
|
-
str.gsub("\\'", "'").inspect
|
|
93
|
-
end
|
|
94
|
-
|
|
95
89
|
# The conversion process doubles escaped slashes, so they have to be reverted
|
|
96
|
-
|
|
90
|
+
if style == :single_quotes
|
|
91
|
+
to_string_literal(str).gsub('\\\\', '\\').gsub('\"', '"')
|
|
92
|
+
else
|
|
93
|
+
str.gsub("\\'", "'").inspect.gsub('\\\\', '\\')
|
|
94
|
+
end
|
|
97
95
|
end
|
|
98
96
|
|
|
99
97
|
def style
|
|
@@ -74,7 +74,7 @@ module RuboCop
|
|
|
74
74
|
|
|
75
75
|
arguments = [exception_node, message_node].compact.map(&:source).join(', ')
|
|
76
76
|
|
|
77
|
-
if
|
|
77
|
+
if parenthesize?(node)
|
|
78
78
|
"#{node.method_name}(#{arguments})"
|
|
79
79
|
else
|
|
80
80
|
"#{node.method_name} #{arguments}"
|
|
@@ -86,31 +86,60 @@ module RuboCop
|
|
|
86
86
|
return if message_nodes.size > 1
|
|
87
87
|
|
|
88
88
|
argument = message_nodes.first.source
|
|
89
|
-
exception_class = exception_node.
|
|
89
|
+
exception_class = exception_class_node(exception_node).source
|
|
90
90
|
|
|
91
|
-
if
|
|
91
|
+
if parenthesize?(node)
|
|
92
92
|
"#{node.method_name}(#{exception_class}.new(#{argument}))"
|
|
93
93
|
else
|
|
94
94
|
"#{node.method_name} #{exception_class}.new(#{argument})"
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
+
def exception_class_node(exception_node)
|
|
99
|
+
use_new_method?(exception_node) ? exception_node.receiver : exception_node
|
|
100
|
+
end
|
|
101
|
+
|
|
98
102
|
def check_compact(node)
|
|
99
103
|
if node.arguments.size > 1
|
|
100
104
|
exception = node.first_argument
|
|
101
105
|
return if exception.send_type? && exception.first_argument&.hash_type?
|
|
106
|
+
return if use_new_method?(exception) && exception.arguments?
|
|
102
107
|
|
|
103
108
|
add_offense(node, message: format(COMPACT_MSG, method: node.method_name)) do |corrector|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
corrector.replace(node, replacement)
|
|
107
|
-
opposite_style_detected
|
|
109
|
+
correct_raise(node) { correct_to_compact(corrector, node) }
|
|
108
110
|
end
|
|
109
111
|
else
|
|
110
112
|
correct_style_detected
|
|
111
113
|
end
|
|
112
114
|
end
|
|
113
115
|
|
|
116
|
+
def correct_to_compact(corrector, node)
|
|
117
|
+
if heredoc_message?(node)
|
|
118
|
+
correct_heredoc_exploded_to_compact(corrector, node)
|
|
119
|
+
else
|
|
120
|
+
corrector.replace(node, correction_exploded_to_compact(node))
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def heredoc_message?(node)
|
|
125
|
+
node.parenthesized? && node.arguments.size == 2 && heredoc?(node.last_argument)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def heredoc?(node)
|
|
129
|
+
node.each_node(:any_str).any?(&:heredoc?)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def correct_heredoc_exploded_to_compact(corrector, node)
|
|
133
|
+
exception_node, message_node = *node.arguments
|
|
134
|
+
exception_class = exception_class_node(exception_node)
|
|
135
|
+
corrector.replace(range_between(exception_class, message_node), '.new(')
|
|
136
|
+
corrector.insert_after(message_node, ')')
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def range_between(left_node, right_node)
|
|
140
|
+
left_node.source_range.end.join(right_node.source_range.begin)
|
|
141
|
+
end
|
|
142
|
+
|
|
114
143
|
def check_exploded(node)
|
|
115
144
|
return correct_style_detected unless node.arguments.one?
|
|
116
145
|
|
|
@@ -121,13 +150,43 @@ module RuboCop
|
|
|
121
150
|
return if allowed_non_exploded_type?(first_arg)
|
|
122
151
|
|
|
123
152
|
add_offense(node, message: format(EXPLODED_MSG, method: node.method_name)) do |corrector|
|
|
124
|
-
|
|
153
|
+
correct_raise(node) { correct_to_exploded(corrector, node) }
|
|
154
|
+
end
|
|
155
|
+
end
|
|
125
156
|
|
|
126
|
-
|
|
127
|
-
|
|
157
|
+
def correct_to_exploded(corrector, node)
|
|
158
|
+
if heredoc_new_argument?(node)
|
|
159
|
+
correct_heredoc_compact_to_exploded(corrector, node)
|
|
160
|
+
else
|
|
161
|
+
corrector.replace(node, correction_compact_to_exploded(node))
|
|
128
162
|
end
|
|
129
163
|
end
|
|
130
164
|
|
|
165
|
+
def heredoc_new_argument?(node)
|
|
166
|
+
new_call = node.first_argument
|
|
167
|
+
return false unless new_call.arguments.one? && heredoc?(new_call.first_argument)
|
|
168
|
+
|
|
169
|
+
node.parenthesized? || !parenthesize?(node)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def correct_heredoc_compact_to_exploded(corrector, node)
|
|
173
|
+
new_call = node.first_argument
|
|
174
|
+
corrector.replace(range_between(new_call.receiver, new_call.first_argument), ', ')
|
|
175
|
+
corrector.remove(new_call.loc.end) if new_call.loc.end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def correct_raise(node)
|
|
179
|
+
opposite_style_detected
|
|
180
|
+
return if inside_corrected_raise?(node)
|
|
181
|
+
|
|
182
|
+
yield
|
|
183
|
+
ignore_node(node)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def inside_corrected_raise?(node)
|
|
187
|
+
node.each_ancestor(:send).any? { |ancestor| ignored_node?(ancestor) }
|
|
188
|
+
end
|
|
189
|
+
|
|
131
190
|
def use_new_method?(first_arg)
|
|
132
191
|
first_arg.send_type? && first_arg.receiver && first_arg.method?(:new)
|
|
133
192
|
end
|
|
@@ -151,8 +210,18 @@ module RuboCop
|
|
|
151
210
|
Array(cop_config['AllowedCompactTypes']).include?(type)
|
|
152
211
|
end
|
|
153
212
|
|
|
213
|
+
def parenthesize?(node)
|
|
214
|
+
return true if node.parenthesized?
|
|
215
|
+
|
|
216
|
+
node.parent && requires_parens?(node.parent)
|
|
217
|
+
end
|
|
218
|
+
|
|
154
219
|
def requires_parens?(parent)
|
|
155
|
-
|
|
220
|
+
return true if parent.operator_keyword?
|
|
221
|
+
return true if parent.type?(:call, :super, :yield, :array, :pair)
|
|
222
|
+
return true if parent.any_def_type? && parent.endless?
|
|
223
|
+
|
|
224
|
+
parent.if_type? && parent.ternary?
|
|
156
225
|
end
|
|
157
226
|
end
|
|
158
227
|
end
|
|
@@ -100,6 +100,7 @@ module RuboCop
|
|
|
100
100
|
return unless key
|
|
101
101
|
return if accumulator_used_in_expressions?(block_node, key, value)
|
|
102
102
|
return if nested_match?(key) || nested_match?(value)
|
|
103
|
+
return if heredoc_in_inject_numblock?(block_node, key, value)
|
|
103
104
|
|
|
104
105
|
register_offense(node, block_node, key, value)
|
|
105
106
|
end
|
|
@@ -124,6 +125,12 @@ module RuboCop
|
|
|
124
125
|
end
|
|
125
126
|
end
|
|
126
127
|
|
|
128
|
+
def heredoc_in_inject_numblock?(block_node, key, value)
|
|
129
|
+
return false if !block_node.numblock_type? || block_node.method?(:each_with_object)
|
|
130
|
+
|
|
131
|
+
[key, value].any? { |node| node.each_node(:any_str).any?(&:heredoc?) }
|
|
132
|
+
end
|
|
133
|
+
|
|
127
134
|
def accumulator_name(block_node)
|
|
128
135
|
index = block_node.method?(:each_with_object) ? 1 : 0
|
|
129
136
|
block_node.argument_list[index].name
|
|
@@ -136,42 +143,20 @@ module RuboCop
|
|
|
136
143
|
def register_offense(send_node, block_node, key_expr, value_expr)
|
|
137
144
|
message = format(MSG, method: send_node.method_name)
|
|
138
145
|
|
|
146
|
+
# Each part is replaced separately so that heredoc bodies between them are kept.
|
|
139
147
|
add_offense(send_node.loc.selector, message: message) do |corrector|
|
|
140
|
-
corrector.replace(
|
|
141
|
-
replacement_range(send_node, block_node),
|
|
142
|
-
replacement(block_node, key_expr, value_expr)
|
|
143
|
-
)
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def replacement(block_node, key_expr, value_expr)
|
|
148
|
-
key_source = adjusted_source(key_expr, block_node)
|
|
149
|
-
value_source = adjusted_source(value_expr, block_node)
|
|
150
|
-
body = "[#{key_source}, #{value_source}]"
|
|
148
|
+
corrector.replace(method_call_range(send_node), 'to_h')
|
|
151
149
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
named_block_replacement(block_node, body)
|
|
156
|
-
end
|
|
157
|
-
end
|
|
150
|
+
unless block_node.numblock_type?
|
|
151
|
+
corrector.replace(block_node.arguments, "|#{element_arg_source(block_node)}|")
|
|
152
|
+
end
|
|
158
153
|
|
|
159
|
-
|
|
160
|
-
arg = element_arg_source(block_node)
|
|
161
|
-
if block_node.braces?
|
|
162
|
-
"to_h { |#{arg}| #{body} }"
|
|
163
|
-
else
|
|
164
|
-
do_end_replacement(block_node, body, arg)
|
|
154
|
+
correct_body(corrector, block_node, key_expr, value_expr)
|
|
165
155
|
end
|
|
166
156
|
end
|
|
167
157
|
|
|
168
|
-
def
|
|
169
|
-
|
|
170
|
-
"to_h do#{args}\n#{indent(block_node)} #{body}\n#{indent(block_node)}end"
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
def replacement_range(send_node, block_node)
|
|
174
|
-
range_between(send_node.loc.selector.begin_pos, block_node.source_range.end_pos)
|
|
158
|
+
def method_call_range(send_node)
|
|
159
|
+
range_between(send_node.loc.selector.begin_pos, send_node.source_range.end_pos)
|
|
175
160
|
end
|
|
176
161
|
|
|
177
162
|
def element_arg_source(block_node)
|
|
@@ -182,8 +167,18 @@ module RuboCop
|
|
|
182
167
|
end
|
|
183
168
|
end
|
|
184
169
|
|
|
170
|
+
def correct_body(corrector, block_node, key_expr, value_expr)
|
|
171
|
+
key_source = adjusted_source(key_expr, block_node)
|
|
172
|
+
value_source = adjusted_source(value_expr, block_node)
|
|
173
|
+
body = block_node.body
|
|
174
|
+
assignment = body.begin_type? ? body.children.first : body
|
|
175
|
+
|
|
176
|
+
corrector.replace(assignment, "[#{key_source}, #{value_source}]")
|
|
177
|
+
corrector.remove(accumulator_range(body.children.last)) if body.begin_type?
|
|
178
|
+
end
|
|
179
|
+
|
|
185
180
|
def adjusted_source(expr_node, block_node)
|
|
186
|
-
source = expr_node
|
|
181
|
+
source = element_source(expr_node)
|
|
187
182
|
return source unless block_node.numblock_type?
|
|
188
183
|
return source if block_node.method?(:each_with_object)
|
|
189
184
|
|
|
@@ -191,8 +186,27 @@ module RuboCop
|
|
|
191
186
|
source.gsub('_2', '_1')
|
|
192
187
|
end
|
|
193
188
|
|
|
194
|
-
def
|
|
195
|
-
|
|
189
|
+
def element_source(expr_node)
|
|
190
|
+
if command_call?(expr_node) || expr_node.assignment? || expr_node.rescue_type?
|
|
191
|
+
return "(#{expr_node.source})"
|
|
192
|
+
end
|
|
193
|
+
return "[#{expr_node.source}]" if expr_node.array_type? && !expr_node.bracketed?
|
|
194
|
+
|
|
195
|
+
expr_node.source
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def command_call?(node)
|
|
199
|
+
node = node.send_node if node.any_block_type?
|
|
200
|
+
return false unless node.type?(:call, :super, :yield)
|
|
201
|
+
|
|
202
|
+
node.arguments? && !node.parenthesized? && !node.operator_method? && !node.setter_method?
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def accumulator_range(accumulator)
|
|
206
|
+
range = range_with_surrounding_space(accumulator.source_range, side: :left)
|
|
207
|
+
return range unless range.source_buffer.source[range.begin_pos - 1] == ';'
|
|
208
|
+
|
|
209
|
+
range_with_surrounding_space(range.adjust(begin_pos: -1), side: :left, newlines: false)
|
|
196
210
|
end
|
|
197
211
|
end
|
|
198
212
|
end
|
|
@@ -67,6 +67,7 @@ module RuboCop
|
|
|
67
67
|
extend AutoCorrector
|
|
68
68
|
|
|
69
69
|
MSG = 'Redundant `begin` block detected.'
|
|
70
|
+
SPACE_INSIDE_PARENS_STYLES = %w[space compact].freeze
|
|
70
71
|
|
|
71
72
|
def self.autocorrect_incompatible_with
|
|
72
73
|
[Style::BlockDelimiters]
|
|
@@ -132,14 +133,15 @@ module RuboCop
|
|
|
132
133
|
empty_begin?(node) ||
|
|
133
134
|
begin_block_has_multiline_statements?(node) ||
|
|
134
135
|
contain_rescue_or_ensure?(node) ||
|
|
135
|
-
valid_context_using_only_begin?(node)
|
|
136
|
+
valid_context_using_only_begin?(node) ||
|
|
137
|
+
ternary_operand_requiring_begin?(node)
|
|
136
138
|
end
|
|
137
139
|
|
|
138
140
|
def register_offense(node)
|
|
139
141
|
offense_range = node.loc.begin
|
|
140
142
|
|
|
141
143
|
add_offense(offense_range) do |corrector|
|
|
142
|
-
if node.parent&.assignment?
|
|
144
|
+
if node.parent&.assignment? || node.parent&.type?(:return, :next, :break)
|
|
143
145
|
replace_begin_with_statement(corrector, offense_range, node)
|
|
144
146
|
else
|
|
145
147
|
remove_begin(corrector, offense_range, node)
|
|
@@ -156,7 +158,7 @@ module RuboCop
|
|
|
156
158
|
first_child = node.children.first
|
|
157
159
|
|
|
158
160
|
source = first_child.source
|
|
159
|
-
source = "(#{source})" if
|
|
161
|
+
source = "(#{source})" if low_precedence_statement?(first_child)
|
|
160
162
|
|
|
161
163
|
corrector.replace(offense_range, source)
|
|
162
164
|
corrector.remove(range_between(offense_range.end_pos, first_child.source_range.end_pos))
|
|
@@ -164,6 +166,13 @@ module RuboCop
|
|
|
164
166
|
restore_removed_comments(corrector, offense_range, node, first_child)
|
|
165
167
|
end
|
|
166
168
|
|
|
169
|
+
def low_precedence_statement?(node)
|
|
170
|
+
return node.modifier_form? if node.basic_conditional?
|
|
171
|
+
return node.prefix_not? if node.send_type?
|
|
172
|
+
|
|
173
|
+
node.operator_keyword? && node.semantic_operator?
|
|
174
|
+
end
|
|
175
|
+
|
|
167
176
|
def remove_begin(corrector, offense_range, node)
|
|
168
177
|
if node.parent.respond_to?(:endless?) && node.parent.endless?
|
|
169
178
|
offense_range = range_with_surrounding_space(offense_range, newlines: true)
|
|
@@ -184,7 +193,8 @@ module RuboCop
|
|
|
184
193
|
def use_modifier_form_after_multiline_begin_block?(node)
|
|
185
194
|
return false unless (parent = node.parent)
|
|
186
195
|
|
|
187
|
-
node.multiline? && parent.if_type? && parent.modifier_form?
|
|
196
|
+
node.multiline? && parent.if_type? && parent.modifier_form? &&
|
|
197
|
+
!parent.condition.equal?(node)
|
|
188
198
|
end
|
|
189
199
|
|
|
190
200
|
def correct_modifier_form_after_multiline_begin_block(corrector, node)
|
|
@@ -221,14 +231,44 @@ module RuboCop
|
|
|
221
231
|
parent&.send_type? || parent&.operator_keyword?
|
|
222
232
|
end
|
|
223
233
|
|
|
234
|
+
def ternary_operand_requiring_begin?(node)
|
|
235
|
+
return false unless node.parent&.if_type? && node.parent.ternary?
|
|
236
|
+
|
|
237
|
+
!node.children.one? || low_precedence_statement?(node.children.first)
|
|
238
|
+
end
|
|
239
|
+
|
|
224
240
|
def valid_begin_assignment?(node)
|
|
225
|
-
node.parent&.assignment? && !node.children.one?
|
|
241
|
+
node.parent&.assignment? && (!node.children.one? || too_long_when_joined?(node))
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def too_long_when_joined?(node)
|
|
245
|
+
statement = node.children.first
|
|
246
|
+
max = config.for_enabled_cop('Layout/LineLength')['Max']
|
|
247
|
+
return false unless max && statement.single_line?
|
|
248
|
+
|
|
249
|
+
length = statement.source.length
|
|
250
|
+
length += parentheses_width if low_precedence_statement?(statement)
|
|
251
|
+
|
|
252
|
+
node.loc.column + length > max
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def parentheses_width
|
|
256
|
+
space_inside_parens? ? 4 : 2
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def space_inside_parens?
|
|
260
|
+
return false unless config.cop_enabled?('Layout/SpaceInsideParens')
|
|
261
|
+
|
|
262
|
+
style = config.for_cop('Layout/SpaceInsideParens')['EnforcedStyle']
|
|
263
|
+
|
|
264
|
+
SPACE_INSIDE_PARENS_STYLES.include?(style)
|
|
226
265
|
end
|
|
227
266
|
|
|
228
267
|
def inspect_branches(node)
|
|
229
268
|
node.branches.each do |branch|
|
|
230
269
|
next unless branch&.kwbegin_type?
|
|
231
270
|
next if branch.rescue_node || branch.ensure_node
|
|
271
|
+
next if ternary_operand_requiring_begin?(branch)
|
|
232
272
|
|
|
233
273
|
register_offense(branch)
|
|
234
274
|
end
|
|
@@ -78,7 +78,10 @@ module RuboCop
|
|
|
78
78
|
].freeze
|
|
79
79
|
|
|
80
80
|
def on_if(node)
|
|
81
|
-
return
|
|
81
|
+
return unless redundant_condition_offense?(node)
|
|
82
|
+
return if node.each_ancestor(:if).any? do |ancestor|
|
|
83
|
+
redundant_condition_offense?(ancestor)
|
|
84
|
+
end
|
|
82
85
|
|
|
83
86
|
message = message(node)
|
|
84
87
|
|
|
@@ -89,6 +92,10 @@ module RuboCop
|
|
|
89
92
|
|
|
90
93
|
private
|
|
91
94
|
|
|
95
|
+
def redundant_condition_offense?(node)
|
|
96
|
+
!node.modifier_form? && !node.elsif_conditional? && offense?(node)
|
|
97
|
+
end
|
|
98
|
+
|
|
92
99
|
def message(node)
|
|
93
100
|
if redundant_condition?(node)
|
|
94
101
|
REDUNDANT_CONDITION
|
|
@@ -240,10 +247,10 @@ module RuboCop
|
|
|
240
247
|
end
|
|
241
248
|
|
|
242
249
|
# rubocop:disable-next Metrics/AbcSize
|
|
243
|
-
def if_source(if_branch,
|
|
250
|
+
def if_source(if_branch, binary_operator)
|
|
244
251
|
if branches_have_method?(if_branch.parent) && if_branch.parenthesized?
|
|
245
252
|
if_branch.source.delete_suffix(')')
|
|
246
|
-
elsif
|
|
253
|
+
elsif binary_operator
|
|
247
254
|
argument_source = if_branch.first_argument.source
|
|
248
255
|
|
|
249
256
|
"#{if_branch.receiver.source} #{if_branch.method_name} (#{argument_source}"
|
|
@@ -257,8 +264,8 @@ module RuboCop
|
|
|
257
264
|
end
|
|
258
265
|
end
|
|
259
266
|
|
|
260
|
-
def else_source(else_branch,
|
|
261
|
-
if
|
|
267
|
+
def else_source(else_branch, binary_operator) # rubocop:disable Metrics/AbcSize
|
|
268
|
+
if binary_operator
|
|
262
269
|
"#{else_branch.first_argument.source})"
|
|
263
270
|
elsif branches_have_method?(else_branch.parent)
|
|
264
271
|
else_source_if_has_method(else_branch)
|
|
@@ -295,11 +302,11 @@ module RuboCop
|
|
|
295
302
|
|
|
296
303
|
def make_ternary_form(node)
|
|
297
304
|
_condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring -- takes all three branches in one step
|
|
298
|
-
|
|
305
|
+
binary_operator = branches_have_method?(node) && binary_operator?(if_branch)
|
|
299
306
|
|
|
300
307
|
ternary_form = [
|
|
301
|
-
if_source(if_branch,
|
|
302
|
-
else_source(else_branch,
|
|
308
|
+
if_source(if_branch, binary_operator),
|
|
309
|
+
else_source(else_branch, binary_operator)
|
|
303
310
|
].join(' || ')
|
|
304
311
|
ternary_form += ')' if branches_have_method?(node) && if_branch.parenthesized?
|
|
305
312
|
|
|
@@ -320,17 +327,27 @@ module RuboCop
|
|
|
320
327
|
|
|
321
328
|
def require_parentheses?(node)
|
|
322
329
|
(node.basic_conditional? && node.modifier_form?) ||
|
|
323
|
-
node.range_type? ||
|
|
324
|
-
node.
|
|
325
|
-
|
|
330
|
+
node.range_type? || node.rescue_type? ||
|
|
331
|
+
(node.respond_to?(:semantic_operator?) && node.semantic_operator?) ||
|
|
332
|
+
low_precedence_keyword?(node)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# e.g. `not foo`, `return foo`, and `yield foo`
|
|
336
|
+
def low_precedence_keyword?(node)
|
|
337
|
+
return node.prefix_not? if node.send_type?
|
|
338
|
+
|
|
339
|
+
node.type?(:return, :next, :break, :yield, :super) &&
|
|
340
|
+
node.arguments? && !node.parenthesized?
|
|
326
341
|
end
|
|
327
342
|
|
|
328
343
|
def require_braces?(node)
|
|
329
344
|
node.hash_type? && !node.braces?
|
|
330
345
|
end
|
|
331
346
|
|
|
332
|
-
|
|
333
|
-
|
|
347
|
+
# Any binary operator binds tighter than `||`, so the fallback must be
|
|
348
|
+
# parenthesized as its argument, e.g. `stack << (foo || :new)`.
|
|
349
|
+
def binary_operator?(node)
|
|
350
|
+
node.binary_operation? && !node.dot?
|
|
334
351
|
end
|
|
335
352
|
|
|
336
353
|
def without_argument_parentheses_method?(node)
|
|
@@ -25,6 +25,12 @@ module RuboCop
|
|
|
25
25
|
MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
|
|
26
26
|
MERGE_METHODS = %i[merge merge!].freeze
|
|
27
27
|
|
|
28
|
+
# `Style/TrailingCommaInHashLiteral` adds a comma to the hash literal whose braces
|
|
29
|
+
# this cop removes in the same pass, which would leave a dangling comma.
|
|
30
|
+
def self.autocorrect_incompatible_with
|
|
31
|
+
[Style::TrailingCommaInHashLiteral]
|
|
32
|
+
end
|
|
33
|
+
|
|
28
34
|
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
29
35
|
def on_hash(node)
|
|
30
36
|
return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
|
|
@@ -37,23 +37,18 @@ module RuboCop
|
|
|
37
37
|
private
|
|
38
38
|
|
|
39
39
|
def fix_exploded(node)
|
|
40
|
-
exploded?(node) do |
|
|
40
|
+
exploded?(node) do |exception, message|
|
|
41
41
|
# `raise RuntimeError, nil` uses the class name as the message, so
|
|
42
42
|
# rewriting it to `raise nil.to_s` (an empty message) would change it.
|
|
43
43
|
next if message.nil_type?
|
|
44
44
|
|
|
45
45
|
add_offense(node, message: MSG_1) do |corrector|
|
|
46
|
-
corrector.
|
|
46
|
+
corrector.remove(exception.source_range.join(message.source_range.begin))
|
|
47
|
+
corrector.replace(message, message_source(message))
|
|
47
48
|
end
|
|
48
49
|
end
|
|
49
50
|
end
|
|
50
51
|
|
|
51
|
-
def replaced_exploded(node, command, message)
|
|
52
|
-
arg = string_message?(message) ? message.source : "#{message.source}.to_s"
|
|
53
|
-
arg = node.parenthesized? ? "(#{arg})" : " #{arg}"
|
|
54
|
-
"#{command}#{arg}"
|
|
55
|
-
end
|
|
56
|
-
|
|
57
52
|
def string_message?(message)
|
|
58
53
|
message.any_str_type?
|
|
59
54
|
end
|
|
@@ -63,22 +58,43 @@ module RuboCop
|
|
|
63
58
|
next if message.nil_type?
|
|
64
59
|
|
|
65
60
|
add_offense(node, message: MSG_2) do |corrector|
|
|
66
|
-
|
|
61
|
+
# Replacing the call would drop a heredoc body that sits inside its parentheses.
|
|
62
|
+
next if heredoc_body_inside?(new_call, message)
|
|
63
|
+
|
|
64
|
+
corrector.replace(new_call, message_source(message))
|
|
67
65
|
end
|
|
68
66
|
end
|
|
69
67
|
end
|
|
70
68
|
|
|
71
|
-
def
|
|
69
|
+
def heredoc_body_inside?(new_call, message)
|
|
70
|
+
message.each_node(:any_str).any? do |str|
|
|
71
|
+
str.heredoc? && str.loc.heredoc_end.end_pos < new_call.source_range.end_pos
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def message_source(message)
|
|
72
76
|
if string_message?(message)
|
|
73
77
|
message.source
|
|
78
|
+
elsif require_parentheses?(message)
|
|
79
|
+
"(#{message.source}).to_s"
|
|
74
80
|
else
|
|
75
81
|
"#{message.source}.to_s"
|
|
76
82
|
end
|
|
77
83
|
end
|
|
78
84
|
|
|
85
|
+
def require_parentheses?(message)
|
|
86
|
+
if message.call_type?
|
|
87
|
+
!message.method?(:[]) &&
|
|
88
|
+
(message.operator_method? || (message.arguments? && !message.parenthesized?))
|
|
89
|
+
else
|
|
90
|
+
!(message.basic_literal? || message.variable? ||
|
|
91
|
+
message.type?(:const, :self, :begin, :array))
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
79
95
|
# @!method exploded?(node)
|
|
80
96
|
def_node_matcher :exploded?, <<~PATTERN
|
|
81
|
-
(send nil?
|
|
97
|
+
(send nil? {:raise :fail} $(const {nil? cbase} :RuntimeError) $_)
|
|
82
98
|
PATTERN
|
|
83
99
|
|
|
84
100
|
# @!method compact?(node)
|