rubocop 1.65.1 → 1.75.6
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/LICENSE.txt +1 -1
- data/README.md +72 -72
- data/config/default.yml +299 -55
- data/config/internal_affairs.yml +31 -0
- data/config/obsoletion.yml +3 -1
- data/exe/rubocop +4 -3
- data/lib/rubocop/cached_data.rb +12 -4
- data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
- data/lib/rubocop/cli/command/execute_runner.rb +4 -4
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli/command/show_cops.rb +24 -2
- data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
- data/lib/rubocop/cli/command/version.rb +2 -2
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/comment_config.rb +3 -3
- data/lib/rubocop/config.rb +57 -11
- data/lib/rubocop/config_loader.rb +66 -17
- data/lib/rubocop/config_loader_resolver.rb +39 -14
- 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_validator.rb +27 -15
- data/lib/rubocop/cop/autocorrect_logic.rb +36 -19
- data/lib/rubocop/cop/base.rb +17 -3
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
- data/lib/rubocop/cop/bundler/gem_version.rb +1 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
- data/lib/rubocop/cop/cop.rb +8 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
- data/lib/rubocop/cop/documentation.rb +18 -1
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
- data/lib/rubocop/cop/generator.rb +6 -0
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
- data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +8 -4
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
- data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -2
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +230 -0
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
- data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
- data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
- data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
- data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
- data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +11 -2
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +23 -2
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
- data/lib/rubocop/cop/internal_affairs.rb +7 -0
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +6 -2
- data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +32 -13
- data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +9 -9
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
- data/lib/rubocop/cop/layout/def_end_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +4 -4
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +9 -12
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +30 -4
- data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +12 -8
- data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -10
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +8 -6
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +12 -12
- data/lib/rubocop/cop/layout/leading_comment_space.rb +83 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/line_length.rb +135 -16
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -4
- data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
- data/lib/rubocop/cop/layout/redundant_line_break.rb +19 -46
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -7
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
- data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +23 -21
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
- data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +7 -0
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +118 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
- data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
- data/lib/rubocop/cop/lint/boolean_symbol.rb +2 -2
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -1
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
- data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
- data/lib/rubocop/cop/lint/debugger.rb +3 -3
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +3 -2
- data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +46 -19
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +87 -0
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +29 -58
- data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
- data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
- data/lib/rubocop/cop/lint/empty_file.rb +0 -2
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -4
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -7
- data/lib/rubocop/cop/lint/float_comparison.rb +21 -17
- data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
- data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +13 -5
- data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +8 -14
- data/lib/rubocop/cop/lint/literal_as_condition.rb +118 -9
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +49 -8
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/missing_super.rb +2 -2
- data/lib/rubocop/cop/lint/mixed_case_range.rb +5 -8
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +10 -6
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
- data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -3
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +6 -11
- data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- 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 +13 -8
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
- 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/refinement_import_methods.rb +1 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
- data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
- data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
- data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +109 -41
- data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +8 -1
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +2 -2
- data/lib/rubocop/cop/lint/syntax.rb +4 -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/unescaped_bracket_in_regexp.rb +88 -0
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +52 -2
- data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
- data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
- data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +5 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +20 -11
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
- data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
- data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +78 -0
- data/lib/rubocop/cop/lint/useless_rescue.rb +2 -2
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
- data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
- data/lib/rubocop/cop/lint/void.rb +40 -14
- data/lib/rubocop/cop/message_annotator.rb +7 -3
- data/lib/rubocop/cop/metrics/block_length.rb +7 -5
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +15 -14
- data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +5 -2
- data/lib/rubocop/cop/metrics/method_length.rb +15 -6
- data/lib/rubocop/cop/metrics/module_length.rb +7 -6
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -4
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
- data/lib/rubocop/cop/mixin/alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
- data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
- data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +22 -12
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
- data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
- 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 +22 -11
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
- data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
- data/lib/rubocop/cop/mixin/line_length_help.rb +12 -6
- data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +7 -9
- data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
- data/lib/rubocop/cop/mixin/range_help.rb +15 -4
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +11 -5
- data/lib/rubocop/cop/mixin/string_help.rb +2 -2
- data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +21 -5
- data/lib/rubocop/cop/naming/accessor_method_name.rb +11 -6
- data/lib/rubocop/cop/naming/block_forwarding.rb +20 -16
- data/lib/rubocop/cop/naming/constant_name.rb +6 -7
- data/lib/rubocop/cop/naming/file_name.rb +0 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +12 -3
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +12 -13
- data/lib/rubocop/cop/naming/method_name.rb +64 -8
- data/lib/rubocop/cop/naming/predicate_name.rb +46 -2
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
- data/lib/rubocop/cop/naming/variable_name.rb +50 -6
- data/lib/rubocop/cop/naming/variable_number.rb +2 -3
- data/lib/rubocop/cop/offense.rb +4 -5
- data/lib/rubocop/cop/registry.rb +9 -6
- data/lib/rubocop/cop/security/compound_hash.rb +2 -0
- data/lib/rubocop/cop/security/yaml_load.rb +3 -2
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +96 -28
- data/lib/rubocop/cop/style/accessor_grouping.rb +29 -7
- data/lib/rubocop/cop/style/alias.rb +1 -1
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +94 -30
- data/lib/rubocop/cop/style/array_first_last.rb +18 -2
- data/lib/rubocop/cop/style/array_intersect.rb +42 -30
- data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +51 -20
- data/lib/rubocop/cop/style/case_like_if.rb +8 -11
- data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_compact.rb +10 -10
- data/lib/rubocop/cop/style/collection_methods.rb +2 -1
- data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +10 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +25 -2
- data/lib/rubocop/cop/style/comparable_between.rb +78 -0
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +40 -28
- data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
- data/lib/rubocop/cop/style/data_inheritance.rb +8 -1
- data/lib/rubocop/cop/style/dig_chain.rb +89 -0
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/double_negation.rb +4 -4
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
- data/lib/rubocop/cop/style/each_with_object.rb +2 -3
- data/lib/rubocop/cop/style/empty_else.rb +10 -7
- data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
- data/lib/rubocop/cop/style/empty_literal.rb +35 -22
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +150 -18
- data/lib/rubocop/cop/style/eval_with_location.rb +5 -5
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
- data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
- data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
- data/lib/rubocop/cop/style/fetch_env_var.rb +2 -1
- data/lib/rubocop/cop/style/file_null.rb +89 -0
- data/lib/rubocop/cop/style/file_touch.rb +75 -0
- data/lib/rubocop/cop/style/float_division.rb +8 -4
- data/lib/rubocop/cop/style/for.rb +1 -1
- 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/global_vars.rb +1 -3
- data/lib/rubocop/cop/style/guard_clause.rb +20 -4
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +12 -8
- data/lib/rubocop/cop/style/hash_except.rb +35 -147
- data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
- data/lib/rubocop/cop/style/hash_slice.rb +80 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +11 -5
- 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 +26 -7
- data/lib/rubocop/cop/style/if_inside_else.rb +11 -15
- data/lib/rubocop/cop/style/if_unless_modifier.rb +25 -5
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +3 -4
- data/lib/rubocop/cop/style/if_with_semicolon.rb +60 -6
- data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +15 -12
- 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 +36 -0
- data/lib/rubocop/cop/style/it_block_parameter.rb +100 -0
- data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
- data/lib/rubocop/cop/style/lambda.rb +2 -1
- data/lib/rubocop/cop/style/lambda_call.rb +10 -4
- data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
- data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
- data/lib/rubocop/cop/style/map_into_array.rb +75 -14
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/map_to_set.rb +3 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +38 -23
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +10 -13
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_else.rb +2 -0
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
- data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
- data/lib/rubocop/cop/style/multiple_comparison.rb +53 -60
- data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
- data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -2
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
- data/lib/rubocop/cop/style/next.rb +44 -0
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +2 -2
- data/lib/rubocop/cop/style/object_then.rb +15 -15
- data/lib/rubocop/cop/style/one_line_conditional.rb +30 -5
- data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
- data/lib/rubocop/cop/style/operator_method_call.rb +25 -7
- data/lib/rubocop/cop/style/or_assignment.rb +3 -6
- data/lib/rubocop/cop/style/parallel_assignment.rb +14 -22
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +2 -2
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -3
- data/lib/rubocop/cop/style/raise_args.rb +15 -13
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
- data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +6 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +97 -24
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
- data/lib/rubocop/cop/style/redundant_each.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
- data/lib/rubocop/cop/style/redundant_format.rb +257 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +3 -3
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +56 -20
- data/lib/rubocop/cop/style/redundant_parentheses.rb +57 -27
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +8 -1
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/redundant_return.rb +2 -2
- data/lib/rubocop/cop/style/redundant_self.rb +9 -15
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
- data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
- data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
- data/lib/rubocop/cop/style/require_order.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +18 -4
- data/lib/rubocop/cop/style/return_nil.rb +2 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
- data/lib/rubocop/cop/style/safe_navigation.rb +123 -54
- data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +14 -8
- data/lib/rubocop/cop/style/self_assignment.rb +11 -17
- data/lib/rubocop/cop/style/semicolon.rb +2 -2
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
- data/lib/rubocop/cop/style/signal_exception.rb +2 -3
- data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +15 -4
- data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +42 -106
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +15 -15
- data/lib/rubocop/cop/style/string_literals.rb +1 -1
- data/lib/rubocop/cop/style/string_methods.rb +1 -1
- data/lib/rubocop/cop/style/struct_inheritance.rb +9 -2
- data/lib/rubocop/cop/style/super_arguments.rb +66 -19
- data/lib/rubocop/cop/style/swap_values.rb +4 -15
- data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +26 -5
- data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
- data/lib/rubocop/cop/style/trivial_accessors.rb +2 -2
- data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
- data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
- data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
- data/lib/rubocop/cop/team.rb +14 -3
- data/lib/rubocop/cop/util.rb +12 -5
- data/lib/rubocop/cop/utils/format_string.rb +10 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -3
- data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
- data/lib/rubocop/cop/variable_force.rb +5 -11
- data/lib/rubocop/cops_documentation_generator.rb +117 -53
- data/lib/rubocop/directive_comment.rb +45 -11
- data/lib/rubocop/ext/regexp_node.rb +0 -1
- data/lib/rubocop/file_finder.rb +9 -4
- data/lib/rubocop/formatter/disabled_config_formatter.rb +3 -2
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +70 -23
- data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
- data/lib/rubocop/lockfile.rb +6 -4
- data/lib/rubocop/lsp/diagnostic.rb +189 -0
- data/lib/rubocop/lsp/logger.rb +2 -2
- data/lib/rubocop/lsp/routes.rb +7 -23
- data/lib/rubocop/lsp/runtime.rb +19 -49
- data/lib/rubocop/lsp/server.rb +0 -3
- data/lib/rubocop/lsp/stdin_runner.rb +85 -0
- data/lib/rubocop/magic_comment.rb +11 -3
- data/lib/rubocop/options.rb +28 -12
- data/lib/rubocop/path_util.rb +15 -8
- data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
- data/lib/rubocop/plugin/load_error.rb +26 -0
- data/lib/rubocop/plugin/loader.rb +100 -0
- data/lib/rubocop/plugin/not_supported_error.rb +29 -0
- data/lib/rubocop/plugin.rb +46 -0
- data/lib/rubocop/rake_task.rb +4 -1
- data/lib/rubocop/remote_config.rb +5 -1
- data/lib/rubocop/result_cache.rb +15 -21
- data/lib/rubocop/rspec/cop_helper.rb +13 -1
- data/lib/rubocop/rspec/expect_offense.rb +7 -2
- data/lib/rubocop/rspec/shared_contexts.rb +40 -3
- data/lib/rubocop/rspec/support.rb +4 -2
- data/lib/rubocop/runner.rb +27 -13
- data/lib/rubocop/server/cache.rb +52 -11
- data/lib/rubocop/server/cli.rb +2 -2
- data/lib/rubocop/server/core.rb +1 -0
- data/lib/rubocop/target_finder.rb +7 -2
- data/lib/rubocop/target_ruby.rb +36 -17
- data/lib/rubocop/version.rb +54 -11
- data/lib/rubocop/yaml_duplication_checker.rb +20 -26
- data/lib/rubocop.rb +36 -2
- data/lib/ruby_lsp/rubocop/addon.rb +75 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
- metadata +83 -40
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -3,7 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks
|
6
|
+
# Checks for predicate method definitions that return `nil`.
|
7
|
+
# A predicate method should only return a boolean value.
|
7
8
|
#
|
8
9
|
# @safety
|
9
10
|
# Autocorrection is marked as unsafe because the change of the return value
|
@@ -31,6 +32,24 @@ module RuboCop
|
|
31
32
|
# do_something?
|
32
33
|
# end
|
33
34
|
#
|
35
|
+
# # bad
|
36
|
+
# def foo?
|
37
|
+
# if condition
|
38
|
+
# nil
|
39
|
+
# else
|
40
|
+
# true
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# def foo?
|
46
|
+
# if condition
|
47
|
+
# false
|
48
|
+
# else
|
49
|
+
# true
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
#
|
34
53
|
# @example AllowedMethods: ['foo?']
|
35
54
|
# # good
|
36
55
|
# def foo?
|
@@ -64,24 +83,25 @@ module RuboCop
|
|
64
83
|
return if allowed_method?(node.method_name) || matches_allowed_pattern?(node.method_name)
|
65
84
|
return unless (body = node.body)
|
66
85
|
|
67
|
-
body.each_descendant(:return)
|
68
|
-
register_offense(return_node, 'return false') if return_nil?(return_node)
|
69
|
-
end
|
70
|
-
|
71
|
-
return unless (nil_node = nil_node_at_the_end_of_method_body(body))
|
86
|
+
body.each_descendant(:return) { |return_node| handle_return(return_node) }
|
72
87
|
|
73
|
-
|
88
|
+
handle_implicit_return_values(body)
|
74
89
|
end
|
75
90
|
alias on_defs on_def
|
76
91
|
|
77
92
|
private
|
78
93
|
|
79
|
-
def
|
80
|
-
return
|
81
|
-
return
|
82
|
-
return unless
|
94
|
+
def last_node_of_type(node, type)
|
95
|
+
return unless node
|
96
|
+
return node if node_type?(node, type)
|
97
|
+
return unless node.begin_type?
|
98
|
+
return unless (last_child = node.children.last)
|
99
|
+
|
100
|
+
last_child if last_child.is_a?(AST::Node) && node_type?(last_child, type)
|
101
|
+
end
|
83
102
|
|
84
|
-
|
103
|
+
def node_type?(node, type)
|
104
|
+
node.type == type.to_sym
|
85
105
|
end
|
86
106
|
|
87
107
|
def register_offense(offense_node, replacement)
|
@@ -89,6 +109,28 @@ module RuboCop
|
|
89
109
|
corrector.replace(offense_node, replacement)
|
90
110
|
end
|
91
111
|
end
|
112
|
+
|
113
|
+
def handle_implicit_return_values(node)
|
114
|
+
handle_if(last_node_of_type(node, :if))
|
115
|
+
handle_nil(last_node_of_type(node, :nil))
|
116
|
+
end
|
117
|
+
|
118
|
+
def handle_return(return_node)
|
119
|
+
register_offense(return_node, 'return false') if return_nil?(return_node)
|
120
|
+
end
|
121
|
+
|
122
|
+
def handle_nil(nil_node)
|
123
|
+
return unless nil_node
|
124
|
+
|
125
|
+
register_offense(nil_node, 'false')
|
126
|
+
end
|
127
|
+
|
128
|
+
def handle_if(if_node)
|
129
|
+
return unless if_node
|
130
|
+
|
131
|
+
handle_implicit_return_values(if_node.if_branch)
|
132
|
+
handle_implicit_return_values(if_node.else_branch)
|
133
|
+
end
|
92
134
|
end
|
93
135
|
end
|
94
136
|
end
|
@@ -17,9 +17,14 @@ module RuboCop
|
|
17
17
|
# `foo&.bar` can start returning `nil` as well as what the method
|
18
18
|
# returns.
|
19
19
|
#
|
20
|
-
# The default for `MaxChainLength` is `2
|
20
|
+
# The default for `MaxChainLength` is `2`.
|
21
21
|
# We have limited the cop to not register an offense for method chains
|
22
|
-
# that exceed this option
|
22
|
+
# that exceed this option's value.
|
23
|
+
#
|
24
|
+
# NOTE: This cop will recognize offenses but not autocorrect code when the
|
25
|
+
# right hand side (RHS) of the `&&` statement is an `||` statement
|
26
|
+
# (eg. `foo && (foo.bar? || foo.baz?)`). It can be corrected
|
27
|
+
# manually by removing the `foo &&` and adding `&.` to each `foo` on the RHS.
|
23
28
|
#
|
24
29
|
# @safety
|
25
30
|
# Autocorrection is unsafe because if a value is `false`, the resulting
|
@@ -81,7 +86,7 @@ module RuboCop
|
|
81
86
|
# foo.baz = bar if foo
|
82
87
|
# foo.baz + bar if foo
|
83
88
|
# foo.bar > 2 if foo
|
84
|
-
class SafeNavigation < Base
|
89
|
+
class SafeNavigation < Base # rubocop:disable Metrics/ClassLength
|
85
90
|
include NilMethods
|
86
91
|
include RangeHelp
|
87
92
|
extend AutoCorrector
|
@@ -121,50 +126,127 @@ module RuboCop
|
|
121
126
|
}
|
122
127
|
PATTERN
|
123
128
|
|
129
|
+
# @!method and_with_rhs_or?(node)
|
130
|
+
def_node_matcher :and_with_rhs_or?, '(and _ {or (begin or)})'
|
131
|
+
|
124
132
|
# @!method not_nil_check?(node)
|
125
133
|
def_node_matcher :not_nil_check?, '(send (send $_ :nil?) :!)'
|
126
134
|
|
135
|
+
# @!method and_inside_begin?(node)
|
136
|
+
def_node_matcher :and_inside_begin?, '`(begin and ...)'
|
137
|
+
|
138
|
+
# @!method strip_begin(node)
|
139
|
+
def_node_matcher :strip_begin, '{ (begin $!begin) $!(begin) }'
|
140
|
+
|
127
141
|
def on_if(node)
|
128
142
|
return if allowed_if_condition?(node)
|
129
143
|
|
130
|
-
|
144
|
+
checked_variable, receiver, method_chain, _method = extract_parts_from_if(node)
|
145
|
+
return unless offending_node?(node, checked_variable, method_chain, receiver)
|
146
|
+
|
147
|
+
body = extract_if_body(node)
|
148
|
+
method_call = receiver.parent
|
149
|
+
|
150
|
+
removal_ranges = [begin_range(node, body), end_range(node, body)]
|
151
|
+
|
152
|
+
report_offense(node, method_chain, method_call, *removal_ranges) do |corrector|
|
153
|
+
corrector.insert_before(method_call.loc.dot, '&') unless method_call.safe_navigation?
|
154
|
+
end
|
131
155
|
end
|
132
156
|
|
133
|
-
def on_and(node)
|
134
|
-
|
157
|
+
def on_and(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
158
|
+
collect_and_clauses(node).each do |(lhs, lhs_operator_range), (rhs, _rhs_operator_range)|
|
159
|
+
lhs_not_nil_check = not_nil_check?(lhs)
|
160
|
+
lhs_receiver = lhs_not_nil_check || lhs
|
161
|
+
rhs_receiver = find_matching_receiver_invocation(strip_begin(rhs), lhs_receiver)
|
162
|
+
|
163
|
+
next if !cop_config['ConvertCodeThatCanStartToReturnNil'] && lhs_not_nil_check
|
164
|
+
next unless offending_node?(node, lhs_receiver, rhs, rhs_receiver)
|
165
|
+
|
166
|
+
# Since we are evaluating every clause in potentially a complex chain of `and` nodes,
|
167
|
+
# we need to ensure that there isn't an object check happening
|
168
|
+
lhs_method_chain = find_method_chain(lhs_receiver)
|
169
|
+
next unless lhs_method_chain == lhs_receiver || lhs_not_nil_check
|
170
|
+
|
171
|
+
report_offense(
|
172
|
+
node,
|
173
|
+
rhs, rhs_receiver,
|
174
|
+
range_with_surrounding_space(range: lhs.source_range, side: :right),
|
175
|
+
range_with_surrounding_space(range: lhs_operator_range, side: :right),
|
176
|
+
offense_range: range_between(lhs.source_range.begin_pos, rhs.source_range.end_pos)
|
177
|
+
) do |corrector|
|
178
|
+
corrector.replace(rhs_receiver, lhs_receiver.source)
|
179
|
+
end
|
180
|
+
ignore_node(node)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def report_offense(node, rhs, rhs_receiver, *removal_ranges, offense_range: node)
|
185
|
+
add_offense(offense_range) do |corrector|
|
186
|
+
next if ignored_node?(node)
|
187
|
+
|
188
|
+
# If the RHS is an `or` we cannot safely autocorrect because in order to remove
|
189
|
+
# the non-nil check we need to add safe-navs to all clauses where the receiver is used
|
190
|
+
next if and_with_rhs_or?(node)
|
191
|
+
|
192
|
+
removal_ranges.each { |range| corrector.remove(range) }
|
193
|
+
yield corrector if block_given?
|
194
|
+
|
195
|
+
handle_comments(corrector, node, rhs)
|
196
|
+
|
197
|
+
add_safe_nav_to_all_methods_in_chain(corrector, rhs_receiver, rhs)
|
198
|
+
end
|
135
199
|
end
|
136
200
|
|
137
201
|
private
|
138
202
|
|
139
|
-
def
|
140
|
-
|
141
|
-
return if receiver != checked_variable || receiver.nil?
|
142
|
-
return if use_var_only_in_unless_modifier?(node, checked_variable)
|
143
|
-
return if chain_length(method_chain, method) > max_chain_length
|
144
|
-
return if unsafe_method_used?(method_chain, method)
|
145
|
-
return if method_chain.method?(:empty?)
|
203
|
+
def find_method_chain(node)
|
204
|
+
return node unless node&.parent&.call_type?
|
146
205
|
|
147
|
-
|
206
|
+
find_method_chain(node.parent)
|
148
207
|
end
|
149
208
|
|
150
|
-
def
|
151
|
-
|
209
|
+
def collect_and_clauses(node)
|
210
|
+
# Collect the lhs, operator and rhs of all `and` nodes
|
211
|
+
# `and` nodes can be nested and can contain `begin` nodes
|
212
|
+
# This gives us a source-ordered list of clauses that is then used to look
|
213
|
+
# for matching receivers as well as operator locations for offense and corrections
|
214
|
+
node.each_descendant(:and)
|
215
|
+
.inject(and_parts(node)) { |nodes, and_node| concat_nodes(nodes, and_node) }
|
216
|
+
.sort_by { |a| a.is_a?(RuboCop::AST::Node) ? a.source_range.begin_pos : a.begin_pos }
|
217
|
+
.each_slice(2)
|
218
|
+
.each_cons(2)
|
152
219
|
end
|
153
220
|
|
154
|
-
def
|
155
|
-
|
156
|
-
method_call = method_call(node)
|
221
|
+
def concat_nodes(nodes, and_node)
|
222
|
+
return nodes if and_node.each_ancestor(:block).any?
|
157
223
|
|
158
|
-
|
159
|
-
|
160
|
-
corrector.insert_before(method_call.loc.dot, '&') unless method_call.safe_navigation?
|
161
|
-
handle_comments(corrector, node, method_call)
|
224
|
+
nodes.concat(and_parts(and_node))
|
225
|
+
end
|
162
226
|
|
163
|
-
|
227
|
+
def and_parts(node)
|
228
|
+
parts = [node.loc.operator]
|
229
|
+
parts << node.rhs unless and_inside_begin?(node.rhs)
|
230
|
+
parts << node.lhs unless node.lhs.and_type? || and_inside_begin?(node.lhs)
|
231
|
+
parts
|
164
232
|
end
|
165
233
|
|
166
|
-
def
|
167
|
-
if
|
234
|
+
def offending_node?(node, lhs_receiver, rhs, rhs_receiver) # rubocop:disable Metrics/CyclomaticComplexity
|
235
|
+
return false if !matching_nodes?(lhs_receiver, rhs_receiver) || rhs_receiver.nil?
|
236
|
+
return false if use_var_only_in_unless_modifier?(node, lhs_receiver)
|
237
|
+
return false if chain_length(rhs, rhs_receiver) > max_chain_length
|
238
|
+
return false if unsafe_method_used?(rhs, rhs_receiver.parent)
|
239
|
+
return false if rhs.send_type? && rhs.method?(:empty?)
|
240
|
+
|
241
|
+
true
|
242
|
+
end
|
243
|
+
|
244
|
+
def use_var_only_in_unless_modifier?(node, variable)
|
245
|
+
node.if_type? && node.unless? && !method_called?(variable)
|
246
|
+
end
|
247
|
+
|
248
|
+
def extract_if_body(node)
|
249
|
+
if node.ternary?
|
168
250
|
node.branches.find { |branch| !branch.nil_type? }
|
169
251
|
else
|
170
252
|
node.node_parts[1]
|
@@ -201,20 +283,6 @@ module RuboCop
|
|
201
283
|
node.else? || node.elsif?
|
202
284
|
end
|
203
285
|
|
204
|
-
def method_call(node)
|
205
|
-
_checked_variable, matching_receiver, = extract_parts(node)
|
206
|
-
matching_receiver.parent
|
207
|
-
end
|
208
|
-
|
209
|
-
def extract_parts(node)
|
210
|
-
case node.type
|
211
|
-
when :if
|
212
|
-
extract_parts_from_if(node)
|
213
|
-
when :and
|
214
|
-
extract_parts_from_and(node)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
286
|
def extract_parts_from_if(node)
|
219
287
|
variable, receiver =
|
220
288
|
if node.ternary?
|
@@ -230,16 +298,6 @@ module RuboCop
|
|
230
298
|
[checked_variable, matching_receiver, receiver, method]
|
231
299
|
end
|
232
300
|
|
233
|
-
def extract_parts_from_and(node)
|
234
|
-
checked_variable, rhs = *node
|
235
|
-
if cop_config['ConvertCodeThatCanStartToReturnNil']
|
236
|
-
checked_variable = not_nil_check?(checked_variable) || checked_variable
|
237
|
-
end
|
238
|
-
|
239
|
-
checked_variable, matching_receiver, method = extract_common_parts(rhs, checked_variable)
|
240
|
-
[checked_variable, matching_receiver, rhs, method]
|
241
|
-
end
|
242
|
-
|
243
301
|
def extract_common_parts(method_chain, checked_variable)
|
244
302
|
matching_receiver = find_matching_receiver_invocation(method_chain, checked_variable)
|
245
303
|
|
@@ -249,17 +307,27 @@ module RuboCop
|
|
249
307
|
end
|
250
308
|
|
251
309
|
def find_matching_receiver_invocation(method_chain, checked_variable)
|
252
|
-
return nil unless method_chain
|
310
|
+
return nil unless method_chain.respond_to?(:receiver)
|
253
311
|
|
254
312
|
receiver = method_chain.receiver
|
255
313
|
|
256
|
-
return receiver if receiver
|
314
|
+
return receiver if matching_nodes?(receiver, checked_variable)
|
257
315
|
|
258
316
|
find_matching_receiver_invocation(receiver, checked_variable)
|
259
317
|
end
|
260
318
|
|
319
|
+
def matching_nodes?(left, right)
|
320
|
+
left == right || matching_call_nodes?(left, right)
|
321
|
+
end
|
322
|
+
|
323
|
+
def matching_call_nodes?(left, right)
|
324
|
+
return false unless left && right.respond_to?(:call_type?)
|
325
|
+
|
326
|
+
left.call_type? && right.call_type? && left.children == right.children
|
327
|
+
end
|
328
|
+
|
261
329
|
def chain_length(method_chain, method)
|
262
|
-
method.each_ancestor(:
|
330
|
+
method.each_ancestor(:call).inject(0) do |total, ancestor|
|
263
331
|
break total + 1 if ancestor == method_chain
|
264
332
|
|
265
333
|
total + 1
|
@@ -270,7 +338,7 @@ module RuboCop
|
|
270
338
|
return true if unsafe_method?(method)
|
271
339
|
|
272
340
|
method.each_ancestor(:send).any? do |ancestor|
|
273
|
-
break true unless config.
|
341
|
+
break true unless config.cop_enabled?('Lint/SafeNavigationChain')
|
274
342
|
|
275
343
|
break true if unsafe_method?(ancestor)
|
276
344
|
break true if nil_methods.include?(ancestor.method_name)
|
@@ -310,6 +378,7 @@ module RuboCop
|
|
310
378
|
start_method.each_ancestor do |ancestor|
|
311
379
|
break unless %i[send block].include?(ancestor.type)
|
312
380
|
next unless ancestor.send_type?
|
381
|
+
next if ancestor.safe_navigation?
|
313
382
|
|
314
383
|
corrector.insert_before(ancestor.loc.dot, '&')
|
315
384
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Enforces safe navigation chains length to not exceed the configured maximum.
|
7
|
+
# The longer the chain is, the harder it becomes to track what on it could be
|
8
|
+
# returning `nil`.
|
9
|
+
#
|
10
|
+
# There is a potential interplay with `Style/SafeNavigation` - if both are enabled
|
11
|
+
# and their settings are "incompatible", one of the cops will complain about what
|
12
|
+
# the other proposes.
|
13
|
+
#
|
14
|
+
# E.g. if `Style/SafeNavigation` is configured with `MaxChainLength: 2` (default)
|
15
|
+
# and this cop is configured with `Max: 1`, then for `foo.bar.baz if foo` the former
|
16
|
+
# will suggest `foo&.bar&.baz`, which is an offense for the latter.
|
17
|
+
#
|
18
|
+
# @example Max: 2 (default)
|
19
|
+
# # bad
|
20
|
+
# user&.address&.zip&.upcase
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# user&.address&.zip
|
24
|
+
# user.address.zip if user
|
25
|
+
#
|
26
|
+
class SafeNavigationChainLength < Base
|
27
|
+
MSG = 'Avoid safe navigation chains longer than %<max>d calls.'
|
28
|
+
|
29
|
+
def on_csend(node)
|
30
|
+
safe_navigation_chains = safe_navigation_chains(node)
|
31
|
+
return if safe_navigation_chains.size < max
|
32
|
+
|
33
|
+
add_offense(safe_navigation_chains.last, message: format(MSG, max: max))
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def safe_navigation_chains(node)
|
39
|
+
node.each_ancestor.with_object([]) do |parent, chains|
|
40
|
+
break chains unless parent.csend_type?
|
41
|
+
|
42
|
+
chains << parent
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def max
|
47
|
+
cop_config['Max'] || 2
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Looks for places where
|
6
|
+
# Looks for places where a subset of an Enumerable (array,
|
7
7
|
# range, set, etc.; see note below) is calculated based on a `Regexp`
|
8
8
|
# match, and suggests `grep` or `grep_v` instead.
|
9
9
|
#
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
# so the correction may not be actually equivalent.
|
28
28
|
#
|
29
29
|
# @example
|
30
|
-
# # bad (select or find_all)
|
30
|
+
# # bad (select, filter, or find_all)
|
31
31
|
# array.select { |x| x.match? /regexp/ }
|
32
32
|
# array.select { |x| /regexp/.match?(x) }
|
33
33
|
# array.select { |x| x =~ /regexp/ }
|
@@ -47,9 +47,11 @@ module RuboCop
|
|
47
47
|
include RangeHelp
|
48
48
|
|
49
49
|
MSG = 'Prefer `%<replacement>s` to `%<original_method>s` with a regexp match.'
|
50
|
-
RESTRICT_ON_SEND = %i[select find_all reject].freeze
|
51
|
-
REPLACEMENTS = { select: 'grep', find_all: 'grep', reject: 'grep_v' }.freeze
|
52
|
-
OPPOSITE_REPLACEMENTS = {
|
50
|
+
RESTRICT_ON_SEND = %i[select filter find_all reject].freeze
|
51
|
+
REPLACEMENTS = { select: 'grep', filter: 'grep', find_all: 'grep', reject: 'grep_v' }.freeze
|
52
|
+
OPPOSITE_REPLACEMENTS = {
|
53
|
+
select: 'grep_v', filter: 'grep_v', find_all: 'grep_v', reject: 'grep'
|
54
|
+
}.freeze
|
53
55
|
REGEXP_METHODS = %i[match? =~ !~].to_set.freeze
|
54
56
|
|
55
57
|
# @!method regexp_match?(node)
|
@@ -57,6 +59,7 @@ module RuboCop
|
|
57
59
|
{
|
58
60
|
(block call (args (arg $_)) ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
59
61
|
(numblock call $1 ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
62
|
+
(itblock call $_ ${(send _ %REGEXP_METHODS _) match-with-lvasgn})
|
60
63
|
}
|
61
64
|
PATTERN
|
62
65
|
|
@@ -84,8 +87,9 @@ module RuboCop
|
|
84
87
|
}
|
85
88
|
PATTERN
|
86
89
|
|
87
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
90
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
88
91
|
def on_send(node)
|
92
|
+
return if target_ruby_version < 2.6 && node.method?(:filter)
|
89
93
|
return unless (block_node = node.block_node)
|
90
94
|
return if block_node.body&.begin_type?
|
91
95
|
return if receiver_allowed?(block_node.receiver)
|
@@ -99,7 +103,7 @@ module RuboCop
|
|
99
103
|
|
100
104
|
register_offense(node, block_node, regexp, replacement)
|
101
105
|
end
|
102
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
106
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
103
107
|
alias on_csend on_send
|
104
108
|
|
105
109
|
private
|
@@ -134,6 +138,7 @@ module RuboCop
|
|
134
138
|
return unless (block_arg_name, regexp_method_send_node = regexp_match?(block_node))
|
135
139
|
|
136
140
|
block_arg_name = :"_#{block_arg_name}" if block_node.numblock_type?
|
141
|
+
|
137
142
|
return unless calls_lvar?(regexp_method_send_node, block_arg_name)
|
138
143
|
|
139
144
|
regexp_method_send_node
|
@@ -147,7 +152,8 @@ module RuboCop
|
|
147
152
|
return node.child_nodes.first if node.match_with_lvasgn_type?
|
148
153
|
|
149
154
|
if node.receiver.lvar_type? &&
|
150
|
-
(block.
|
155
|
+
(block.type?(:numblock, :itblock) ||
|
156
|
+
node.receiver.source == block.first_argument.source)
|
151
157
|
node.first_argument
|
152
158
|
elsif node.first_argument.lvar_type?
|
153
159
|
node.receiver
|
@@ -37,33 +37,29 @@ module RuboCop
|
|
37
37
|
private
|
38
38
|
|
39
39
|
def check(node, var_type)
|
40
|
-
|
41
|
-
return unless rhs
|
40
|
+
return unless (rhs = node.expression)
|
42
41
|
|
43
|
-
if rhs.send_type?
|
44
|
-
check_send_node(node, rhs,
|
42
|
+
if rhs.send_type? && rhs.arguments.one?
|
43
|
+
check_send_node(node, rhs, node.name, var_type)
|
45
44
|
elsif rhs.operator_keyword?
|
46
|
-
check_boolean_node(node, rhs,
|
45
|
+
check_boolean_node(node, rhs, node.name, var_type)
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
50
49
|
def check_send_node(node, rhs, var_name, var_type)
|
51
|
-
|
52
|
-
return unless OPS.include?(method_name)
|
50
|
+
return unless OPS.include?(rhs.method_name)
|
53
51
|
|
54
52
|
target_node = s(var_type, var_name)
|
55
|
-
return unless receiver == target_node
|
53
|
+
return unless rhs.receiver == target_node
|
56
54
|
|
57
|
-
add_offense(node, message: format(MSG, method: method_name)) do |corrector|
|
55
|
+
add_offense(node, message: format(MSG, method: rhs.method_name)) do |corrector|
|
58
56
|
autocorrect(corrector, node)
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
62
60
|
def check_boolean_node(node, rhs, var_name, var_type)
|
63
|
-
first_operand, _second_operand = *rhs
|
64
|
-
|
65
61
|
target_node = s(var_type, var_name)
|
66
|
-
return unless
|
62
|
+
return unless rhs.lhs == target_node
|
67
63
|
|
68
64
|
operator = rhs.loc.operator.source
|
69
65
|
add_offense(node, message: format(MSG, method: operator)) do |corrector|
|
@@ -72,7 +68,7 @@ module RuboCop
|
|
72
68
|
end
|
73
69
|
|
74
70
|
def autocorrect(corrector, node)
|
75
|
-
|
71
|
+
rhs = node.expression
|
76
72
|
|
77
73
|
if rhs.send_type?
|
78
74
|
autocorrect_send_node(corrector, node, rhs)
|
@@ -82,13 +78,11 @@ module RuboCop
|
|
82
78
|
end
|
83
79
|
|
84
80
|
def autocorrect_send_node(corrector, node, rhs)
|
85
|
-
|
86
|
-
apply_autocorrect(corrector, node, rhs, method_name.to_s, args)
|
81
|
+
apply_autocorrect(corrector, node, rhs, rhs.method_name, rhs.first_argument)
|
87
82
|
end
|
88
83
|
|
89
84
|
def autocorrect_boolean_node(corrector, node, rhs)
|
90
|
-
|
91
|
-
apply_autocorrect(corrector, node, rhs, rhs.loc.operator.source, second_operand)
|
85
|
+
apply_autocorrect(corrector, node, rhs, rhs.loc.operator.source, rhs.rhs)
|
92
86
|
end
|
93
87
|
|
94
88
|
def apply_autocorrect(corrector, node, rhs, operator, new_rhs)
|
@@ -141,7 +141,7 @@ module RuboCop
|
|
141
141
|
|
142
142
|
def expressions_per_line(exprs)
|
143
143
|
# create a map matching lines to the number of expressions on them
|
144
|
-
exprs_lines = exprs.map(&:
|
144
|
+
exprs_lines = exprs.map(&:last_line)
|
145
145
|
exprs_lines.group_by(&:itself)
|
146
146
|
end
|
147
147
|
|
@@ -164,7 +164,7 @@ module RuboCop
|
|
164
164
|
|
165
165
|
ast = processed_source.ast
|
166
166
|
@range_nodes = ast.range_type? ? [ast] : []
|
167
|
-
@range_nodes.concat(ast.each_descendant(:
|
167
|
+
@range_nodes.concat(ast.each_descendant(:range).to_a)
|
168
168
|
end
|
169
169
|
end
|
170
170
|
end
|
@@ -68,7 +68,7 @@ module RuboCop
|
|
68
68
|
def on_send(node)
|
69
69
|
return if allow_send? && !node.method?(:public_send)
|
70
70
|
return unless (first_argument = node.first_argument)
|
71
|
-
return unless
|
71
|
+
return unless first_argument.type?(*STATIC_METHOD_NAME_NODE_TYPES)
|
72
72
|
|
73
73
|
offense_range = offense_range(node)
|
74
74
|
method_name = first_argument.value
|
@@ -83,6 +83,7 @@ module RuboCop
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
86
|
+
alias on_csend on_send
|
86
87
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
87
88
|
|
88
89
|
private
|
@@ -122,10 +122,9 @@ module RuboCop
|
|
122
122
|
def on_rescue(node)
|
123
123
|
return unless style == :semantic
|
124
124
|
|
125
|
-
|
126
|
-
check_scope(:raise, begin_node)
|
125
|
+
check_scope(:raise, node.body)
|
127
126
|
|
128
|
-
|
127
|
+
node.resbody_branches.each do |rescue_node|
|
129
128
|
check_scope(:fail, rescue_node)
|
130
129
|
allow(:raise, rescue_node)
|
131
130
|
end
|
@@ -33,22 +33,19 @@ module RuboCop
|
|
33
33
|
#
|
34
34
|
class SingleArgumentDig < Base
|
35
35
|
extend AutoCorrector
|
36
|
+
include DigHelp
|
36
37
|
|
37
38
|
MSG = 'Use `%<receiver>s[%<argument>s]` instead of `%<original>s`.'
|
38
39
|
RESTRICT_ON_SEND = %i[dig].freeze
|
39
40
|
IGNORED_ARGUMENT_TYPES = %i[block_pass forwarded_restarg forwarded_args hash].freeze
|
40
41
|
|
41
|
-
# @!method single_argument_dig?(node)
|
42
|
-
def_node_matcher :single_argument_dig?, <<~PATTERN
|
43
|
-
(send _ :dig $!splat)
|
44
|
-
PATTERN
|
45
|
-
|
46
42
|
def on_send(node)
|
47
43
|
return unless node.receiver
|
48
44
|
|
49
45
|
expression = single_argument_dig?(node)
|
50
46
|
return unless expression
|
51
47
|
return if IGNORED_ARGUMENT_TYPES.include?(expression.type)
|
48
|
+
return if ignore_dig_chain?(node)
|
52
49
|
|
53
50
|
receiver = node.receiver.source
|
54
51
|
argument = expression.source
|
@@ -63,6 +60,13 @@ module RuboCop
|
|
63
60
|
|
64
61
|
ignore_node(node)
|
65
62
|
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def ignore_dig_chain?(node)
|
67
|
+
dig_chain_enabled? &&
|
68
|
+
(dig?(node.receiver) || dig?(node.parent))
|
69
|
+
end
|
66
70
|
end
|
67
71
|
end
|
68
72
|
end
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
# parameters.
|
11
11
|
#
|
12
12
|
# Configuration option: Methods
|
13
|
-
# Should be set to use this cop. Array of hashes, where each key is the
|
13
|
+
# Should be set to use this cop. `Array` of hashes, where each key is the
|
14
14
|
# method name and value - array of argument names.
|
15
15
|
#
|
16
16
|
# @example Methods: [{reduce: %w[a b]}]
|