rubocop 1.66.0 → 1.72.1
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 +2 -2
- data/config/default.yml +160 -14
- data/config/internal_affairs.yml +11 -0
- 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/comment_config.rb +6 -10
- data/lib/rubocop/config.rb +21 -20
- data/lib/rubocop/config_loader.rb +62 -16
- data/lib/rubocop/config_loader_resolver.rb +36 -11
- data/lib/rubocop/config_validator.rb +25 -18
- data/lib/rubocop/cop/autocorrect_logic.rb +36 -19
- data/lib/rubocop/cop/base.rb +13 -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/parentheses_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
- 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/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 +229 -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_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 +7 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
- data/lib/rubocop/cop/internal_affairs.rb +6 -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 +3 -2
- data/lib/rubocop/cop/layout/class_structure.rb +9 -9
- 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 +2 -2
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -3
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +3 -3
- data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -5
- 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 -7
- 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 +6 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +11 -12
- data/lib/rubocop/cop/layout/leading_comment_space.rb +71 -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 +119 -4
- 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_operation_indentation.rb +2 -3
- data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
- data/lib/rubocop/cop/layout/redundant_line_break.rb +10 -41
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -3
- 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 +1 -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 +19 -20
- 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 +6 -0
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +4 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -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 +119 -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 +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +6 -0
- 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 +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +2 -1
- 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_regexp_character_class_element.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +87 -0
- 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 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +20 -9
- 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 +11 -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 +1 -0
- 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_super.rb +2 -2
- data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -6
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +9 -5
- 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 +1 -1
- 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 +1 -2
- 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/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- 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 +231 -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/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/shared_mutable_default.rb +65 -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/unescaped_bracket_in_regexp.rb +88 -0
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +51 -2
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
- 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 +4 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +74 -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 +2 -1
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
- 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 +8 -11
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +9 -9
- 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 +8 -1
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- 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 +2 -3
- 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/check_assignment.rb +4 -12
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +20 -10
- 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/dig_help.rb +27 -0
- data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -2
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
- data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
- data/lib/rubocop/cop/mixin/line_length_help.rb +5 -4
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -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 +3 -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 +1 -1
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
- data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -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 +11 -12
- data/lib/rubocop/cop/naming/predicate_name.rb +45 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
- data/lib/rubocop/cop/naming/variable_name.rb +3 -4
- data/lib/rubocop/cop/naming/variable_number.rb +2 -3
- data/lib/rubocop/cop/offense.rb +4 -5
- 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 +10 -2
- 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 +78 -22
- data/lib/rubocop/cop/style/array_first_last.rb +18 -2
- data/lib/rubocop/cop/style/array_intersect.rb +5 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +49 -19
- data/lib/rubocop/cop/style/case_like_if.rb +8 -11
- data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
- data/lib/rubocop/cop/style/collection_compact.rb +10 -10
- data/lib/rubocop/cop/style/collection_methods.rb +1 -1
- data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +9 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +17 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +26 -26
- data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
- data/lib/rubocop/cop/style/data_inheritance.rb +1 -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 +3 -3
- 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 +5 -2
- data/lib/rubocop/cop/style/empty_literal.rb +2 -2
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -14
- data/lib/rubocop/cop/style/eval_with_location.rb +2 -2
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
- data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
- data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
- 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 +0 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/global_vars.rb +1 -3
- data/lib/rubocop/cop/style/guard_clause.rb +16 -3
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +9 -6
- data/lib/rubocop/cop/style/hash_except.rb +35 -147
- data/lib/rubocop/cop/style/hash_slice.rb +80 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +8 -5
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -2
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -3
- data/lib/rubocop/cop/style/if_with_semicolon.rb +28 -6
- data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +6 -7
- data/lib/rubocop/cop/style/it_assignment.rb +36 -0
- data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
- data/lib/rubocop/cop/style/lambda.rb +1 -1
- data/lib/rubocop/cop/style/lambda_call.rb +3 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +3 -8
- data/lib/rubocop/cop/style/map_into_array.rb +61 -12
- 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 +32 -20
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -11
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -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 +1 -1
- data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
- data/lib/rubocop/cop/style/multiple_comparison.rb +52 -51
- 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/not.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +14 -15
- data/lib/rubocop/cop/style/one_line_conditional.rb +29 -4
- 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 +9 -18
- 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/proc.rb +1 -2
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +7 -5
- 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 +5 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +39 -24
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
- 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 +222 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +56 -17
- data/lib/rubocop/cop/style/redundant_parentheses.rb +38 -24
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
- 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 +8 -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_string_escape.rb +2 -2
- data/lib/rubocop/cop/style/require_order.rb +1 -1
- data/lib/rubocop/cop/style/rescue_modifier.rb +15 -4
- data/lib/rubocop/cop/style/return_nil.rb +1 -1
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
- data/lib/rubocop/cop/style/safe_navigation.rb +105 -51
- data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +10 -7
- 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 +12 -3
- data/lib/rubocop/cop/style/single_line_methods.rb +3 -4
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -5
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +14 -13
- 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 +1 -1
- data/lib/rubocop/cop/style/super_arguments.rb +65 -17
- data/lib/rubocop/cop/style/swap_values.rb +4 -15
- data/lib/rubocop/cop/style/ternary_parentheses.rb +26 -5
- data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- 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 +8 -1
- data/lib/rubocop/cop/util.rb +12 -5
- data/lib/rubocop/cop/utils/format_string.rb +7 -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/variable.rb +18 -2
- data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
- data/lib/rubocop/cop/variable_force.rb +4 -10
- data/lib/rubocop/cops_documentation_generator.rb +100 -51
- data/lib/rubocop/directive_comment.rb +44 -10
- data/lib/rubocop/file_finder.rb +9 -4
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- 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 +18 -48
- data/lib/rubocop/lsp/server.rb +0 -3
- data/lib/rubocop/lsp/stdin_runner.rb +83 -0
- data/lib/rubocop/magic_comment.rb +3 -3
- data/lib/rubocop/options.rb +28 -12
- data/lib/rubocop/path_util.rb +15 -8
- data/lib/rubocop/plugin/configuration_integrator.rb +141 -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 +39 -0
- data/lib/rubocop/rake_task.rb +4 -1
- data/lib/rubocop/result_cache.rb +13 -13
- data/lib/rubocop/rspec/cop_helper.rb +7 -0
- data/lib/rubocop/rspec/expect_offense.rb +7 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -1
- data/lib/rubocop/rspec/support.rb +1 -2
- data/lib/rubocop/runner.rb +22 -12
- data/lib/rubocop/server/cache.rb +39 -1
- data/lib/rubocop/server/cli.rb +2 -2
- data/lib/rubocop/server/core.rb +1 -0
- data/lib/rubocop/target_finder.rb +1 -0
- data/lib/rubocop/target_ruby.rb +28 -13
- data/lib/rubocop/version.rb +42 -6
- data/lib/rubocop/yaml_duplication_checker.rb +20 -26
- data/lib/rubocop.rb +29 -0
- data/lib/ruby_lsp/rubocop/addon.rb +75 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +47 -0
- metadata +75 -19
- 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
|
@@ -21,6 +21,11 @@ module RuboCop
|
|
21
21
|
# We have limited the cop to not register an offense for method chains
|
22
22
|
# that exceed this option's value.
|
23
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.
|
28
|
+
#
|
24
29
|
# @safety
|
25
30
|
# Autocorrection is unsafe because if a value is `false`, the resulting
|
26
31
|
# code will have different behavior or raise an error.
|
@@ -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,122 @@ 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
|
+
)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def report_offense(node, rhs, rhs_receiver, *removal_ranges, offense_range: node)
|
182
|
+
add_offense(offense_range) do |corrector|
|
183
|
+
# If the RHS is an `or` we cannot safely autocorrect because in order to remove
|
184
|
+
# the non-nil check we need to add safe-navs to all clauses where the receiver is used
|
185
|
+
next if and_with_rhs_or?(node)
|
186
|
+
|
187
|
+
removal_ranges.each { |range| corrector.remove(range) }
|
188
|
+
yield corrector if block_given?
|
189
|
+
|
190
|
+
handle_comments(corrector, node, rhs)
|
191
|
+
|
192
|
+
add_safe_nav_to_all_methods_in_chain(corrector, rhs_receiver, rhs)
|
193
|
+
end
|
135
194
|
end
|
136
195
|
|
137
196
|
private
|
138
197
|
|
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?)
|
198
|
+
def find_method_chain(node)
|
199
|
+
return node unless node&.parent&.call_type?
|
146
200
|
|
147
|
-
|
201
|
+
find_method_chain(node.parent)
|
148
202
|
end
|
149
203
|
|
150
|
-
def
|
151
|
-
|
204
|
+
def collect_and_clauses(node)
|
205
|
+
# Collect the lhs, operator and rhs of all `and` nodes
|
206
|
+
# `and` nodes can be nested and can contain `begin` nodes
|
207
|
+
# This gives us a source-ordered list of clauses that is then used to look
|
208
|
+
# for matching receivers as well as operator locations for offense and corrections
|
209
|
+
node.each_descendant(:and)
|
210
|
+
.inject(and_parts(node)) { |nodes, and_node| concat_nodes(nodes, and_node) }
|
211
|
+
.sort_by { |a| a.is_a?(RuboCop::AST::Node) ? a.source_range.begin_pos : a.begin_pos }
|
212
|
+
.each_slice(2)
|
213
|
+
.each_cons(2)
|
152
214
|
end
|
153
215
|
|
154
|
-
def
|
155
|
-
|
156
|
-
method_call = method_call(node)
|
216
|
+
def concat_nodes(nodes, and_node)
|
217
|
+
return nodes if and_node.each_ancestor(:block).any?
|
157
218
|
|
158
|
-
|
159
|
-
|
160
|
-
corrector.insert_before(method_call.loc.dot, '&') unless method_call.safe_navigation?
|
161
|
-
handle_comments(corrector, node, method_call)
|
219
|
+
nodes.concat(and_parts(and_node))
|
220
|
+
end
|
162
221
|
|
163
|
-
|
222
|
+
def and_parts(node)
|
223
|
+
parts = [node.loc.operator]
|
224
|
+
parts << node.rhs unless and_inside_begin?(node.rhs)
|
225
|
+
parts << node.lhs unless node.lhs.and_type? || and_inside_begin?(node.lhs)
|
226
|
+
parts
|
164
227
|
end
|
165
228
|
|
166
|
-
def
|
167
|
-
if
|
229
|
+
def offending_node?(node, lhs_receiver, rhs, rhs_receiver) # rubocop:disable Metrics/CyclomaticComplexity
|
230
|
+
return false if lhs_receiver != rhs_receiver || rhs_receiver.nil?
|
231
|
+
return false if use_var_only_in_unless_modifier?(node, lhs_receiver)
|
232
|
+
return false if chain_length(rhs, rhs_receiver) > max_chain_length
|
233
|
+
return false if unsafe_method_used?(rhs, rhs_receiver.parent)
|
234
|
+
return false if rhs.send_type? && rhs.method?(:empty?)
|
235
|
+
|
236
|
+
true
|
237
|
+
end
|
238
|
+
|
239
|
+
def use_var_only_in_unless_modifier?(node, variable)
|
240
|
+
node.if_type? && node.unless? && !method_called?(variable)
|
241
|
+
end
|
242
|
+
|
243
|
+
def extract_if_body(node)
|
244
|
+
if node.ternary?
|
168
245
|
node.branches.find { |branch| !branch.nil_type? }
|
169
246
|
else
|
170
247
|
node.node_parts[1]
|
@@ -201,20 +278,6 @@ module RuboCop
|
|
201
278
|
node.else? || node.elsif?
|
202
279
|
end
|
203
280
|
|
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
281
|
def extract_parts_from_if(node)
|
219
282
|
variable, receiver =
|
220
283
|
if node.ternary?
|
@@ -230,16 +293,6 @@ module RuboCop
|
|
230
293
|
[checked_variable, matching_receiver, receiver, method]
|
231
294
|
end
|
232
295
|
|
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
296
|
def extract_common_parts(method_chain, checked_variable)
|
244
297
|
matching_receiver = find_matching_receiver_invocation(method_chain, checked_variable)
|
245
298
|
|
@@ -249,7 +302,7 @@ module RuboCop
|
|
249
302
|
end
|
250
303
|
|
251
304
|
def find_matching_receiver_invocation(method_chain, checked_variable)
|
252
|
-
return nil unless method_chain
|
305
|
+
return nil unless method_chain.respond_to?(:receiver)
|
253
306
|
|
254
307
|
receiver = method_chain.receiver
|
255
308
|
|
@@ -259,7 +312,7 @@ module RuboCop
|
|
259
312
|
end
|
260
313
|
|
261
314
|
def chain_length(method_chain, method)
|
262
|
-
method.each_ancestor(:
|
315
|
+
method.each_ancestor(:call).inject(0) do |total, ancestor|
|
263
316
|
break total + 1 if ancestor == method_chain
|
264
317
|
|
265
318
|
total + 1
|
@@ -270,7 +323,7 @@ module RuboCop
|
|
270
323
|
return true if unsafe_method?(method)
|
271
324
|
|
272
325
|
method.each_ancestor(:send).any? do |ancestor|
|
273
|
-
break true unless config.
|
326
|
+
break true unless config.cop_enabled?('Lint/SafeNavigationChain')
|
274
327
|
|
275
328
|
break true if unsafe_method?(ancestor)
|
276
329
|
break true if nil_methods.include?(ancestor.method_name)
|
@@ -310,6 +363,7 @@ module RuboCop
|
|
310
363
|
start_method.each_ancestor do |ancestor|
|
311
364
|
break unless %i[send block].include?(ancestor.type)
|
312
365
|
next unless ancestor.send_type?
|
366
|
+
next if ancestor.safe_navigation?
|
313
367
|
|
314
368
|
corrector.insert_before(ancestor.loc.dot, '&')
|
315
369
|
|
@@ -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)
|
@@ -84,8 +86,9 @@ module RuboCop
|
|
84
86
|
}
|
85
87
|
PATTERN
|
86
88
|
|
87
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
89
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
88
90
|
def on_send(node)
|
91
|
+
return if target_ruby_version < 2.6 && node.method?(:filter)
|
89
92
|
return unless (block_node = node.block_node)
|
90
93
|
return if block_node.body&.begin_type?
|
91
94
|
return if receiver_allowed?(block_node.receiver)
|
@@ -99,7 +102,7 @@ module RuboCop
|
|
99
102
|
|
100
103
|
register_offense(node, block_node, regexp, replacement)
|
101
104
|
end
|
102
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
105
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
103
106
|
alias on_csend on_send
|
104
107
|
|
105
108
|
private
|
@@ -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]}]
|
@@ -6,8 +6,13 @@ module RuboCop
|
|
6
6
|
# Checks for single-line `do`...`end` block.
|
7
7
|
#
|
8
8
|
# In practice a single line `do`...`end` is autocorrected when `EnforcedStyle: semantic`
|
9
|
-
#
|
10
|
-
# preserve semantics and does not change it to `{`...`}` block.
|
9
|
+
# is configured for `Style/BlockDelimiters`. The autocorrection maintains the
|
10
|
+
# `do` ... `end` syntax to preserve semantics and does not change it to `{`...`}` block.
|
11
|
+
#
|
12
|
+
# NOTE: If `InspectBlocks` is set to `true` for `Layout/RedundantLineBreak`, blocks will
|
13
|
+
# be autocorrected to be on a single line if possible. This cop respects that configuration
|
14
|
+
# by not registering an offense if it would subsequently cause a
|
15
|
+
# `Layout/RedundantLineBreak` offense.
|
11
16
|
#
|
12
17
|
# @example
|
13
18
|
#
|
@@ -27,12 +32,14 @@ module RuboCop
|
|
27
32
|
#
|
28
33
|
class SingleLineDoEndBlock < Base
|
29
34
|
extend AutoCorrector
|
35
|
+
include CheckSingleLineSuitability
|
30
36
|
|
31
37
|
MSG = 'Prefer multiline `do`...`end` block.'
|
32
38
|
|
33
39
|
# rubocop:disable Metrics/AbcSize
|
34
40
|
def on_block(node)
|
35
41
|
return if !node.single_line? || node.braces?
|
42
|
+
return if single_line_blocks_preferred? && suitable_as_single_line?(node)
|
36
43
|
|
37
44
|
add_offense(node) do |corrector|
|
38
45
|
corrector.insert_after(do_line(node), "\n")
|
@@ -60,7 +67,9 @@ module RuboCop
|
|
60
67
|
end
|
61
68
|
end
|
62
69
|
|
63
|
-
def
|
70
|
+
def single_line_blocks_preferred?
|
71
|
+
@config.for_enabled_cop('Layout/RedundantLineBreak')['InspectBlocks']
|
72
|
+
end
|
64
73
|
end
|
65
74
|
end
|
66
75
|
end
|
@@ -68,7 +68,7 @@ module RuboCop
|
|
68
68
|
return false if body_node.parent.assignment_method? ||
|
69
69
|
NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES.include?(body_node.type)
|
70
70
|
|
71
|
-
!
|
71
|
+
!body_node.type?(:begin, :kwbegin)
|
72
72
|
end
|
73
73
|
|
74
74
|
def correct_to_multiline(corrector, node)
|
@@ -134,10 +134,9 @@ module RuboCop
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def disallow_endless_method_style?
|
137
|
-
|
138
|
-
return true unless endless_method_config['Enabled']
|
137
|
+
return true unless config.cop_enabled?('Style/EndlessMethod')
|
139
138
|
|
140
|
-
|
139
|
+
config.for_cop('Style/EndlessMethod')['EnforcedStyle'] == 'disallow'
|
141
140
|
end
|
142
141
|
end
|
143
142
|
end
|