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
|
@@ -18,12 +18,15 @@ module RuboCop
|
|
|
18
18
|
# end
|
|
19
19
|
#
|
|
20
20
|
# # bad
|
|
21
|
-
#
|
|
21
|
+
# # We're only interested in the left hand side being a truthy literal,
|
|
22
|
+
# # because it affects the evaluation of the &&, whereas the right hand
|
|
23
|
+
# # side will be conditionally executed/called and can be a literal.
|
|
24
|
+
# if true && some_var
|
|
22
25
|
# do_something
|
|
23
26
|
# end
|
|
24
27
|
#
|
|
25
28
|
# # good
|
|
26
|
-
# if some_var
|
|
29
|
+
# if some_var
|
|
27
30
|
# do_something
|
|
28
31
|
# end
|
|
29
32
|
#
|
|
@@ -34,30 +37,107 @@ module RuboCop
|
|
|
34
37
|
# end
|
|
35
38
|
class LiteralAsCondition < Base
|
|
36
39
|
include RangeHelp
|
|
40
|
+
extend AutoCorrector
|
|
37
41
|
|
|
38
42
|
MSG = 'Literal `%<literal>s` appeared as a condition.'
|
|
39
43
|
RESTRICT_ON_SEND = [:!].freeze
|
|
40
44
|
|
|
45
|
+
def on_and(node)
|
|
46
|
+
return unless node.lhs.truthy_literal?
|
|
47
|
+
|
|
48
|
+
add_offense(node.lhs) do |corrector|
|
|
49
|
+
# Don't autocorrect `'foo' && return` because having `return` as
|
|
50
|
+
# the leftmost node can lead to a void value expression syntax error.
|
|
51
|
+
next if node.rhs.type?(:return, :break, :next)
|
|
52
|
+
|
|
53
|
+
corrector.replace(node, node.rhs.source)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def on_or(node)
|
|
58
|
+
return unless node.lhs.falsey_literal?
|
|
59
|
+
|
|
60
|
+
add_offense(node.lhs) do |corrector|
|
|
61
|
+
# Don't autocorrect `'foo' && return` because having `return` as
|
|
62
|
+
# the leftmost node can lead to a void value expression syntax error.
|
|
63
|
+
next if node.rhs.type?(:return, :break, :next)
|
|
64
|
+
|
|
65
|
+
corrector.replace(node, node.rhs.source)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
41
69
|
def on_if(node)
|
|
42
|
-
|
|
70
|
+
cond = condition(node)
|
|
71
|
+
|
|
72
|
+
return unless cond.falsey_literal? || cond.truthy_literal?
|
|
73
|
+
|
|
74
|
+
correct_if_node(node, cond)
|
|
43
75
|
end
|
|
44
76
|
|
|
45
77
|
def on_while(node)
|
|
46
|
-
return if
|
|
78
|
+
return if node.condition.source == 'true'
|
|
47
79
|
|
|
48
|
-
|
|
80
|
+
if node.condition.truthy_literal?
|
|
81
|
+
add_offense(node.condition) do |corrector|
|
|
82
|
+
corrector.replace(node.condition, 'true')
|
|
83
|
+
end
|
|
84
|
+
elsif node.condition.falsey_literal?
|
|
85
|
+
add_offense(node.condition) do |corrector|
|
|
86
|
+
corrector.remove(node)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
49
89
|
end
|
|
50
|
-
|
|
90
|
+
|
|
91
|
+
# rubocop:disable Metrics/AbcSize
|
|
92
|
+
def on_while_post(node)
|
|
93
|
+
return if node.condition.source == 'true'
|
|
94
|
+
|
|
95
|
+
if node.condition.truthy_literal?
|
|
96
|
+
add_offense(node.condition) do |corrector|
|
|
97
|
+
corrector.replace(node, node.source.sub(node.condition.source, 'true'))
|
|
98
|
+
end
|
|
99
|
+
elsif node.condition.falsey_literal?
|
|
100
|
+
add_offense(node.condition) do |corrector|
|
|
101
|
+
corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
# rubocop:enable Metrics/AbcSize
|
|
51
106
|
|
|
52
107
|
def on_until(node)
|
|
53
|
-
return if
|
|
108
|
+
return if node.condition.source == 'false'
|
|
54
109
|
|
|
55
|
-
|
|
110
|
+
if node.condition.falsey_literal?
|
|
111
|
+
add_offense(node.condition) do |corrector|
|
|
112
|
+
corrector.replace(node.condition, 'false')
|
|
113
|
+
end
|
|
114
|
+
elsif node.condition.truthy_literal?
|
|
115
|
+
add_offense(node.condition) do |corrector|
|
|
116
|
+
corrector.remove(node)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# rubocop:disable Metrics/AbcSize
|
|
122
|
+
def on_until_post(node)
|
|
123
|
+
return if node.condition.source == 'false'
|
|
124
|
+
|
|
125
|
+
if node.condition.falsey_literal?
|
|
126
|
+
add_offense(node.condition) do |corrector|
|
|
127
|
+
corrector.replace(node, node.source.sub(node.condition.source, 'false'))
|
|
128
|
+
end
|
|
129
|
+
elsif node.condition.truthy_literal?
|
|
130
|
+
add_offense(node.condition) do |corrector|
|
|
131
|
+
corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
|
|
132
|
+
end
|
|
133
|
+
end
|
|
56
134
|
end
|
|
57
|
-
|
|
135
|
+
# rubocop:enable Metrics/AbcSize
|
|
58
136
|
|
|
59
137
|
def on_case(case_node)
|
|
60
|
-
if case_node.condition
|
|
138
|
+
if (cond = case_node.condition)
|
|
139
|
+
return if !cond.falsey_literal? && !cond.truthy_literal?
|
|
140
|
+
|
|
61
141
|
check_case(case_node)
|
|
62
142
|
else
|
|
63
143
|
case_node.when_branches.each do |when_node|
|
|
@@ -130,6 +210,8 @@ module RuboCop
|
|
|
130
210
|
|
|
131
211
|
def handle_node(node)
|
|
132
212
|
if node.literal?
|
|
213
|
+
return if node.parent.and_type?
|
|
214
|
+
|
|
133
215
|
add_offense(node)
|
|
134
216
|
elsif %i[send and or begin].include?(node.type)
|
|
135
217
|
check_node(node)
|
|
@@ -159,6 +241,38 @@ module RuboCop
|
|
|
159
241
|
when_node.conditions.last.source_range.end_pos
|
|
160
242
|
)
|
|
161
243
|
end
|
|
244
|
+
|
|
245
|
+
def condition_evaluation?(node, cond)
|
|
246
|
+
if node.unless?
|
|
247
|
+
cond.falsey_literal?
|
|
248
|
+
else
|
|
249
|
+
cond.truthy_literal?
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
254
|
+
def correct_if_node(node, cond)
|
|
255
|
+
result = condition_evaluation?(node, cond)
|
|
256
|
+
|
|
257
|
+
new_node = if node.elsif? && result
|
|
258
|
+
"else\n #{range_with_comments(node.if_branch).source}"
|
|
259
|
+
elsif node.elsif? && !result
|
|
260
|
+
"else\n #{node.else_branch.source}"
|
|
261
|
+
elsif node.if_branch && result
|
|
262
|
+
node.if_branch.source
|
|
263
|
+
elsif node.elsif_conditional?
|
|
264
|
+
"#{node.else_branch.source.sub('elsif', 'if')}\nend"
|
|
265
|
+
elsif node.else? || node.ternary?
|
|
266
|
+
node.else_branch.source
|
|
267
|
+
else
|
|
268
|
+
'' # Equivalent to removing the node
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
add_offense(cond) do |corrector|
|
|
272
|
+
corrector.replace(node, new_node)
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
162
276
|
end
|
|
163
277
|
end
|
|
164
278
|
end
|
|
@@ -9,9 +9,21 @@ module RuboCop
|
|
|
9
9
|
# cop disables on wide ranges of code, that latter contributors to
|
|
10
10
|
# a file wouldn't be aware of.
|
|
11
11
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
12
|
+
# You can set `MaximumRangeSize` to define the maximum number of
|
|
13
|
+
# consecutive lines a cop can be disabled for.
|
|
14
|
+
#
|
|
15
|
+
# - `.inf` any size (default)
|
|
16
|
+
# - `0` allows only single-line disables
|
|
17
|
+
# - `1` means the maximum allowed is as follows:
|
|
18
|
+
#
|
|
19
|
+
# [source,ruby]
|
|
20
|
+
# ----
|
|
21
|
+
# # rubocop:disable SomeCop
|
|
22
|
+
# a = 1
|
|
23
|
+
# # rubocop:enable SomeCop
|
|
24
|
+
# ----
|
|
25
|
+
#
|
|
26
|
+
# @example MaximumRangeSize: .inf (default)
|
|
15
27
|
#
|
|
16
28
|
# # good
|
|
17
29
|
# # rubocop:disable Layout/SpaceAroundOperators
|
|
@@ -25,9 +37,7 @@ module RuboCop
|
|
|
25
37
|
# x= 0
|
|
26
38
|
# # EOF
|
|
27
39
|
#
|
|
28
|
-
# @example
|
|
29
|
-
# # Lint/MissingCopEnableDirective:
|
|
30
|
-
# # MaximumRangeSize: 2
|
|
40
|
+
# @example MaximumRangeSize: 2
|
|
31
41
|
#
|
|
32
42
|
# # good
|
|
33
43
|
# # rubocop:disable Layout/SpaceAroundOperators
|
|
@@ -52,10 +62,9 @@ module RuboCop
|
|
|
52
62
|
each_missing_enable do |cop, line_range|
|
|
53
63
|
next if acceptable_range?(cop, line_range)
|
|
54
64
|
|
|
55
|
-
range = source_range(processed_source.buffer, line_range.min, (0..0))
|
|
56
65
|
comment = processed_source.comment_at_line(line_range.begin)
|
|
57
66
|
|
|
58
|
-
add_offense(
|
|
67
|
+
add_offense(comment, message: message(cop, comment))
|
|
59
68
|
end
|
|
60
69
|
end
|
|
61
70
|
|
|
@@ -79,7 +79,7 @@ module RuboCop
|
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def range_pairs(expr)
|
|
82
|
-
|
|
82
|
+
expr.expressions.filter_map { |e| [e.expressions[0], e.expressions[1]] if e.type == :set }
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def unsafe_range?(range_start, range_end)
|
|
@@ -94,7 +94,7 @@ module RuboCop
|
|
|
94
94
|
|
|
95
95
|
def skip_range?(range_start, range_end)
|
|
96
96
|
[range_start, range_end].any? do |bound|
|
|
97
|
-
bound
|
|
97
|
+
bound&.type != :literal
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
|
|
@@ -98,7 +98,7 @@ module RuboCop
|
|
|
98
98
|
subject, = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
|
99
99
|
return if node.defs_type? && allowed_subject_type?(subject)
|
|
100
100
|
|
|
101
|
-
def_ancestor = node.each_ancestor(:
|
|
101
|
+
def_ancestor = node.each_ancestor(:any_def).first
|
|
102
102
|
return unless def_ancestor
|
|
103
103
|
|
|
104
104
|
within_scoping_def =
|
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
|
46
46
|
def on_return(return_node)
|
|
47
47
|
return if return_value?(return_node)
|
|
48
48
|
|
|
49
|
-
return_node.each_ancestor(:
|
|
49
|
+
return_node.each_ancestor(:any_block, :any_def) do |node|
|
|
50
50
|
break if scoped_node?(node)
|
|
51
51
|
|
|
52
52
|
# if a proc is passed to `Module#define_method` or
|
|
@@ -54,7 +54,7 @@ module RuboCop
|
|
|
54
54
|
# non-local exit error
|
|
55
55
|
break if define_method?(node.send_node)
|
|
56
56
|
|
|
57
|
-
next
|
|
57
|
+
next if node.argument_list.empty?
|
|
58
58
|
|
|
59
59
|
if chained_send?(node.send_node)
|
|
60
60
|
add_offense(return_node.loc.keyword)
|
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
|
66
66
|
private
|
|
67
67
|
|
|
68
68
|
def scoped_node?(node)
|
|
69
|
-
node.
|
|
69
|
+
node.any_def_type? || node.lambda?
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def return_value?(return_node)
|
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Lint
|
|
6
|
-
# Checks for `raise` or `fail` statements which
|
|
7
|
-
#
|
|
6
|
+
# Checks for `raise` or `fail` statements which raise `Exception` or
|
|
7
|
+
# `Exception.new`. Use `StandardError` or a specific exception class instead.
|
|
8
8
|
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
9
|
+
# If you have defined your own namespaced `Exception` class, it is possible
|
|
10
|
+
# to configure the cop to allow it by setting `AllowedImplicitNamespaces` to
|
|
11
|
+
# an array with the names of the namespaces to allow. By default, this is set to
|
|
12
|
+
# `['Gem']`, which allows `Gem::Exception` to be raised without an explicit namespace.
|
|
13
|
+
# If not allowed, a false positive may be registered if `raise Exception` is called
|
|
14
|
+
# within the namespace.
|
|
15
|
+
#
|
|
16
|
+
# Alternatively, use a fully qualified name with `raise`/`fail`
|
|
17
|
+
# (eg. `raise Namespace::Exception`).
|
|
15
18
|
#
|
|
16
19
|
# @safety
|
|
17
20
|
# This cop is unsafe because it will change the exception class being
|
|
@@ -20,15 +23,31 @@ module RuboCop
|
|
|
20
23
|
# @example
|
|
21
24
|
# # bad
|
|
22
25
|
# raise Exception, 'Error message here'
|
|
26
|
+
# raise Exception.new('Error message here')
|
|
23
27
|
#
|
|
24
28
|
# # good
|
|
25
29
|
# raise StandardError, 'Error message here'
|
|
30
|
+
# raise MyError.new, 'Error message here'
|
|
31
|
+
#
|
|
32
|
+
# @example AllowedImplicitNamespaces: ['Gem'] (default)
|
|
33
|
+
# # bad - `Foo` is not an allowed implicit namespace
|
|
34
|
+
# module Foo
|
|
35
|
+
# def self.foo
|
|
36
|
+
# raise Exception # This is qualified to `Foo::Exception`.
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
26
39
|
#
|
|
27
|
-
# @example AllowedImplicitNamespaces: ['Gem']
|
|
28
40
|
# # good
|
|
29
41
|
# module Gem
|
|
30
42
|
# def self.foo
|
|
31
|
-
# raise Exception # This
|
|
43
|
+
# raise Exception # This is qualified to `Gem::Exception`.
|
|
44
|
+
# end
|
|
45
|
+
# end
|
|
46
|
+
#
|
|
47
|
+
# # good
|
|
48
|
+
# module Foo
|
|
49
|
+
# def self.foo
|
|
50
|
+
# raise Foo::Exception
|
|
32
51
|
# end
|
|
33
52
|
# end
|
|
34
53
|
class RaiseException < Base
|
|
@@ -73,7 +73,7 @@ module RuboCop
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def redundant_group?(expr)
|
|
76
|
-
expr.is?(:passive, :group) && expr.
|
|
76
|
+
expr.is?(:passive, :group) && expr.one? { |child| child.type != :free_space }
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def redundantly_quantifiable?(node)
|
|
@@ -17,17 +17,12 @@ module RuboCop
|
|
|
17
17
|
# * 2.0+ ... `enumerator`
|
|
18
18
|
# * 2.1+ ... `thread`
|
|
19
19
|
# * 2.2+ ... Add `rational` and `complex` above
|
|
20
|
-
# * 2.5+ ... Add `pp` above
|
|
21
20
|
# * 2.7+ ... Add `ruby2_keywords` above
|
|
22
21
|
# * 3.1+ ... Add `fiber` above
|
|
23
22
|
# * 3.2+ ... `set`
|
|
24
23
|
#
|
|
25
24
|
# This cop target those features.
|
|
26
25
|
#
|
|
27
|
-
# @safety
|
|
28
|
-
# This cop's autocorrection is unsafe because if `require 'pp'` is removed from one file,
|
|
29
|
-
# `NameError` can be encountered when another file uses `PP.pp`.
|
|
30
|
-
#
|
|
31
26
|
# @example
|
|
32
27
|
# # bad
|
|
33
28
|
# require 'unloaded_feature'
|
|
@@ -42,10 +37,6 @@ module RuboCop
|
|
|
42
37
|
MSG = 'Remove unnecessary `require` statement.'
|
|
43
38
|
RESTRICT_ON_SEND = %i[require].freeze
|
|
44
39
|
RUBY_22_LOADED_FEATURES = %w[rational complex].freeze
|
|
45
|
-
PRETTY_PRINT_METHODS = %i[
|
|
46
|
-
pretty_inspect pretty_print pretty_print_cycle
|
|
47
|
-
pretty_print_inspect pretty_print_instance_variables
|
|
48
|
-
].freeze
|
|
49
40
|
|
|
50
41
|
# @!method redundant_require_statement?(node)
|
|
51
42
|
def_node_matcher :redundant_require_statement?, <<~PATTERN
|
|
@@ -53,11 +44,6 @@ module RuboCop
|
|
|
53
44
|
(str #redundant_feature?))
|
|
54
45
|
PATTERN
|
|
55
46
|
|
|
56
|
-
# @!method pp_const?(node)
|
|
57
|
-
def_node_matcher :pp_const?, <<~PATTERN
|
|
58
|
-
(const {nil? cbase} :PP)
|
|
59
|
-
PATTERN
|
|
60
|
-
|
|
61
47
|
def on_send(node)
|
|
62
48
|
return unless redundant_require_statement?(node)
|
|
63
49
|
|
|
@@ -81,18 +67,11 @@ module RuboCop
|
|
|
81
67
|
feature_name == 'enumerator' ||
|
|
82
68
|
(target_ruby_version >= 2.1 && feature_name == 'thread') ||
|
|
83
69
|
(target_ruby_version >= 2.2 && RUBY_22_LOADED_FEATURES.include?(feature_name)) ||
|
|
84
|
-
(target_ruby_version >= 2.5 && feature_name == 'pp' && !need_to_require_pp?) ||
|
|
85
70
|
(target_ruby_version >= 2.7 && feature_name == 'ruby2_keywords') ||
|
|
86
71
|
(target_ruby_version >= 3.1 && feature_name == 'fiber') ||
|
|
87
72
|
(target_ruby_version >= 3.2 && feature_name == 'set')
|
|
88
73
|
end
|
|
89
74
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
90
|
-
|
|
91
|
-
def need_to_require_pp?
|
|
92
|
-
processed_source.ast.each_descendant(:send).any? do |node|
|
|
93
|
-
pp_const?(node.receiver) || PRETTY_PRINT_METHODS.include?(node.method_name)
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
75
|
end
|
|
97
76
|
end
|
|
98
77
|
end
|
|
@@ -20,6 +20,15 @@ module RuboCop
|
|
|
20
20
|
# In the example below, the safe navigation operator (`&.`) is unnecessary
|
|
21
21
|
# because `NilClass` has methods like `respond_to?` and `is_a?`.
|
|
22
22
|
#
|
|
23
|
+
# The `InferNonNilReceiver` option specifies whether to look into previous code
|
|
24
|
+
# paths to infer if the receiver can't be nil. This check is unsafe because the receiver
|
|
25
|
+
# can be redefined between the safe navigation call and previous regular method call.
|
|
26
|
+
# It does the inference only in the current scope, e.g. within the same method definition etc.
|
|
27
|
+
#
|
|
28
|
+
# The `AdditionalNilMethods` option specifies additional custom methods which are
|
|
29
|
+
# defined on `NilClass`. When `InferNonNilReceiver` is set, they are used to determine
|
|
30
|
+
# whether the receiver can be nil.
|
|
31
|
+
#
|
|
23
32
|
# @safety
|
|
24
33
|
# This cop is unsafe, because autocorrection can change the return type of
|
|
25
34
|
# the expression. An offending expression that previously could return `nil`
|
|
@@ -33,6 +42,20 @@ module RuboCop
|
|
|
33
42
|
# CamelCaseConst.do_something
|
|
34
43
|
#
|
|
35
44
|
# # bad
|
|
45
|
+
# foo.to_s&.strip
|
|
46
|
+
# foo.to_i&.zero?
|
|
47
|
+
# foo.to_f&.zero?
|
|
48
|
+
# foo.to_a&.size
|
|
49
|
+
# foo.to_h&.size
|
|
50
|
+
#
|
|
51
|
+
# # good
|
|
52
|
+
# foo.to_s.strip
|
|
53
|
+
# foo.to_i.zero?
|
|
54
|
+
# foo.to_f.zero?
|
|
55
|
+
# foo.to_a.size
|
|
56
|
+
# foo.to_h.size
|
|
57
|
+
#
|
|
58
|
+
# # bad
|
|
36
59
|
# do_something if attrs&.respond_to?(:[])
|
|
37
60
|
#
|
|
38
61
|
# # good
|
|
@@ -81,17 +104,59 @@ module RuboCop
|
|
|
81
104
|
# do_something if attrs.nil_safe_method(:[])
|
|
82
105
|
# do_something if attrs&.not_nil_safe_method(:[])
|
|
83
106
|
#
|
|
107
|
+
# @example InferNonNilReceiver: false (default)
|
|
108
|
+
# # good
|
|
109
|
+
# foo.bar
|
|
110
|
+
# foo&.baz
|
|
111
|
+
#
|
|
112
|
+
# @example InferNonNilReceiver: true
|
|
113
|
+
# # bad
|
|
114
|
+
# foo.bar
|
|
115
|
+
# foo&.baz # would raise on previous line if `foo` is nil
|
|
116
|
+
#
|
|
117
|
+
# # good
|
|
118
|
+
# foo.bar
|
|
119
|
+
# foo.baz
|
|
120
|
+
#
|
|
121
|
+
# # bad
|
|
122
|
+
# if foo.condition?
|
|
123
|
+
# foo&.bar
|
|
124
|
+
# end
|
|
125
|
+
#
|
|
126
|
+
# # good
|
|
127
|
+
# if foo.condition?
|
|
128
|
+
# foo.bar
|
|
129
|
+
# end
|
|
130
|
+
#
|
|
131
|
+
# # good (different scopes)
|
|
132
|
+
# def method1
|
|
133
|
+
# foo.bar
|
|
134
|
+
# end
|
|
135
|
+
#
|
|
136
|
+
# def method2
|
|
137
|
+
# foo&.bar
|
|
138
|
+
# end
|
|
139
|
+
#
|
|
140
|
+
# @example AdditionalNilMethods: [present?]
|
|
141
|
+
# # good
|
|
142
|
+
# foo.present?
|
|
143
|
+
# foo&.bar
|
|
144
|
+
#
|
|
84
145
|
class RedundantSafeNavigation < Base
|
|
85
146
|
include AllowedMethods
|
|
86
147
|
extend AutoCorrector
|
|
87
148
|
|
|
88
149
|
MSG = 'Redundant safe navigation detected, use `.` instead.'
|
|
89
150
|
MSG_LITERAL = 'Redundant safe navigation with default literal detected.'
|
|
151
|
+
MSG_NON_NIL = 'Redundant safe navigation on non-nil receiver (detected by analyzing ' \
|
|
152
|
+
'previous code/method invocations).'
|
|
90
153
|
|
|
91
154
|
NIL_SPECIFIC_METHODS = (nil.methods - Object.new.methods).to_set.freeze
|
|
92
155
|
|
|
93
156
|
SNAKE_CASE = /\A[[:digit:][:upper:]_]+\z/.freeze
|
|
94
157
|
|
|
158
|
+
GUARANTEED_INSTANCE_METHODS = %i[to_s to_i to_f to_a to_h].freeze
|
|
159
|
+
|
|
95
160
|
# @!method respond_to_nil_specific_method?(node)
|
|
96
161
|
def_node_matcher :respond_to_nil_specific_method?, <<~PATTERN
|
|
97
162
|
(csend _ :respond_to? (sym %NIL_SPECIFIC_METHODS))
|
|
@@ -111,15 +176,27 @@ module RuboCop
|
|
|
111
176
|
|
|
112
177
|
# rubocop:disable Metrics/AbcSize
|
|
113
178
|
def on_csend(node)
|
|
179
|
+
range = node.loc.dot
|
|
180
|
+
|
|
181
|
+
if infer_non_nil_receiver?
|
|
182
|
+
checker = Lint::Utils::NilReceiverChecker.new(node.receiver, additional_nil_methods)
|
|
183
|
+
|
|
184
|
+
if checker.cant_be_nil?
|
|
185
|
+
add_offense(range, message: MSG_NON_NIL) { |corrector| corrector.replace(range, '.') }
|
|
186
|
+
return
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
114
190
|
unless assume_receiver_instance_exists?(node.receiver)
|
|
115
|
-
return
|
|
191
|
+
return if !guaranteed_instance?(node.receiver) && !check?(node)
|
|
116
192
|
return if respond_to_nil_specific_method?(node)
|
|
117
193
|
end
|
|
118
194
|
|
|
119
|
-
range = node.loc.dot
|
|
120
195
|
add_offense(range) { |corrector| corrector.replace(range, '.') }
|
|
121
196
|
end
|
|
197
|
+
# rubocop:enable Metrics/AbcSize
|
|
122
198
|
|
|
199
|
+
# rubocop:disable Metrics/AbcSize
|
|
123
200
|
def on_or(node)
|
|
124
201
|
conversion_with_default?(node) do |send_node|
|
|
125
202
|
range = send_node.loc.dot.begin.join(node.source_range.end)
|
|
@@ -142,7 +219,20 @@ module RuboCop
|
|
|
142
219
|
receiver.self_type? || (receiver.literal? && !receiver.nil_type?)
|
|
143
220
|
end
|
|
144
221
|
|
|
222
|
+
def guaranteed_instance?(node)
|
|
223
|
+
receiver = if node.any_block_type?
|
|
224
|
+
node.send_node
|
|
225
|
+
else
|
|
226
|
+
node
|
|
227
|
+
end
|
|
228
|
+
return false unless receiver.send_type?
|
|
229
|
+
|
|
230
|
+
GUARANTEED_INSTANCE_METHODS.include?(receiver.method_name)
|
|
231
|
+
end
|
|
232
|
+
|
|
145
233
|
def check?(node)
|
|
234
|
+
return false unless allowed_method?(node.method_name)
|
|
235
|
+
|
|
146
236
|
parent = node.parent
|
|
147
237
|
return false unless parent
|
|
148
238
|
|
|
@@ -154,6 +244,15 @@ module RuboCop
|
|
|
154
244
|
def condition?(parent, node)
|
|
155
245
|
(parent.conditional? || parent.post_condition_loop?) && parent.condition == node
|
|
156
246
|
end
|
|
247
|
+
|
|
248
|
+
def infer_non_nil_receiver?
|
|
249
|
+
cop_config['InferNonNilReceiver']
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def additional_nil_methods
|
|
253
|
+
@additional_nil_methods ||=
|
|
254
|
+
Array(cop_config.fetch('AdditionalNilMethods', []).map(&:to_sym))
|
|
255
|
+
end
|
|
157
256
|
end
|
|
158
257
|
end
|
|
159
258
|
end
|