rubocop 1.72.1 → 1.81.7
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 +22 -18
- data/config/default.yml +240 -65
- data/config/internal_affairs.yml +20 -0
- data/config/obsoletion.yml +8 -3
- data/exe/rubocop +1 -8
- data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
- data/lib/rubocop/cli.rb +19 -4
- data/lib/rubocop/config.rb +35 -6
- data/lib/rubocop/config_loader.rb +8 -40
- data/lib/rubocop/config_loader_resolver.rb +9 -7
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
- data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
- data/lib/rubocop/config_obsoletion.rb +46 -2
- data/lib/rubocop/config_store.rb +5 -0
- data/lib/rubocop/config_validator.rb +7 -6
- data/lib/rubocop/cop/autocorrect_logic.rb +22 -14
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +7 -4
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
- data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +37 -15
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +9 -5
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +4 -4
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +6 -2
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +92 -0
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +6 -1
- data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +1 -1
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +36 -1
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +32 -14
- data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +101 -0
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +34 -4
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +8 -29
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +4 -7
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
- data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
- data/lib/rubocop/cop/layout/line_length.rb +43 -10
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +9 -5
- data/lib/rubocop/cop/layout/redundant_line_break.rb +9 -5
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +11 -5
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +10 -0
- data/lib/rubocop/cop/layout/space_around_keyword.rb +6 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -38
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +12 -3
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -5
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +13 -7
- data/lib/rubocop/cop/lint/debugger.rb +2 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +5 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +111 -23
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
- data/lib/rubocop/cop/lint/empty_interpolation.rb +14 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +32 -10
- data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/literal_as_condition.rb +124 -10
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +17 -8
- data/lib/rubocop/cop/lint/mixed_case_range.rb +2 -2
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +1 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
- data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +101 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +43 -13
- data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
- data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
- data/lib/rubocop/cop/lint/require_range_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -1
- data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +4 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +31 -5
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -1
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +12 -1
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +30 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +2 -0
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +9 -12
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +1 -0
- data/lib/rubocop/cop/lint/useless_or.rb +98 -0
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +121 -0
- data/lib/rubocop/cop/lint/void.rb +16 -2
- data/lib/rubocop/cop/message_annotator.rb +7 -3
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/metrics/block_length.rb +1 -0
- data/lib/rubocop/cop/metrics/method_length.rb +1 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +3 -3
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -2
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
- data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
- data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
- data/lib/rubocop/cop/mixin/hash_subset.rb +19 -4
- data/lib/rubocop/cop/mixin/line_length_help.rb +24 -8
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +12 -0
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +18 -2
- data/lib/rubocop/cop/naming/block_forwarding.rb +3 -3
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +187 -15
- data/lib/rubocop/cop/naming/predicate_method.rb +319 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +4 -4
- data/lib/rubocop/cop/naming/variable_name.rb +51 -6
- data/lib/rubocop/cop/registry.rb +9 -6
- data/lib/rubocop/cop/security/eval.rb +2 -1
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/security/open.rb +1 -0
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -10
- data/lib/rubocop/cop/style/accessor_grouping.rb +32 -6
- data/lib/rubocop/cop/style/arguments_forwarding.rb +21 -24
- data/lib/rubocop/cop/style/array_intersect.rb +113 -38
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
- data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +3 -2
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/class_and_module_children.rb +48 -10
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_methods.rb +1 -0
- data/lib/rubocop/cop/style/collection_querying.rb +167 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +1 -0
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +12 -5
- data/lib/rubocop/cop/style/comparable_between.rb +78 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +26 -8
- data/lib/rubocop/cop/style/constant_visibility.rb +14 -9
- data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
- data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
- data/lib/rubocop/cop/style/dig_chain.rb +1 -1
- data/lib/rubocop/cop/style/double_negation.rb +3 -3
- data/lib/rubocop/cop/style/empty_literal.rb +4 -0
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
- data/lib/rubocop/cop/style/endless_method.rb +176 -18
- data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
- data/lib/rubocop/cop/style/explicit_block_argument.rb +3 -3
- data/lib/rubocop/cop/style/exponential_notation.rb +5 -4
- data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
- data/lib/rubocop/cop/style/float_division.rb +15 -1
- data/lib/rubocop/cop/style/for.rb +1 -0
- data/lib/rubocop/cop/style/format_string_token.rb +38 -11
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
- data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
- data/lib/rubocop/cop/style/guard_clause.rb +2 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +16 -8
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -2
- data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +4 -1
- data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
- data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +3 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
- data/lib/rubocop/cop/style/if_unless_modifier.rb +35 -8
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +10 -6
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
- data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
- data/lib/rubocop/cop/style/it_assignment.rb +69 -12
- data/lib/rubocop/cop/style/it_block_parameter.rb +121 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +13 -7
- data/lib/rubocop/cop/style/lambda.rb +1 -0
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
- data/lib/rubocop/cop/style/map_into_array.rb +4 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +12 -3
- data/lib/rubocop/cop/style/map_to_set.rb +1 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +9 -8
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +16 -0
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -1
- data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
- data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
- data/lib/rubocop/cop/style/next.rb +44 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
- data/lib/rubocop/cop/style/object_then.rb +1 -0
- data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
- data/lib/rubocop/cop/style/parallel_assignment.rb +32 -20
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +1 -0
- data/lib/rubocop/cop/style/raise_args.rb +8 -8
- data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +35 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +57 -0
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +14 -4
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -9
- data/lib/rubocop/cop/style/redundant_format.rb +79 -18
- data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
- data/lib/rubocop/cop/style/redundant_interpolation.rb +12 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +1 -4
- data/lib/rubocop/cop/style/redundant_parentheses.rb +73 -18
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/redundant_self.rb +9 -5
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
- data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
- data/lib/rubocop/cop/style/return_nil.rb +2 -2
- data/lib/rubocop/cop/style/safe_navigation.rb +61 -14
- data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
- data/lib/rubocop/cop/style/semicolon.rb +23 -7
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +3 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +10 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +75 -101
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +18 -15
- data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
- data/lib/rubocop/cop/style/super_arguments.rb +1 -2
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +3 -1
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -0
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +52 -1
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/format_string.rb +15 -2
- data/lib/rubocop/cop/variable_force/assignment.rb +7 -3
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +3 -8
- data/lib/rubocop/cop/variable_force.rb +26 -9
- data/lib/rubocop/cops_documentation_generator.rb +23 -7
- data/lib/rubocop/directive_comment.rb +1 -1
- data/lib/rubocop/ext/regexp_node.rb +0 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -5
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -0
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +2 -1
- data/lib/rubocop/lsp/diagnostic.rb +25 -24
- data/lib/rubocop/lsp/routes.rb +65 -9
- data/lib/rubocop/lsp/runtime.rb +5 -5
- data/lib/rubocop/lsp/server.rb +2 -2
- data/lib/rubocop/lsp/stdin_runner.rb +3 -17
- data/lib/rubocop/magic_comment.rb +8 -0
- data/lib/rubocop/pending_cops_reporter.rb +56 -0
- data/lib/rubocop/plugin/configuration_integrator.rb +2 -0
- data/lib/rubocop/plugin/load_error.rb +1 -1
- data/lib/rubocop/plugin.rb +9 -2
- data/lib/rubocop/result_cache.rb +14 -12
- data/lib/rubocop/rspec/cop_helper.rb +6 -1
- data/lib/rubocop/rspec/expect_offense.rb +9 -3
- data/lib/rubocop/rspec/shared_contexts.rb +34 -0
- data/lib/rubocop/rspec/support.rb +3 -0
- data/lib/rubocop/runner.rb +10 -4
- data/lib/rubocop/server/cache.rb +17 -12
- data/lib/rubocop/server/client_command/base.rb +10 -0
- data/lib/rubocop/server/client_command/exec.rb +2 -1
- data/lib/rubocop/server/client_command/start.rb +11 -1
- data/lib/rubocop/target_finder.rb +13 -9
- data/lib/rubocop/target_ruby.rb +11 -2
- data/lib/rubocop/version.rb +14 -7
- data/lib/rubocop.rb +17 -2
- data/lib/ruby_lsp/rubocop/addon.rb +25 -10
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +57 -5
- metadata +24 -8
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Prefer `Enumerable` predicate methods over expressions with `count`.
|
|
7
|
+
#
|
|
8
|
+
# The cop checks calls to `count` without arguments, or with a
|
|
9
|
+
# block. It doesn't register offenses for `count` with a positional
|
|
10
|
+
# argument because its behavior differs from predicate methods (`count`
|
|
11
|
+
# matches the argument using `==`, while `any?`, `none?` and `one?` use
|
|
12
|
+
# `===`).
|
|
13
|
+
#
|
|
14
|
+
# NOTE: This cop doesn't check `length` and `size` methods because they
|
|
15
|
+
# would yield false positives. For example, `String` implements `length`
|
|
16
|
+
# and `size`, but it doesn't include `Enumerable`.
|
|
17
|
+
#
|
|
18
|
+
# @safety
|
|
19
|
+
# The cop is unsafe because receiver might not include `Enumerable`, or
|
|
20
|
+
# it has nonstandard implementation of `count` or any replacement
|
|
21
|
+
# methods.
|
|
22
|
+
#
|
|
23
|
+
# It's also unsafe because for collections with falsey values, expressions
|
|
24
|
+
# with `count` without a block return a different result than methods `any?`,
|
|
25
|
+
# `none?` and `one?`:
|
|
26
|
+
#
|
|
27
|
+
# [source,ruby]
|
|
28
|
+
# ----
|
|
29
|
+
# [nil, false].count.positive?
|
|
30
|
+
# [nil].count == 1
|
|
31
|
+
# # => true
|
|
32
|
+
#
|
|
33
|
+
# [nil, false].any?
|
|
34
|
+
# [nil].one?
|
|
35
|
+
# # => false
|
|
36
|
+
#
|
|
37
|
+
# [nil].count == 0
|
|
38
|
+
# # => false
|
|
39
|
+
#
|
|
40
|
+
# [nil].none?
|
|
41
|
+
# # => true
|
|
42
|
+
# ----
|
|
43
|
+
#
|
|
44
|
+
# Autocorrection is unsafe when replacement methods don't iterate over
|
|
45
|
+
# every element in collection and the given block runs side effects:
|
|
46
|
+
#
|
|
47
|
+
# [source,ruby]
|
|
48
|
+
# ----
|
|
49
|
+
# x.count(&:method_with_side_effects).positive?
|
|
50
|
+
# # calls `method_with_side_effects` on every element
|
|
51
|
+
#
|
|
52
|
+
# x.any?(&:method_with_side_effects)
|
|
53
|
+
# # calls `method_with_side_effects` until first element returns a truthy value
|
|
54
|
+
# ----
|
|
55
|
+
#
|
|
56
|
+
# @example
|
|
57
|
+
#
|
|
58
|
+
# # bad
|
|
59
|
+
# x.count.positive?
|
|
60
|
+
# x.count > 0
|
|
61
|
+
# x.count != 0
|
|
62
|
+
#
|
|
63
|
+
# x.count(&:foo?).positive?
|
|
64
|
+
# x.count { |item| item.foo? }.positive?
|
|
65
|
+
#
|
|
66
|
+
# # good
|
|
67
|
+
# x.any?
|
|
68
|
+
#
|
|
69
|
+
# x.any?(&:foo?)
|
|
70
|
+
# x.any? { |item| item.foo? }
|
|
71
|
+
#
|
|
72
|
+
# # bad
|
|
73
|
+
# x.count.zero?
|
|
74
|
+
# x.count == 0
|
|
75
|
+
#
|
|
76
|
+
# # good
|
|
77
|
+
# x.none?
|
|
78
|
+
#
|
|
79
|
+
# # bad
|
|
80
|
+
# x.count == 1
|
|
81
|
+
# x.one?
|
|
82
|
+
#
|
|
83
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: false (default)
|
|
84
|
+
#
|
|
85
|
+
# # good
|
|
86
|
+
# x.count > 1
|
|
87
|
+
#
|
|
88
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: true
|
|
89
|
+
#
|
|
90
|
+
# # bad
|
|
91
|
+
# x.count > 1
|
|
92
|
+
#
|
|
93
|
+
# # good
|
|
94
|
+
# x.many?
|
|
95
|
+
#
|
|
96
|
+
class CollectionQuerying < Base
|
|
97
|
+
include RangeHelp
|
|
98
|
+
extend AutoCorrector
|
|
99
|
+
|
|
100
|
+
MSG = 'Use `%<prefer>s` instead.'
|
|
101
|
+
|
|
102
|
+
RESTRICT_ON_SEND = %i[positive? > != zero? ==].freeze
|
|
103
|
+
|
|
104
|
+
REPLACEMENTS = {
|
|
105
|
+
[:positive?, nil] => :any?,
|
|
106
|
+
[:>, 0] => :any?,
|
|
107
|
+
[:!=, 0] => :any?,
|
|
108
|
+
[:zero?, nil] => :none?,
|
|
109
|
+
[:==, 0] => :none?,
|
|
110
|
+
[:==, 1] => :one?,
|
|
111
|
+
[:>, 1] => :many?
|
|
112
|
+
}.freeze
|
|
113
|
+
|
|
114
|
+
# @!method count_predicate(node)
|
|
115
|
+
def_node_matcher :count_predicate, <<~PATTERN
|
|
116
|
+
(send
|
|
117
|
+
{
|
|
118
|
+
(any_block $(call !nil? :count) _ _)
|
|
119
|
+
$(call !nil? :count (block-pass _)?)
|
|
120
|
+
}
|
|
121
|
+
{
|
|
122
|
+
:positive? |
|
|
123
|
+
:> (int 0) |
|
|
124
|
+
:!= (int 0) |
|
|
125
|
+
:zero? |
|
|
126
|
+
:== (int 0) |
|
|
127
|
+
:== (int 1) |
|
|
128
|
+
:> (int 1)
|
|
129
|
+
})
|
|
130
|
+
PATTERN
|
|
131
|
+
|
|
132
|
+
def on_send(node)
|
|
133
|
+
return unless (count_node = count_predicate(node))
|
|
134
|
+
|
|
135
|
+
replacement_method = replacement_method(node)
|
|
136
|
+
|
|
137
|
+
return unless replacement_supported?(replacement_method)
|
|
138
|
+
|
|
139
|
+
offense_range = count_node.loc.selector.join(node.source_range.end)
|
|
140
|
+
add_offense(offense_range,
|
|
141
|
+
message: format(MSG, prefer: replacement_method)) do |corrector|
|
|
142
|
+
corrector.replace(count_node.loc.selector, replacement_method)
|
|
143
|
+
corrector.remove(removal_range(node))
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
|
|
149
|
+
def replacement_method(node)
|
|
150
|
+
REPLACEMENTS.fetch([node.method_name, node.first_argument&.value])
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def replacement_supported?(method_name)
|
|
154
|
+
return true if active_support_extensions_enabled?
|
|
155
|
+
|
|
156
|
+
method_name != :many?
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def removal_range(node)
|
|
160
|
+
range = (node.loc.dot || node.loc.selector).join(node.source_range.end)
|
|
161
|
+
|
|
162
|
+
range_with_surrounding_space(range, side: :left)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -9,8 +9,8 @@ module RuboCop
|
|
|
9
9
|
# These keywords are: `class`, `module`, `def`, `begin`, `end`.
|
|
10
10
|
#
|
|
11
11
|
# Note that some comments
|
|
12
|
-
# (`:nodoc:`, `:yields:`, `rubocop:disable` and `rubocop:todo`)
|
|
13
|
-
#
|
|
12
|
+
# (`:nodoc:`, `:yields:`, `rubocop:disable` and `rubocop:todo`),
|
|
13
|
+
# RBS::Inline annotation, and Steep annotation (`steep:ignore`) are allowed.
|
|
14
14
|
#
|
|
15
15
|
# Autocorrection removes comments from `end` keyword and keeps comments
|
|
16
16
|
# for `class`, `module`, `def` and `begin` above the keyword.
|
|
@@ -57,8 +57,10 @@ module RuboCop
|
|
|
57
57
|
|
|
58
58
|
REGEXP = /(?<keyword>\S+).*#/.freeze
|
|
59
59
|
|
|
60
|
-
SUBCLASS_DEFINITION = /\A\s*class\s
|
|
61
|
-
|
|
60
|
+
SUBCLASS_DEFINITION = /\A\s*class\s+(\w|::)+\s*<\s*(\w|::)+/.freeze
|
|
61
|
+
METHOD_OR_END_DEFINITIONS = /\A\s*(def\s|end)/.freeze
|
|
62
|
+
|
|
63
|
+
STEEP_REGEXP = /#\ssteep:ignore(\s|\z)/.freeze
|
|
62
64
|
|
|
63
65
|
def on_new_investigation
|
|
64
66
|
processed_source.comments.each do |comment|
|
|
@@ -86,6 +88,7 @@ module RuboCop
|
|
|
86
88
|
def offensive?(comment)
|
|
87
89
|
line = source_line(comment)
|
|
88
90
|
return false if rbs_inline_annotation?(line, comment)
|
|
91
|
+
return false if steep_annotation?(comment)
|
|
89
92
|
|
|
90
93
|
KEYWORD_REGEXES.any? { |r| r.match?(line) } &&
|
|
91
94
|
ALLOWED_COMMENT_REGEXES.none? { |r| r.match?(line) }
|
|
@@ -99,12 +102,16 @@ module RuboCop
|
|
|
99
102
|
case line
|
|
100
103
|
when SUBCLASS_DEFINITION
|
|
101
104
|
comment.text.start_with?(/#\[.+\]/)
|
|
102
|
-
when
|
|
105
|
+
when METHOD_OR_END_DEFINITIONS
|
|
103
106
|
comment.text.start_with?('#:')
|
|
104
107
|
else
|
|
105
108
|
false
|
|
106
109
|
end
|
|
107
110
|
end
|
|
111
|
+
|
|
112
|
+
def steep_annotation?(comment)
|
|
113
|
+
comment.text.match?(STEEP_REGEXP)
|
|
114
|
+
end
|
|
108
115
|
end
|
|
109
116
|
end
|
|
110
117
|
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for logical comparison which can be replaced with `Comparable#between?`.
|
|
7
|
+
#
|
|
8
|
+
# NOTE: `Comparable#between?` is on average slightly slower than logical comparison,
|
|
9
|
+
# although the difference generally isn't observable. If you require maximum
|
|
10
|
+
# performance, consider using logical comparison.
|
|
11
|
+
#
|
|
12
|
+
# @safety
|
|
13
|
+
# This cop is unsafe because the receiver may not respond to `between?`.
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
#
|
|
17
|
+
# # bad
|
|
18
|
+
# x >= min && x <= max
|
|
19
|
+
#
|
|
20
|
+
# # bad
|
|
21
|
+
# x <= max && x >= min
|
|
22
|
+
#
|
|
23
|
+
# # good
|
|
24
|
+
# x.between?(min, max)
|
|
25
|
+
#
|
|
26
|
+
class ComparableBetween < Base
|
|
27
|
+
extend AutoCorrector
|
|
28
|
+
|
|
29
|
+
MSG = 'Prefer `%<prefer>s` over logical comparison.'
|
|
30
|
+
|
|
31
|
+
# @!method logical_comparison_between_by_min_first?(node)
|
|
32
|
+
def_node_matcher :logical_comparison_between_by_min_first?, <<~PATTERN
|
|
33
|
+
(and
|
|
34
|
+
(send
|
|
35
|
+
{$_value :>= $_min | $_min :<= $_value})
|
|
36
|
+
(send
|
|
37
|
+
{$_value :<= $_max | $_max :>= $_value}))
|
|
38
|
+
PATTERN
|
|
39
|
+
|
|
40
|
+
# @!method logical_comparison_between_by_max_first?(node)
|
|
41
|
+
def_node_matcher :logical_comparison_between_by_max_first?, <<~PATTERN
|
|
42
|
+
(and
|
|
43
|
+
(send
|
|
44
|
+
{$_value :<= $_max | $_max :>= $_value})
|
|
45
|
+
(send
|
|
46
|
+
{$_value :>= $_min | $_min :<= $_value}))
|
|
47
|
+
PATTERN
|
|
48
|
+
|
|
49
|
+
def on_and(node)
|
|
50
|
+
logical_comparison_between_by_min_first?(node) do |*args|
|
|
51
|
+
min_and_value, max_and_value = args.each_slice(2).to_a
|
|
52
|
+
|
|
53
|
+
register_offense(node, min_and_value, max_and_value)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
logical_comparison_between_by_max_first?(node) do |*args|
|
|
57
|
+
max_and_value, min_and_value = args.each_slice(2).to_a
|
|
58
|
+
|
|
59
|
+
register_offense(node, min_and_value, max_and_value)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def register_offense(node, min_and_value, max_and_value)
|
|
66
|
+
value = (min_and_value & max_and_value).first
|
|
67
|
+
min = min_and_value.find { _1 != value } || value
|
|
68
|
+
max = max_and_value.find { _1 != value } || value
|
|
69
|
+
|
|
70
|
+
prefer = "#{value.source}.between?(#{min.source}, #{max.source})"
|
|
71
|
+
add_offense(node, message: format(MSG, prefer: prefer)) do |corrector|
|
|
72
|
+
corrector.replace(node, prefer)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -111,7 +111,7 @@ module RuboCop
|
|
|
111
111
|
end
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
-
#
|
|
114
|
+
# Checks for `if` and `case` statements where each branch is used for
|
|
115
115
|
# both the assignment and comparison of the same variable
|
|
116
116
|
# when using the return of the condition can be used instead.
|
|
117
117
|
#
|
|
@@ -314,6 +314,7 @@ module RuboCop
|
|
|
314
314
|
|
|
315
315
|
def assignment_node(node)
|
|
316
316
|
assignment = node.send_type? ? node.last_argument : node.expression
|
|
317
|
+
return unless assignment
|
|
317
318
|
|
|
318
319
|
# ignore pseudo-assignments without rhs in for nodes
|
|
319
320
|
return if node.parent&.for_type?
|
|
@@ -436,26 +437,41 @@ module RuboCop
|
|
|
436
437
|
# Helper module to provide common methods to ConditionalAssignment
|
|
437
438
|
# correctors
|
|
438
439
|
module ConditionalCorrectorHelper
|
|
440
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
439
441
|
def remove_whitespace_in_branches(corrector, branch, condition, column)
|
|
440
442
|
branch.each_node do |child|
|
|
441
443
|
next if child.source_range.nil?
|
|
444
|
+
next if child.parent.dstr_type?
|
|
442
445
|
|
|
443
446
|
white_space = white_space_range(child, column)
|
|
444
|
-
corrector.remove(white_space) if white_space
|
|
447
|
+
corrector.remove(white_space) if white_space
|
|
445
448
|
end
|
|
446
449
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
corrector.remove_preceding(loc, loc.column - column)
|
|
450
|
+
if condition.loc.else && !same_line?(condition.else_branch, condition)
|
|
451
|
+
corrector.remove_preceding(condition.loc.else, condition.loc.else.column - column)
|
|
451
452
|
end
|
|
453
|
+
|
|
454
|
+
return unless condition.loc.end && !same_line?(
|
|
455
|
+
condition.branches.last.parent.else_branch, condition.loc.end
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
corrector.remove_preceding(condition.loc.end, condition.loc.end.column - column)
|
|
459
|
+
end
|
|
460
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
461
|
+
|
|
462
|
+
def same_line?(node1, node2)
|
|
463
|
+
RuboCop::Cop::Util.same_line?(node1, node2)
|
|
452
464
|
end
|
|
453
465
|
|
|
454
466
|
def white_space_range(node, column)
|
|
455
467
|
expression = node.source_range
|
|
456
|
-
|
|
468
|
+
end_pos = expression.begin_pos
|
|
469
|
+
begin_pos = end_pos - (expression.column - column - 2)
|
|
470
|
+
|
|
471
|
+
return nil if begin_pos > end_pos
|
|
457
472
|
|
|
458
|
-
Parser::Source::Range.new(expression.source_buffer, begin_pos,
|
|
473
|
+
white_space = Parser::Source::Range.new(expression.source_buffer, begin_pos, end_pos)
|
|
474
|
+
white_space if white_space.source.strip.empty?
|
|
459
475
|
end
|
|
460
476
|
|
|
461
477
|
def assignment(node)
|
|
@@ -595,6 +611,8 @@ module RuboCop
|
|
|
595
611
|
|
|
596
612
|
return unless (branch_else = branch.parent.loc.else)
|
|
597
613
|
|
|
614
|
+
return if same_line?(branch_else, condition)
|
|
615
|
+
|
|
598
616
|
corrector.remove_preceding(branch_else, branch_else.column - column)
|
|
599
617
|
end
|
|
600
618
|
end
|
|
@@ -48,6 +48,11 @@ module RuboCop
|
|
|
48
48
|
MSG = 'Explicitly make `%<constant_name>s` public or private using ' \
|
|
49
49
|
'either `#public_constant` or `#private_constant`.'
|
|
50
50
|
|
|
51
|
+
# @!method visibility_declaration_for(node)
|
|
52
|
+
def_node_matcher :visibility_declaration_for, <<~PATTERN
|
|
53
|
+
(send nil? {:public_constant :private_constant} $...)
|
|
54
|
+
PATTERN
|
|
55
|
+
|
|
51
56
|
def on_casgn(node)
|
|
52
57
|
return unless class_or_module_scope?(node)
|
|
53
58
|
return if visibility_declaration?(node)
|
|
@@ -77,20 +82,20 @@ module RuboCop
|
|
|
77
82
|
end
|
|
78
83
|
end
|
|
79
84
|
|
|
85
|
+
# rubocop:disable Metrics/AbcSize
|
|
80
86
|
def visibility_declaration?(node)
|
|
81
87
|
node.parent.each_child_node(:send).any? do |child|
|
|
82
|
-
visibility_declaration_for
|
|
83
|
-
end
|
|
84
|
-
end
|
|
88
|
+
next false unless (arguments = visibility_declaration_for(child))
|
|
85
89
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
arguments = arguments.first.children.first.to_a if arguments.first&.splat_type?
|
|
91
|
+
constant_values = arguments.map do |argument|
|
|
92
|
+
argument.value.to_sym if argument.respond_to?(:value)
|
|
93
|
+
end
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
constant_values.include?(node.name)
|
|
96
|
+
end
|
|
93
97
|
end
|
|
98
|
+
# rubocop:enable Metrics/AbcSize
|
|
94
99
|
end
|
|
95
100
|
end
|
|
96
101
|
end
|
|
@@ -4,6 +4,7 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
6
|
# Checks for inheritance from `Data.define` to avoid creating the anonymous parent class.
|
|
7
|
+
# Inheriting from `Data.define` adds a superfluous level in inheritance tree.
|
|
7
8
|
#
|
|
8
9
|
# @safety
|
|
9
10
|
# Autocorrection is unsafe because it will change the inheritance
|
|
@@ -17,12 +18,18 @@ module RuboCop
|
|
|
17
18
|
# end
|
|
18
19
|
# end
|
|
19
20
|
#
|
|
21
|
+
# Person.ancestors
|
|
22
|
+
# # => [Person, #<Class:0x000000010b4e14a0>, Data, (...)]
|
|
23
|
+
#
|
|
20
24
|
# # good
|
|
21
25
|
# Person = Data.define(:first_name, :last_name) do
|
|
22
26
|
# def age
|
|
23
27
|
# 42
|
|
24
28
|
# end
|
|
25
29
|
# end
|
|
30
|
+
#
|
|
31
|
+
# Person.ancestors
|
|
32
|
+
# # => [Person, Data, (...)]
|
|
26
33
|
class DataInheritance < Base
|
|
27
34
|
include RangeHelp
|
|
28
35
|
extend AutoCorrector
|
|
@@ -25,8 +25,9 @@ module RuboCop
|
|
|
25
25
|
# # good
|
|
26
26
|
# def foo = do_something
|
|
27
27
|
#
|
|
28
|
-
# # good
|
|
28
|
+
# # good - without parentheses it's a syntax error
|
|
29
29
|
# def foo() do_something end
|
|
30
|
+
# def foo()=do_something
|
|
30
31
|
#
|
|
31
32
|
# # bad
|
|
32
33
|
# def Baz.foo()
|
|
@@ -38,19 +39,31 @@ module RuboCop
|
|
|
38
39
|
# do_something
|
|
39
40
|
# end
|
|
40
41
|
class DefWithParentheses < Base
|
|
42
|
+
include RangeHelp
|
|
41
43
|
extend AutoCorrector
|
|
42
44
|
|
|
43
45
|
MSG = "Omit the parentheses in defs when the method doesn't accept any arguments."
|
|
44
46
|
|
|
45
47
|
def on_def(node)
|
|
46
|
-
return
|
|
47
|
-
return
|
|
48
|
+
return unless !node.arguments? && (arguments_range = node.arguments.source_range)
|
|
49
|
+
return if parentheses_required?(node, arguments_range)
|
|
48
50
|
|
|
49
|
-
add_offense(
|
|
50
|
-
corrector.remove(
|
|
51
|
+
add_offense(arguments_range) do |corrector|
|
|
52
|
+
corrector.remove(arguments_range)
|
|
51
53
|
end
|
|
52
54
|
end
|
|
53
55
|
alias on_defs on_def
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def parentheses_required?(node, arguments_range)
|
|
60
|
+
return true if node.single_line? && !node.endless?
|
|
61
|
+
|
|
62
|
+
end_pos = arguments_range.end.end_pos
|
|
63
|
+
token_after_argument = range_between(end_pos, end_pos + 1).source
|
|
64
|
+
|
|
65
|
+
token_after_argument == '='
|
|
66
|
+
end
|
|
54
67
|
end
|
|
55
68
|
end
|
|
56
69
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Style
|
|
6
|
-
#
|
|
6
|
+
# Checks for chained `dig` calls that can be collapsed into a single `dig`.
|
|
7
7
|
#
|
|
8
8
|
# @safety
|
|
9
9
|
# This cop is unsafe because it cannot be guaranteed that the receiver
|
|
@@ -96,20 +96,20 @@ module RuboCop
|
|
|
96
96
|
elsif last_child.type?(:pair, :hash) || last_child.parent.array_type?
|
|
97
97
|
false
|
|
98
98
|
else
|
|
99
|
-
last_child.
|
|
99
|
+
last_child.first_line <= node.first_line
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
def find_def_node_from_ascendant(node)
|
|
104
104
|
return unless (parent = node.parent)
|
|
105
|
-
return parent if parent.
|
|
105
|
+
return parent if parent.any_def_type?
|
|
106
106
|
return node.parent.child_nodes.first if define_method?(parent)
|
|
107
107
|
|
|
108
108
|
find_def_node_from_ascendant(node.parent)
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
def define_method?(node)
|
|
112
|
-
return false unless node.
|
|
112
|
+
return false unless node.any_block_type?
|
|
113
113
|
|
|
114
114
|
child = node.child_nodes.first
|
|
115
115
|
return false unless child.send_type?
|
|
@@ -6,6 +6,10 @@ module RuboCop
|
|
|
6
6
|
# Checks for the use of a method, the result of which
|
|
7
7
|
# would be a literal, like an empty array, hash, or string.
|
|
8
8
|
#
|
|
9
|
+
# NOTE: When frozen string literals are enabled, `String.new`
|
|
10
|
+
# isn't corrected to an empty string since the former is
|
|
11
|
+
# mutable and the latter would be frozen.
|
|
12
|
+
#
|
|
9
13
|
# @example
|
|
10
14
|
# # bad
|
|
11
15
|
# a = Array.new
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for empty strings being assigned inside string interpolation.
|
|
7
|
+
#
|
|
8
|
+
# Empty strings are a meaningless outcome inside of string interpolation, so we remove them.
|
|
9
|
+
# Alternatively, when configured to do so, we prioritise using empty strings.
|
|
10
|
+
#
|
|
11
|
+
# While this cop would also apply to variables that are only going to be used as strings,
|
|
12
|
+
# RuboCop can't detect that, so we only check inside of string interpolation.
|
|
13
|
+
#
|
|
14
|
+
# @example EnforcedStyle: trailing_conditional (default)
|
|
15
|
+
# # bad
|
|
16
|
+
# "#{condition ? 'foo' : ''}"
|
|
17
|
+
#
|
|
18
|
+
# # good
|
|
19
|
+
# "#{'foo' if condition}"
|
|
20
|
+
#
|
|
21
|
+
# # bad
|
|
22
|
+
# "#{condition ? '' : 'foo'}"
|
|
23
|
+
#
|
|
24
|
+
# # good
|
|
25
|
+
# "#{'foo' unless condition}"
|
|
26
|
+
#
|
|
27
|
+
# @example EnforcedStyle: ternary
|
|
28
|
+
# # bad
|
|
29
|
+
# "#{'foo' if condition}"
|
|
30
|
+
#
|
|
31
|
+
# # good
|
|
32
|
+
# "#{condition ? 'foo' : ''}"
|
|
33
|
+
#
|
|
34
|
+
# # bad
|
|
35
|
+
# "#{'foo' unless condition}"
|
|
36
|
+
#
|
|
37
|
+
# # good
|
|
38
|
+
# "#{condition ? '' : 'foo'}"
|
|
39
|
+
#
|
|
40
|
+
class EmptyStringInsideInterpolation < Base
|
|
41
|
+
include ConfigurableEnforcedStyle
|
|
42
|
+
include Interpolation
|
|
43
|
+
extend AutoCorrector
|
|
44
|
+
|
|
45
|
+
MSG_TRAILING_CONDITIONAL = 'Do not use trailing conditionals in string interpolation.'
|
|
46
|
+
MSG_TERNARY = 'Do not return empty strings in string interpolation.'
|
|
47
|
+
|
|
48
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
49
|
+
def on_interpolation(node)
|
|
50
|
+
node.each_child_node(:if) do |child_node|
|
|
51
|
+
if style == :trailing_conditional
|
|
52
|
+
if empty_if_outcome?(child_node)
|
|
53
|
+
ternary_style_autocorrect(child_node, child_node.else_branch.source, 'unless')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if empty_else_outcome?(child_node)
|
|
57
|
+
ternary_style_autocorrect(child_node, child_node.if_branch.source, 'if')
|
|
58
|
+
end
|
|
59
|
+
elsif style == :ternary
|
|
60
|
+
next unless child_node.modifier_form?
|
|
61
|
+
|
|
62
|
+
ternary_component = if child_node.unless?
|
|
63
|
+
"'' : #{child_node.if_branch.source}"
|
|
64
|
+
else
|
|
65
|
+
"#{child_node.if_branch.source} : ''"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
add_offense(node, message: MSG_TRAILING_CONDITIONAL) do |corrector|
|
|
69
|
+
corrector.replace(node, "\#{#{child_node.condition.source} ? #{ternary_component}}")
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def empty_if_outcome?(node)
|
|
79
|
+
empty_branch_outcome?(node.if_branch)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def empty_else_outcome?(node)
|
|
83
|
+
empty_branch_outcome?(node.else_branch)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def empty_branch_outcome?(branch)
|
|
87
|
+
return false unless branch
|
|
88
|
+
|
|
89
|
+
branch.nil_type? || (branch.str_type? && branch.value.empty?)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def ternary_style_autocorrect(node, outcome, condition)
|
|
93
|
+
add_offense(node, message: MSG_TERNARY) do |corrector|
|
|
94
|
+
corrector.replace(node, "#{outcome} #{condition} #{node.condition.source}")
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|