rubocop 1.90.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 +241 -11
- data/config/obsoletion.yml +9 -0
- data/lib/rubocop/cached_data.rb +47 -7
- data/lib/rubocop/changed_files.rb +134 -0
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +23 -3
- 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 +11 -4
- data/lib/rubocop/comment_config/directive_range.rb +3 -1
- data/lib/rubocop/comment_config/disable_next.rb +49 -3
- data/lib/rubocop/comment_config/push_pop.rb +55 -0
- data/lib/rubocop/comment_config.rb +32 -53
- data/lib/rubocop/config.rb +10 -0
- data/lib/rubocop/config_loader.rb +18 -7
- data/lib/rubocop/config_loader_resolver.rb +79 -12
- data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
- data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +29 -3
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/badge.rb +1 -1
- data/lib/rubocop/cop/base.rb +57 -24
- 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/correctors.rb +2 -2
- 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/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/generator.rb +1 -1
- 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/on_send_without_on_csend.rb +1 -1
- 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 +2 -0
- 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/comment_indentation.rb +8 -5
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -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_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 +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_array_element_indentation.rb +17 -4
- 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/first_parameter_indentation.rb +11 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +15 -10
- 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 +4 -4
- 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 +71 -19
- 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 +10 -4
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +5 -1
- 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/argument_mismatch.rb +14 -4
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -0
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +88 -14
- 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/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +23 -2
- 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 +245 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +17 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +42 -17
- 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/lint.rb +1 -0
- 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/migration/department_name.rb +1 -1
- data/lib/rubocop/cop/mixin/alignment.rb +5 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
- 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 +26 -2
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +31 -3
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- 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 +29 -3
- 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 +4 -2
- data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
- data/lib/rubocop/cop/naming/block_forwarding.rb +4 -1
- data/lib/rubocop/cop/naming/block_parameter_name.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 +10 -2
- data/lib/rubocop/cop/security/json_load.rb +16 -4
- data/lib/rubocop/cop/severity.rb +12 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +10 -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 +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +6 -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 +29 -3
- data/lib/rubocop/cop/style/case_like_if.rb +9 -6
- 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/constant_visibility.rb +6 -2
- data/lib/rubocop/cop/style/data_inheritance.rb +14 -0
- data/lib/rubocop/cop/style/directive_scope.rb +154 -21
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +118 -18
- data/lib/rubocop/cop/style/documentation_method.rb +1 -9
- data/lib/rubocop/cop/style/double_negation.rb +11 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +15 -3
- data/lib/rubocop/cop/style/endless_method.rb +91 -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/file_null.rb +2 -2
- data/lib/rubocop/cop/style/float_division.rb +28 -14
- data/lib/rubocop/cop/style/for.rb +44 -1
- data/lib/rubocop/cop/style/format_string.rb +28 -6
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +13 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +35 -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/magic_comment_format.rb +1 -1
- 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 +36 -12
- 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 +48 -8
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +18 -2
- data/lib/rubocop/cop/style/not.rb +10 -3
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +14 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
- 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 +34 -17
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +10 -2
- data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +23 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +25 -5
- 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_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- 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/struct_inheritance.rb +14 -0
- 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_comma_in_block_args.rb +1 -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/style.rb +0 -1
- data/lib/rubocop/cop/team.rb +10 -5
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -1
- data/lib/rubocop/cops_documentation_generator.rb +23 -2
- data/lib/rubocop/directive_comment.rb +37 -8
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -1
- data/lib/rubocop/formatter/formatter_set.rb +6 -1
- data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
- data/lib/rubocop/formatter/html_formatter.rb +2 -2
- data/lib/rubocop/formatter/json_formatter.rb +71 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -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 +186 -0
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
- data/lib/rubocop/formatter.rb +1 -0
- 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/magic_comment.rb +27 -0
- 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 +97 -4
- data/lib/rubocop/path_util.rb +1 -1
- data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +8 -5
- data/lib/rubocop/result_cache.rb +36 -18
- data/lib/rubocop/runner.rb +160 -49
- data/lib/rubocop/server/cache.rb +2 -2
- data/lib/rubocop/unified_diff.rb +257 -0
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +9 -1
- metadata +21 -6
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
|
@@ -181,11 +181,11 @@ module RuboCop
|
|
|
181
181
|
def autocorrect_modifier(corrector, node)
|
|
182
182
|
body = node.if_branch || node.else_branch
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
"#{' ' * node.source_range.column}#{body.source}"
|
|
184
|
+
next_code = "next #{node.inverse_keyword} #{node.condition.source}\n" \
|
|
185
|
+
"#{' ' * node.source_range.column}"
|
|
187
186
|
|
|
188
|
-
corrector.
|
|
187
|
+
corrector.insert_before(node, next_code)
|
|
188
|
+
corrector.remove(range_between(body.source_range.end_pos, node.source_range.end_pos))
|
|
189
189
|
end
|
|
190
190
|
|
|
191
191
|
def autocorrect_block(corrector, node)
|
|
@@ -231,7 +231,7 @@ module RuboCop
|
|
|
231
231
|
|
|
232
232
|
# end_range starts with the final newline of the if body
|
|
233
233
|
lines = (node.source_range.line + 1)...node.loc.end.line
|
|
234
|
-
lines = lines.to_a -
|
|
234
|
+
lines = lines.to_a - string_content_lines(node)
|
|
235
235
|
# Skip blank lines
|
|
236
236
|
lines.reject { |lineno| /\A\s*\z/.match?(buffer.source_line(lineno)) }
|
|
237
237
|
end
|
|
@@ -250,11 +250,25 @@ module RuboCop
|
|
|
250
250
|
lines.map { |lineno| buffer.source_line(lineno) =~ /\S/ }.min
|
|
251
251
|
end
|
|
252
252
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
253
|
+
# Lines that start inside a string literal or a heredoc body, whose
|
|
254
|
+
# leading whitespace is part of the string value.
|
|
255
|
+
def string_content_lines(node)
|
|
256
|
+
buffer = node.source_range.source_buffer
|
|
257
|
+
ranges = node.each_node(:any_str).filter_map { |str| string_content_range(str) }
|
|
258
|
+
|
|
259
|
+
ranges.flat_map do |range|
|
|
260
|
+
(range.line..range.last_line).select do |lineno|
|
|
261
|
+
(range.begin_pos...range.end_pos).cover?(buffer.line_range(lineno).begin_pos)
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def string_content_range(node)
|
|
267
|
+
if node.heredoc?
|
|
268
|
+
node.loc.heredoc_body
|
|
269
|
+
elsif node.loc?(:begin) && node.loc?(:end)
|
|
270
|
+
node.loc.begin.end.join(node.loc.end.begin)
|
|
271
|
+
end
|
|
258
272
|
end
|
|
259
273
|
|
|
260
274
|
def reindent_line(corrector, lineno, delta, buffer)
|
|
@@ -42,28 +42,68 @@ module RuboCop
|
|
|
42
42
|
# @!method nil_check?(node)
|
|
43
43
|
def_node_matcher :nil_check?, '(send _ :nil?)'
|
|
44
44
|
|
|
45
|
-
# rubocop:disable-next Metrics/AbcSize
|
|
46
45
|
def on_send(node)
|
|
47
46
|
return unless node.receiver
|
|
47
|
+
return if prefer_comparison? && comment_before_dot?(node)
|
|
48
48
|
|
|
49
49
|
style_check?(node) do
|
|
50
50
|
add_offense(node.loc.selector) do |corrector|
|
|
51
51
|
if prefer_comparison?
|
|
52
|
-
|
|
53
|
-
corrector.replace(range, ' == nil')
|
|
52
|
+
autocorrect_to_comparison(corrector, node)
|
|
54
53
|
else
|
|
55
|
-
|
|
56
|
-
corrector.replace(range, '.nil?')
|
|
54
|
+
autocorrect_to_predicate(corrector, node)
|
|
57
55
|
end
|
|
58
|
-
|
|
59
|
-
parent = node.parent
|
|
60
|
-
corrector.wrap(node, '(', ')') if parent.respond_to?(:method?) && parent.method?(:!)
|
|
61
56
|
end
|
|
62
57
|
end
|
|
63
58
|
end
|
|
64
59
|
|
|
65
60
|
private
|
|
66
61
|
|
|
62
|
+
def comment_before_dot?(node)
|
|
63
|
+
return false unless node.loc.dot
|
|
64
|
+
|
|
65
|
+
processed_source.contains_comment?(node.receiver.source_range.end.join(node.loc.dot))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def autocorrect_to_comparison(corrector, node)
|
|
69
|
+
range = node.receiver.source_range.end.join(node.loc.selector.end)
|
|
70
|
+
corrector.replace(range, ' == nil')
|
|
71
|
+
|
|
72
|
+
return if !operator_expression?(node.parent) && !receiver_of_parent?(node)
|
|
73
|
+
|
|
74
|
+
corrector.wrap(node, '(', ')')
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def autocorrect_to_predicate(corrector, node)
|
|
78
|
+
receiver = node.receiver
|
|
79
|
+
if operator_expression?(receiver)
|
|
80
|
+
# A looser-binding receiver (e.g. `!x`, `a + b`) must be parenthesized
|
|
81
|
+
# so the appended `.nil?` applies to the whole expression.
|
|
82
|
+
corrector.replace(node, "(#{receiver.source}).nil?")
|
|
83
|
+
else
|
|
84
|
+
range = receiver.source_range.end.join(node.source_range.end)
|
|
85
|
+
corrector.replace(range, '.nil?')
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def operator_expression?(node)
|
|
90
|
+
return false unless node
|
|
91
|
+
|
|
92
|
+
operator_send?(node) ||
|
|
93
|
+
node.operator_keyword? ||
|
|
94
|
+
(node.if_type? && node.ternary?) ||
|
|
95
|
+
node.type?(:range, :iflipflop, :eflipflop) ||
|
|
96
|
+
node.assignment?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def receiver_of_parent?(node)
|
|
100
|
+
node.parent&.call_type? && node.parent.receiver.equal?(node)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def operator_send?(node)
|
|
104
|
+
node.send_type? && node.operator_method? && !node.method?(:[]) && !node.method?(:[]=)
|
|
105
|
+
end
|
|
106
|
+
|
|
67
107
|
def message(_node)
|
|
68
108
|
prefer_comparison? ? EXPLICIT_MSG : PREDICATE_MSG
|
|
69
109
|
end
|
|
@@ -48,7 +48,7 @@ module RuboCop
|
|
|
48
48
|
{ ({return next break} nil) (nil) }
|
|
49
49
|
PATTERN
|
|
50
50
|
|
|
51
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
|
|
51
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler -- a lambda whose body is `nil` uses no parameters
|
|
52
52
|
return unless node.lambda_or_proc?
|
|
53
53
|
return unless nil_return?(node.body)
|
|
54
54
|
# `return` inside a non-lambda proc returns from the enclosing method,
|
|
@@ -109,7 +109,7 @@ module RuboCop
|
|
|
109
109
|
|
|
110
110
|
def message(node)
|
|
111
111
|
if node.method?(:!=) && !include_semantic_changes?
|
|
112
|
-
prefer =
|
|
112
|
+
prefer = non_nil_check_replacement(node)
|
|
113
113
|
format(MSG_FOR_REPLACEMENT, prefer: prefer, current: node.source)
|
|
114
114
|
else
|
|
115
115
|
MSG_FOR_REDUNDANCY
|
|
@@ -120,11 +120,27 @@ module RuboCop
|
|
|
120
120
|
cop_config['IncludeSemanticChanges']
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
+
# An operator-expression receiver (e.g. `a + b`) binds looser than the
|
|
124
|
+
# appended `.nil?`, so it must be parenthesized: `!(a + b).nil?`.
|
|
125
|
+
def non_nil_check_replacement(node)
|
|
126
|
+
receiver = node.receiver
|
|
127
|
+
source = operator_expression?(receiver) ? "(#{receiver.source})" : receiver.source
|
|
128
|
+
"!#{source}.nil?"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def operator_expression?(node)
|
|
132
|
+
node.operator_keyword? ||
|
|
133
|
+
(node.send_type? && node.operator_method?) ||
|
|
134
|
+
(node.if_type? && node.ternary?) ||
|
|
135
|
+
node.type?(:range, :iflipflop, :eflipflop) ||
|
|
136
|
+
node.assignment?
|
|
137
|
+
end
|
|
138
|
+
|
|
123
139
|
def autocorrect_comparison(corrector, node)
|
|
124
140
|
if include_semantic_changes?
|
|
125
141
|
corrector.replace(node, node.receiver.source)
|
|
126
142
|
else
|
|
127
|
-
corrector.replace(node,
|
|
143
|
+
corrector.replace(node, non_nil_check_replacement(node))
|
|
128
144
|
end
|
|
129
145
|
end
|
|
130
146
|
|
|
@@ -54,9 +54,10 @@ module RuboCop
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def requires_parens?(child)
|
|
57
|
-
child.operator_keyword? ||
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
return true if child.operator_keyword? || operator_method_requiring_parens?(child)
|
|
58
|
+
return true if child.if_type? && child.ternary?
|
|
59
|
+
|
|
60
|
+
child.type?(:range, :iflipflop, :eflipflop) || child.assignment?
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
def correct_opposite_method(corrector, range, child)
|
|
@@ -72,6 +73,12 @@ module RuboCop
|
|
|
72
73
|
def correct_without_parens(corrector, range)
|
|
73
74
|
corrector.replace(range, '!')
|
|
74
75
|
end
|
|
76
|
+
|
|
77
|
+
def operator_method_requiring_parens?(child)
|
|
78
|
+
return false unless child.send_type?
|
|
79
|
+
|
|
80
|
+
child.binary_operation? || (child.unary_operation? && child.method?(:~))
|
|
81
|
+
end
|
|
75
82
|
end
|
|
76
83
|
end
|
|
77
84
|
end
|
|
@@ -55,7 +55,11 @@ module RuboCop
|
|
|
55
55
|
return unless type
|
|
56
56
|
|
|
57
57
|
add_offense(node) do |corrector|
|
|
58
|
-
|
|
58
|
+
# The prefix patterns below are anchored, so correct only the digits
|
|
59
|
+
# and leave any sign the literal's source carries in place.
|
|
60
|
+
range = unsigned_range(node)
|
|
61
|
+
|
|
62
|
+
corrector.replace(range, send(:"format_#{type}", range.source))
|
|
59
63
|
end
|
|
60
64
|
end
|
|
61
65
|
|
|
@@ -71,6 +75,12 @@ module RuboCop
|
|
|
71
75
|
octal_literal_type(literal) || hex_bin_dec_literal_type(literal)
|
|
72
76
|
end
|
|
73
77
|
|
|
78
|
+
def unsigned_range(node)
|
|
79
|
+
range = node.source_range
|
|
80
|
+
|
|
81
|
+
node.source.start_with?('+', '-') ? range.adjust(begin_pos: 1) : range
|
|
82
|
+
end
|
|
83
|
+
|
|
74
84
|
def octal_literal_type(literal)
|
|
75
85
|
if OCTAL_ZERO_ONLY_REGEX.match?(literal) && octal_zero_only?
|
|
76
86
|
:octal_zero_only
|
|
@@ -90,6 +90,7 @@ module RuboCop
|
|
|
90
90
|
def on_send(node)
|
|
91
91
|
numeric, replacement = check(node)
|
|
92
92
|
return unless numeric
|
|
93
|
+
return if handled_by_bitwise_predicate?(node)
|
|
93
94
|
|
|
94
95
|
return if allowed_method_name?(node.method_name) ||
|
|
95
96
|
node.each_ancestor(:send, :any_block).any? do |ancestor|
|
|
@@ -108,6 +109,12 @@ module RuboCop
|
|
|
108
109
|
allowed_method?(name) || matches_allowed_pattern?(name)
|
|
109
110
|
end
|
|
110
111
|
|
|
112
|
+
def handled_by_bitwise_predicate?(node)
|
|
113
|
+
bitwise_predicate_candidate?(node) &&
|
|
114
|
+
config.for_cop('Style/BitwisePredicate').fetch('Enabled') &&
|
|
115
|
+
BitwisePredicate.support_target_ruby_version?(target_ruby_version)
|
|
116
|
+
end
|
|
117
|
+
|
|
111
118
|
def check(node)
|
|
112
119
|
numeric, operator =
|
|
113
120
|
if style == :predicate
|
|
@@ -124,7 +131,7 @@ module RuboCop
|
|
|
124
131
|
def replacement(node, numeric, operation)
|
|
125
132
|
if style == :predicate
|
|
126
133
|
[parenthesized_source(numeric), REPLACEMENTS.invert[operation.to_s]].join('.')
|
|
127
|
-
elsif
|
|
134
|
+
elsif comparison_requires_parentheses?(node)
|
|
128
135
|
"(#{numeric.source} #{REPLACEMENTS[operation.to_s]} 0)"
|
|
129
136
|
else
|
|
130
137
|
[numeric.source, REPLACEMENTS[operation.to_s], 0].join(' ')
|
|
@@ -140,7 +147,7 @@ module RuboCop
|
|
|
140
147
|
end
|
|
141
148
|
|
|
142
149
|
def require_parentheses?(node)
|
|
143
|
-
node.send_type? && node.
|
|
150
|
+
node.send_type? && node.operator_method? && !node.parenthesized?
|
|
144
151
|
end
|
|
145
152
|
|
|
146
153
|
def replacement_supported?(operator)
|
|
@@ -159,10 +166,11 @@ module RuboCop
|
|
|
159
166
|
end
|
|
160
167
|
end
|
|
161
168
|
|
|
162
|
-
def
|
|
163
|
-
return false unless (parent = node.parent)
|
|
169
|
+
def comparison_requires_parentheses?(node)
|
|
170
|
+
return false unless (parent = node.parent)&.call_type?
|
|
171
|
+
return true if parent.receiver.equal?(node)
|
|
164
172
|
|
|
165
|
-
parent.
|
|
173
|
+
parent.operator_method? && !parent.method?(:[]) && !parent.method?(:[]=)
|
|
166
174
|
end
|
|
167
175
|
|
|
168
176
|
# @!method predicate(node)
|
|
@@ -179,6 +187,14 @@ module RuboCop
|
|
|
179
187
|
def_node_matcher :inverted_comparison, <<~PATTERN
|
|
180
188
|
(send (int 0) ${:== :> :<} [$(...) !gvar_type?])
|
|
181
189
|
PATTERN
|
|
190
|
+
|
|
191
|
+
# @!method bitwise_predicate_candidate?(node)
|
|
192
|
+
def_node_matcher :bitwise_predicate_candidate?, <<~PATTERN
|
|
193
|
+
{
|
|
194
|
+
(send {(begin (send _ :& _)) (send _ :& _)} {:positive? :zero?})
|
|
195
|
+
(send {(begin (send _ :& _)) (send _ :& _)} {:> :==} (int 0))
|
|
196
|
+
}
|
|
197
|
+
PATTERN
|
|
182
198
|
end
|
|
183
199
|
end
|
|
184
200
|
end
|
|
@@ -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
|
|
@@ -117,13 +118,21 @@ module RuboCop
|
|
|
117
118
|
end
|
|
118
119
|
|
|
119
120
|
def ternary_replacement(node)
|
|
120
|
-
condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
|
121
|
+
condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring -- takes all three branches in one step
|
|
121
122
|
|
|
122
123
|
"#{expr_replacement(condition)} ? " \
|
|
123
124
|
"#{expr_replacement(if_branch)} : " \
|
|
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?
|
|
@@ -184,7 +184,7 @@ module RuboCop
|
|
|
184
184
|
def accesses?(rhs, lhs)
|
|
185
185
|
if lhs.method?(:[]=)
|
|
186
186
|
# FIXME: Workaround `rubocop:disable` comment for JRuby.
|
|
187
|
-
# rubocop:disable-next Performance/RedundantEqualityComparisonBlock
|
|
187
|
+
# rubocop:disable-next Performance/RedundantEqualityComparisonBlock -- a JRuby workaround, as the comment above says
|
|
188
188
|
matching_calls(rhs, lhs.receiver, :[]).any? { |args| args == lhs.arguments }
|
|
189
189
|
else
|
|
190
190
|
access_method = lhs.method_name.to_s.chop.to_sym
|
|
@@ -123,10 +123,15 @@ module RuboCop
|
|
|
123
123
|
|
|
124
124
|
def parens_allowed?(node)
|
|
125
125
|
parens_required?(node) ||
|
|
126
|
-
(safe_assignment?(node) &&
|
|
126
|
+
(safe_assignment?(node) && safe_assignment_kept?) ||
|
|
127
127
|
(node.multiline? && allow_multiline_conditions?)
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
+
def safe_assignment_kept?
|
|
131
|
+
safe_assignment_allowed? ||
|
|
132
|
+
config.for_enabled_cop('Lint/AssignmentInCondition')['AllowSafeAssignment']
|
|
133
|
+
end
|
|
134
|
+
|
|
130
135
|
def allow_multiline_conditions?
|
|
131
136
|
cop_config['AllowInMultilineConditions']
|
|
132
137
|
end
|
|
@@ -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)
|
|
@@ -183,7 +183,7 @@ module RuboCop
|
|
|
183
183
|
end
|
|
184
184
|
|
|
185
185
|
def adjusted_source(expr_node, block_node)
|
|
186
|
-
source = expr_node
|
|
186
|
+
source = element_source(expr_node)
|
|
187
187
|
return source unless block_node.numblock_type?
|
|
188
188
|
return source if block_node.method?(:each_with_object)
|
|
189
189
|
|
|
@@ -194,6 +194,22 @@ module RuboCop
|
|
|
194
194
|
def indent(node)
|
|
195
195
|
' ' * node.source_range.column
|
|
196
196
|
end
|
|
197
|
+
|
|
198
|
+
def element_source(expr_node)
|
|
199
|
+
if command_call?(expr_node) || expr_node.assignment? || expr_node.rescue_type?
|
|
200
|
+
return "(#{expr_node.source})"
|
|
201
|
+
end
|
|
202
|
+
return "[#{expr_node.source}]" if expr_node.array_type? && !expr_node.bracketed?
|
|
203
|
+
|
|
204
|
+
expr_node.source
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def command_call?(node)
|
|
208
|
+
node = node.send_node if node.any_block_type?
|
|
209
|
+
return false unless node.type?(:call, :super, :yield)
|
|
210
|
+
|
|
211
|
+
node.arguments? && !node.parenthesized? && !node.operator_method? && !node.setter_method?
|
|
212
|
+
end
|
|
197
213
|
end
|
|
198
214
|
end
|
|
199
215
|
end
|
|
@@ -139,7 +139,7 @@ module RuboCop
|
|
|
139
139
|
offense_range = node.loc.begin
|
|
140
140
|
|
|
141
141
|
add_offense(offense_range) do |corrector|
|
|
142
|
-
if node.parent&.assignment?
|
|
142
|
+
if node.parent&.assignment? || node.parent&.type?(:return, :next, :break)
|
|
143
143
|
replace_begin_with_statement(corrector, offense_range, node)
|
|
144
144
|
else
|
|
145
145
|
remove_begin(corrector, offense_range, node)
|
|
@@ -156,7 +156,7 @@ module RuboCop
|
|
|
156
156
|
first_child = node.children.first
|
|
157
157
|
|
|
158
158
|
source = first_child.source
|
|
159
|
-
source = "(#{source})" if
|
|
159
|
+
source = "(#{source})" if low_precedence_statement?(first_child)
|
|
160
160
|
|
|
161
161
|
corrector.replace(offense_range, source)
|
|
162
162
|
corrector.remove(range_between(offense_range.end_pos, first_child.source_range.end_pos))
|
|
@@ -164,6 +164,13 @@ module RuboCop
|
|
|
164
164
|
restore_removed_comments(corrector, offense_range, node, first_child)
|
|
165
165
|
end
|
|
166
166
|
|
|
167
|
+
def low_precedence_statement?(node)
|
|
168
|
+
return node.modifier_form? if node.basic_conditional?
|
|
169
|
+
return node.prefix_not? if node.send_type?
|
|
170
|
+
|
|
171
|
+
node.operator_keyword? && node.semantic_operator?
|
|
172
|
+
end
|
|
173
|
+
|
|
167
174
|
def remove_begin(corrector, offense_range, node)
|
|
168
175
|
if node.parent.respond_to?(:endless?) && node.parent.endless?
|
|
169
176
|
offense_range = range_with_surrounding_space(offense_range, newlines: true)
|
|
@@ -222,7 +229,17 @@ module RuboCop
|
|
|
222
229
|
end
|
|
223
230
|
|
|
224
231
|
def valid_begin_assignment?(node)
|
|
225
|
-
node.parent&.assignment? && !node.children.one?
|
|
232
|
+
node.parent&.assignment? && (!node.children.one? || too_long_when_joined?(node))
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def too_long_when_joined?(node)
|
|
236
|
+
statement = node.children.first
|
|
237
|
+
max = config.for_enabled_cop('Layout/LineLength')['Max']
|
|
238
|
+
return false unless max && statement.single_line?
|
|
239
|
+
|
|
240
|
+
length = statement.source.length
|
|
241
|
+
length += 2 if low_precedence_statement?(statement)
|
|
242
|
+
node.loc.column + length > max
|
|
226
243
|
end
|
|
227
244
|
|
|
228
245
|
def inspect_branches(node)
|
|
@@ -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
|
|
@@ -119,7 +126,7 @@ module RuboCop
|
|
|
119
126
|
end
|
|
120
127
|
|
|
121
128
|
def offense?(node)
|
|
122
|
-
_condition, _if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
|
129
|
+
_condition, _if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring -- takes all three branches in one step
|
|
123
130
|
return false if use_if_branch?(else_branch) || use_hash_key_assignment?(else_branch)
|
|
124
131
|
|
|
125
132
|
synonymous_condition_and_branch?(node) && !node.elsif? &&
|
|
@@ -143,7 +150,7 @@ module RuboCop
|
|
|
143
150
|
end
|
|
144
151
|
|
|
145
152
|
def synonymous_condition_and_branch?(node)
|
|
146
|
-
condition, if_branch, _else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
|
153
|
+
condition, if_branch, _else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring -- takes all three branches in one step
|
|
147
154
|
# e.g.
|
|
148
155
|
# if var
|
|
149
156
|
# var
|
|
@@ -192,7 +199,7 @@ module RuboCop
|
|
|
192
199
|
end
|
|
193
200
|
|
|
194
201
|
def branches_have_assignment?(node)
|
|
195
|
-
_condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
|
202
|
+
_condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring -- takes all three branches in one step
|
|
196
203
|
|
|
197
204
|
return false unless if_branch && else_branch
|
|
198
205
|
|
|
@@ -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)
|
|
@@ -294,12 +301,12 @@ module RuboCop
|
|
|
294
301
|
end
|
|
295
302
|
|
|
296
303
|
def make_ternary_form(node)
|
|
297
|
-
_condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
|
298
|
-
|
|
304
|
+
_condition, if_branch, else_branch = *node # rubocop:disable InternalAffairs/NodeDestructuring -- takes all three branches in one step
|
|
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?)
|
|
@@ -108,7 +114,7 @@ module RuboCop
|
|
|
108
114
|
|
|
109
115
|
node.arguments.map do |arg|
|
|
110
116
|
if arg.hash_type?
|
|
111
|
-
arg
|
|
117
|
+
hash_argument_source(arg)
|
|
112
118
|
else
|
|
113
119
|
"**#{arg.source}"
|
|
114
120
|
end
|
|
@@ -122,6 +128,15 @@ module RuboCop
|
|
|
122
128
|
|
|
123
129
|
mergeable?(parent)
|
|
124
130
|
end
|
|
131
|
+
|
|
132
|
+
# A braced hash literal passed to `merge` must have its braces stripped so
|
|
133
|
+
# its pairs join the surrounding keyword arguments. Keeping the braces would
|
|
134
|
+
# produce a positional hash after keyword arguments, which is invalid Ruby.
|
|
135
|
+
def hash_argument_source(hash)
|
|
136
|
+
return hash.source unless hash.braces?
|
|
137
|
+
|
|
138
|
+
hash.pairs.map(&:source).join(', ')
|
|
139
|
+
end
|
|
125
140
|
end
|
|
126
141
|
end
|
|
127
142
|
end
|