rubocop 1.67.0 → 1.75.5
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 +4 -4
- data/config/default.yml +264 -47
- data/config/internal_affairs.yml +20 -0
- data/config/obsoletion.yml +3 -1
- data/lib/rubocop/cached_data.rb +12 -4
- data/lib/rubocop/cli/command/execute_runner.rb +4 -4
- 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 +2 -2
- data/lib/rubocop/config.rb +52 -10
- data/lib/rubocop/config_loader.rb +52 -9
- data/lib/rubocop/config_loader_resolver.rb +36 -10
- 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 +25 -14
- data/lib/rubocop/cop/autocorrect_logic.rb +36 -19
- data/lib/rubocop/cop/base.rb +7 -1
- 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/insecure_protocol_source.rb +0 -1
- 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/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_enabled.rb +85 -0
- 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 +1 -1
- 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_source_range.rb +3 -1
- 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 +13 -2
- data/lib/rubocop/cop/internal_affairs.rb +7 -16
- data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
- 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/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 +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 +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 +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_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 +8 -7
- data/lib/rubocop/cop/layout/leading_comment_space.rb +57 -2
- 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 +123 -4
- 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 +10 -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/array_literal_in_regexp.rb +118 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
- 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 +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_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 +2 -17
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
- 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 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
- data/lib/rubocop/cop/lint/float_comparison.rb +20 -14
- 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 +1 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
- 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 +24 -6
- 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 +1 -5
- 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 +12 -7
- 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 +5 -1
- 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 +1 -1
- 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/useless_access_modifier.rb +5 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
- 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 +2 -1
- 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 +16 -12
- data/lib/rubocop/cop/message_annotator.rb +7 -3
- data/lib/rubocop/cop/metrics/block_length.rb +1 -0
- 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 +9 -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 +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/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 +3 -2
- 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 +5 -4
- 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_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 +8 -3
- 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 +21 -5
- 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/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 +44 -0
- 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 +2 -3
- 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 +86 -28
- data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
- 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 +47 -28
- 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 +43 -25
- 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_methods.rb +2 -1
- data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +20 -3
- data/lib/rubocop/cop/style/comparable_between.rb +75 -0
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +39 -27
- data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
- 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 +4 -2
- data/lib/rubocop/cop/style/empty_literal.rb +5 -1
- 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 +4 -4
- 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 +17 -3
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +6 -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 +9 -3
- 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 +25 -6
- data/lib/rubocop/cop/style/if_inside_else.rb +10 -14
- data/lib/rubocop/cop/style/if_unless_modifier.rb +5 -5
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +3 -4
- data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -9
- 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 +1 -0
- 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/map_into_array.rb +11 -3
- 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 +27 -17
- 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 +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_memoization.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
- 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_parenthesized_calls.rb +1 -1
- 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/object_then.rb +15 -15
- data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
- data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
- data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
- 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 +2 -2
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- 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 +2 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +95 -23
- 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_line_continuation.rb +54 -18
- data/lib/rubocop/cop/style/redundant_parentheses.rb +56 -26
- 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 +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/rescue_modifier.rb +5 -3
- data/lib/rubocop/cop/style/return_nil.rb +2 -2
- data/lib/rubocop/cop/style/safe_navigation.rb +32 -5
- data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +5 -2
- data/lib/rubocop/cop/style/self_assignment.rb +11 -17
- data/lib/rubocop/cop/style/semicolon.rb +1 -1
- 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 +40 -106
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/string_concatenation.rb +15 -14
- 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/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 +25 -4
- 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 +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/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 +50 -25
- data/lib/rubocop/directive_comment.rb +45 -11
- data/lib/rubocop/ext/regexp_node.rb +0 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -2
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/pacman_formatter.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 -50
- data/lib/rubocop/lsp/server.rb +0 -2
- 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/result_cache.rb +13 -13
- data/lib/rubocop/rspec/cop_helper.rb +13 -1
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/rspec/shared_contexts.rb +38 -1
- data/lib/rubocop/rspec/support.rb +4 -2
- data/lib/rubocop/runner.rb +26 -15
- data/lib/rubocop/server/cache.rb +47 -11
- data/lib/rubocop/server/cli.rb +2 -2
- data/lib/rubocop/target_finder.rb +7 -2
- data/lib/rubocop/target_ruby.rb +17 -2
- data/lib/rubocop/version.rb +53 -12
- data/lib/rubocop.rb +32 -1
- data/lib/ruby_lsp/rubocop/addon.rb +75 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
- metadata +78 -16
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -151,7 +151,7 @@ module RuboCop
|
|
151
151
|
|
152
152
|
def frozen_string_literal_comment(processed_source)
|
153
153
|
processed_source.tokens.find do |token|
|
154
|
-
token.text.
|
154
|
+
MagicComment.parse(token.text).frozen_string_literal_specified?
|
155
155
|
end
|
156
156
|
end
|
157
157
|
|
@@ -189,8 +189,9 @@ module RuboCop
|
|
189
189
|
|
190
190
|
def enable_comment(corrector)
|
191
191
|
comment = frozen_string_literal_comment(processed_source)
|
192
|
+
replacement = MagicComment.parse(comment.text).new_frozen_string_literal(true)
|
192
193
|
|
193
|
-
corrector.replace(line_range(comment.line),
|
194
|
+
corrector.replace(line_range(comment.line), replacement)
|
194
195
|
end
|
195
196
|
|
196
197
|
def insert_comment(corrector)
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
8
8
|
# reassign (possibly to redirect some stream) constants in Ruby, you'll get
|
9
9
|
# an interpreter warning if you do so.
|
10
10
|
#
|
11
|
+
# Additionally, `$stdout/$stderr/$stdin` can safely be accessed in a Ractor because they
|
12
|
+
# are ractor-local, while `STDOUT/STDERR/STDIN` will raise `Ractor::IsolationError`.
|
13
|
+
#
|
11
14
|
# @safety
|
12
15
|
# Autocorrection is unsafe because `STDOUT` and `$stdout` may point to different
|
13
16
|
# objects, for example.
|
@@ -135,6 +135,7 @@ module RuboCop
|
|
135
135
|
on_def(node)
|
136
136
|
end
|
137
137
|
alias on_numblock on_block
|
138
|
+
alias on_itblock on_block
|
138
139
|
|
139
140
|
def on_if(node)
|
140
141
|
return if accepted_form?(node)
|
@@ -213,7 +214,7 @@ module RuboCop
|
|
213
214
|
if_branch = node.if_branch
|
214
215
|
else_branch = node.else_branch
|
215
216
|
|
216
|
-
corrector.replace(node.loc.begin, "\n") if node.
|
217
|
+
corrector.replace(node.loc.begin, "\n") if node.then?
|
217
218
|
|
218
219
|
if if_branch&.send_type? && heredoc?(if_branch.last_argument)
|
219
220
|
autocorrect_heredoc_argument(corrector, node, if_branch, else_branch, guard)
|
@@ -264,7 +265,7 @@ module RuboCop
|
|
264
265
|
|
265
266
|
def and_or_guard_clause?(guard_clause)
|
266
267
|
parent = guard_clause.parent
|
267
|
-
parent.
|
268
|
+
parent.operator_keyword?
|
268
269
|
end
|
269
270
|
|
270
271
|
def too_long_for_single_line?(node, example)
|
@@ -283,7 +284,8 @@ module RuboCop
|
|
283
284
|
end
|
284
285
|
|
285
286
|
def accepted_if?(node, ending)
|
286
|
-
return true if node.modifier_form? || node.ternary? || node.elsif_conditional?
|
287
|
+
return true if node.modifier_form? || node.ternary? || node.elsif_conditional? ||
|
288
|
+
assigned_lvar_used_in_if_branch?(node)
|
287
289
|
|
288
290
|
if ending
|
289
291
|
node.else?
|
@@ -292,6 +294,18 @@ module RuboCop
|
|
292
294
|
end
|
293
295
|
end
|
294
296
|
|
297
|
+
def assigned_lvar_used_in_if_branch?(node)
|
298
|
+
return false unless (if_branch = node.if_branch)
|
299
|
+
|
300
|
+
assigned_lvars_in_condition = node.condition.each_descendant(:lvasgn).map do |lvasgn|
|
301
|
+
lvar_name, = *lvasgn
|
302
|
+
lvar_name.to_s
|
303
|
+
end
|
304
|
+
used_lvars_in_branch = if_branch.each_descendant(:lvar).map(&:source) || []
|
305
|
+
|
306
|
+
(assigned_lvars_in_condition & used_lvars_in_branch).any?
|
307
|
+
end
|
308
|
+
|
295
309
|
def remove_whole_lines(corrector, range)
|
296
310
|
corrector.remove(range_by_whole_lines(range, include_final_newline: true))
|
297
311
|
end
|
@@ -111,8 +111,7 @@ module RuboCop
|
|
111
111
|
end
|
112
112
|
|
113
113
|
def requires_parens?(node)
|
114
|
-
(node.call_type? && node.arguments.any? && !node.parenthesized?) ||
|
115
|
-
node.or_type? || node.and_type?
|
114
|
+
(node.call_type? && node.arguments.any? && !node.parenthesized?) || node.operator_keyword?
|
116
115
|
end
|
117
116
|
|
118
117
|
def multi_argument(node)
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Checks for uses of `each_key` and `each_value` Hash methods.
|
6
|
+
# Checks for uses of `each_key` and `each_value` `Hash` methods.
|
7
7
|
#
|
8
8
|
# NOTE: If you have an array of two-element arrays, you can put
|
9
9
|
# parentheses around the block arguments to indicate that you're not
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
|
45
45
|
# @!method kv_each(node)
|
46
46
|
def_node_matcher :kv_each, <<~PATTERN
|
47
|
-
(
|
47
|
+
(any_block $(call (call _ ${:keys :values}) :each) ...)
|
48
48
|
PATTERN
|
49
49
|
|
50
50
|
# @!method each_arguments(node)
|
@@ -74,6 +74,7 @@ module RuboCop
|
|
74
74
|
check_unused_block_args(node, key, value)
|
75
75
|
end
|
76
76
|
alias on_numblock on_block
|
77
|
+
alias on_itblock on_block
|
77
78
|
|
78
79
|
# rubocop:disable Metrics/AbcSize
|
79
80
|
def check_unused_block_args(node, key, value)
|
@@ -128,8 +129,8 @@ module RuboCop
|
|
128
129
|
lvar_sources = node.body.each_descendant(:lvar).map(&:source)
|
129
130
|
|
130
131
|
if block_arg.mlhs_type?
|
131
|
-
block_arg.each_descendant(:arg, :restarg).all? do |
|
132
|
-
lvar_sources.none?(
|
132
|
+
block_arg.each_descendant(:arg, :restarg).all? do |descendant|
|
133
|
+
lvar_sources.none?(descendant.source.delete_prefix('*'))
|
133
134
|
end
|
134
135
|
else
|
135
136
|
lvar_sources.none?(block_arg.source.delete_prefix('*'))
|
@@ -162,10 +163,7 @@ module RuboCop
|
|
162
163
|
|
163
164
|
def use_array_converter_method_as_preceding?(node)
|
164
165
|
return false unless (preceding_method = node.children.first.children.first)
|
165
|
-
unless preceding_method.
|
166
|
-
preceding_method.block_type? || preceding_method.numblock_type?
|
167
|
-
return false
|
168
|
-
end
|
166
|
+
return false unless preceding_method.type?(:call, :any_block)
|
169
167
|
|
170
168
|
ARRAY_CONVERTER_METHODS.include?(preceding_method.method_name)
|
171
169
|
end
|
@@ -10,8 +10,10 @@ module RuboCop
|
|
10
10
|
# (`Hash#except` was added in Ruby 3.0.)
|
11
11
|
#
|
12
12
|
# For safe detection, it is limited to commonly used string and symbol comparisons
|
13
|
-
# when
|
14
|
-
#
|
13
|
+
# when using `==` or `!=`.
|
14
|
+
#
|
15
|
+
# This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
|
16
|
+
# modify the receiver.
|
15
17
|
#
|
16
18
|
# @safety
|
17
19
|
# This cop is unsafe because it cannot be guaranteed that the receiver
|
@@ -23,6 +25,9 @@ module RuboCop
|
|
23
25
|
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k == :bar }
|
24
26
|
# {foo: 1, bar: 2, baz: 3}.select {|k, v| k != :bar }
|
25
27
|
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| k != :bar }
|
28
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.eql?(:bar) }
|
29
|
+
#
|
30
|
+
# # bad
|
26
31
|
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].include?(k) }
|
27
32
|
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].include?(k) }
|
28
33
|
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| !%i[bar].include?(k) }
|
@@ -30,161 +35,44 @@ module RuboCop
|
|
30
35
|
# # good
|
31
36
|
# {foo: 1, bar: 2, baz: 3}.except(:bar)
|
32
37
|
#
|
38
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: false (default)
|
39
|
+
#
|
40
|
+
# # good
|
41
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
|
42
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.in?(%i[bar]) }
|
46
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !k.in?(%i[bar]) }
|
47
|
+
#
|
48
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: true
|
49
|
+
#
|
50
|
+
# # bad
|
51
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].exclude?(k) }
|
52
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].exclude?(k) }
|
53
|
+
#
|
54
|
+
# # bad
|
55
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k.in?(%i[bar]) }
|
56
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !k.in?(%i[bar]) }
|
57
|
+
#
|
58
|
+
# # good
|
59
|
+
# {foo: 1, bar: 2, baz: 3}.except(:bar)
|
60
|
+
#
|
33
61
|
class HashExcept < Base
|
34
|
-
include
|
62
|
+
include HashSubset
|
35
63
|
extend TargetRubyVersion
|
36
64
|
extend AutoCorrector
|
37
65
|
|
38
66
|
minimum_target_ruby_version 3.0
|
39
67
|
|
40
|
-
MSG = 'Use `%<prefer>s` instead.'
|
41
|
-
RESTRICT_ON_SEND = %i[reject select filter].freeze
|
42
|
-
|
43
|
-
# @!method bad_method_with_poro?(node)
|
44
|
-
def_node_matcher :bad_method_with_poro?, <<~PATTERN
|
45
|
-
(block
|
46
|
-
(call _ _)
|
47
|
-
(args
|
48
|
-
$(arg _)
|
49
|
-
(arg _))
|
50
|
-
{
|
51
|
-
$(send
|
52
|
-
_ {:== :!= :eql? :include?} _)
|
53
|
-
(send
|
54
|
-
$(send
|
55
|
-
_ {:== :!= :eql? :include?} _) :!)
|
56
|
-
})
|
57
|
-
PATTERN
|
58
|
-
|
59
|
-
# @!method bad_method_with_active_support?(node)
|
60
|
-
def_node_matcher :bad_method_with_active_support?, <<~PATTERN
|
61
|
-
(block
|
62
|
-
(send _ _)
|
63
|
-
(args
|
64
|
-
$(arg _)
|
65
|
-
(arg _))
|
66
|
-
{
|
67
|
-
$(send
|
68
|
-
_ {:== :!= :eql? :in? :include? :exclude?} _)
|
69
|
-
(send
|
70
|
-
$(send
|
71
|
-
_ {:== :!= :eql? :in? :include? :exclude?} _) :!)
|
72
|
-
})
|
73
|
-
PATTERN
|
74
|
-
|
75
|
-
def on_send(node)
|
76
|
-
method_name = node.method_name
|
77
|
-
block = node.parent
|
78
|
-
return unless bad_method?(method_name, block) && semantically_except_method?(node, block)
|
79
|
-
|
80
|
-
except_key = except_key(block)
|
81
|
-
return if except_key.nil? || !safe_to_register_offense?(block, except_key)
|
82
|
-
|
83
|
-
range = offense_range(node)
|
84
|
-
preferred_method = "except(#{except_key_source(except_key)})"
|
85
|
-
|
86
|
-
add_offense(range, message: format(MSG, prefer: preferred_method)) do |corrector|
|
87
|
-
corrector.replace(range, preferred_method)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
alias on_csend on_send
|
91
|
-
|
92
68
|
private
|
93
69
|
|
94
|
-
|
95
|
-
|
96
|
-
if active_support_extensions_enabled?
|
97
|
-
bad_method_with_active_support?(block) do |key_arg, send_node|
|
98
|
-
if send_node.method?(:in?) && send_node.receiver&.source != key_arg.source
|
99
|
-
return false
|
100
|
-
end
|
101
|
-
return true if !send_node.method?(:include?) && !send_node.method?(:exclude?)
|
102
|
-
|
103
|
-
send_node.first_argument&.source == key_arg.source
|
104
|
-
end
|
105
|
-
else
|
106
|
-
bad_method_with_poro?(block) do |key_arg, send_node|
|
107
|
-
return false if method_name == :reject && block.body.method?(:!)
|
108
|
-
|
109
|
-
!send_node.method?(:include?) || send_node.first_argument&.source == key_arg.source
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
114
|
-
|
115
|
-
def semantically_except_method?(send, block)
|
116
|
-
body = block.body
|
117
|
-
|
118
|
-
negated = body.method?('!')
|
119
|
-
body = body.receiver if negated
|
120
|
-
|
121
|
-
case send.method_name
|
122
|
-
when :reject
|
123
|
-
body.method?('==') || body.method?('eql?') || included?(negated, body)
|
124
|
-
when :select, :filter
|
125
|
-
body.method?('!=') || not_included?(negated, body)
|
126
|
-
else
|
127
|
-
false
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def included?(negated, body)
|
132
|
-
body.method?('include?') || body.method?('in?') || (negated && body.method?('exclude?'))
|
133
|
-
end
|
134
|
-
|
135
|
-
def not_included?(negated, body)
|
136
|
-
body.method?('exclude?') || (negated && (body.method?('include?') || body.method?('in?')))
|
137
|
-
end
|
138
|
-
|
139
|
-
def safe_to_register_offense?(block, except_key)
|
140
|
-
extracted = extract_body_if_negated(block.body)
|
141
|
-
if extracted.method?('in?') || extracted.method?('include?') ||
|
142
|
-
extracted.method?('exclude?')
|
143
|
-
return true
|
144
|
-
end
|
145
|
-
return true if block.body.method?('eql?')
|
146
|
-
|
147
|
-
except_key.sym_type? || except_key.str_type?
|
148
|
-
end
|
149
|
-
|
150
|
-
def extract_body_if_negated(body)
|
151
|
-
return body unless body.method?('!')
|
152
|
-
|
153
|
-
body.receiver
|
154
|
-
end
|
155
|
-
|
156
|
-
def except_key_source(key)
|
157
|
-
if key.array_type?
|
158
|
-
key = if key.percent_literal?
|
159
|
-
key.each_value.map { |v| decorate_source(v) }
|
160
|
-
else
|
161
|
-
key.each_value.map(&:source)
|
162
|
-
end
|
163
|
-
return key.join(', ')
|
164
|
-
end
|
165
|
-
|
166
|
-
key.literal? ? key.source : "*#{key.source}"
|
167
|
-
end
|
168
|
-
|
169
|
-
def decorate_source(value)
|
170
|
-
return ":\"#{value.source}\"" if value.dsym_type?
|
171
|
-
return "\"#{value.source}\"" if value.dstr_type?
|
172
|
-
return ":#{value.source}" if value.sym_type?
|
173
|
-
|
174
|
-
"'#{value.source}'"
|
175
|
-
end
|
176
|
-
|
177
|
-
def except_key(node)
|
178
|
-
key_argument = node.argument_list.first.source
|
179
|
-
body = extract_body_if_negated(node.body)
|
180
|
-
lhs, _method_name, rhs = *body
|
181
|
-
return if [lhs, rhs].map(&:source).none?(key_argument)
|
182
|
-
|
183
|
-
[lhs, rhs].find { |operand| operand.source != key_argument }
|
70
|
+
def semantically_subset_method?(node)
|
71
|
+
semantically_except_method?(node)
|
184
72
|
end
|
185
73
|
|
186
|
-
def
|
187
|
-
|
74
|
+
def preferred_method_name
|
75
|
+
'except'
|
188
76
|
end
|
189
77
|
end
|
190
78
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Use `Hash#dig` instead of chaining potentially null `fetch` calls.
|
7
|
+
#
|
8
|
+
# When `fetch(identifier, nil)` calls are chained on a hash, the expectation
|
9
|
+
# is that each step in the chain returns either `nil` or another hash,
|
10
|
+
# and in both cases, these can be simplified with a single call to `dig` with
|
11
|
+
# multiple arguments.
|
12
|
+
#
|
13
|
+
# If the 2nd parameter is `{}` or `Hash.new`, an offense will also be registered,
|
14
|
+
# as long as the final call in the chain is a nil value. If a non-nil value is given,
|
15
|
+
# the chain will not be registered as an offense, as the default value cannot be safely
|
16
|
+
# given with `dig`.
|
17
|
+
#
|
18
|
+
# NOTE: See `Style/DigChain` for replacing chains of `dig` calls with
|
19
|
+
# a single method call.
|
20
|
+
#
|
21
|
+
# @safety
|
22
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
23
|
+
# is a `Hash` or that `fetch` or `dig` have the expected standard implementation.
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# # bad
|
27
|
+
# hash.fetch('foo', nil)&.fetch('bar', nil)
|
28
|
+
#
|
29
|
+
# # bad
|
30
|
+
# # earlier members of the chain can return `{}` as long as the final `fetch`
|
31
|
+
# # has `nil` as a default value
|
32
|
+
# hash.fetch('foo', {}).fetch('bar', nil)
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
# hash.dig('foo', 'bar')
|
36
|
+
#
|
37
|
+
# # ok - not handled by the cop since the final `fetch` value is non-nil
|
38
|
+
# hash.fetch('foo', {}).fetch('bar', {})
|
39
|
+
#
|
40
|
+
class HashFetchChain < Base
|
41
|
+
extend AutoCorrector
|
42
|
+
extend TargetRubyVersion
|
43
|
+
|
44
|
+
MSG = 'Use `%<replacement>s` instead.'
|
45
|
+
RESTRICT_ON_SEND = %i[fetch].freeze
|
46
|
+
|
47
|
+
minimum_target_ruby_version 2.3
|
48
|
+
|
49
|
+
# @!method diggable?(node)
|
50
|
+
def_node_matcher :diggable?, <<~PATTERN
|
51
|
+
(call _ :fetch $_arg {nil (hash) (send (const {nil? cbase} :Hash) :new)})
|
52
|
+
PATTERN
|
53
|
+
|
54
|
+
def on_send(node)
|
55
|
+
return if ignored_node?(node)
|
56
|
+
return if last_fetch_non_nil?(node)
|
57
|
+
|
58
|
+
last_replaceable_node, arguments = inspect_chain(node)
|
59
|
+
return unless last_replaceable_node
|
60
|
+
return unless arguments.size > 1
|
61
|
+
|
62
|
+
range = last_replaceable_node.selector.join(node.loc.end)
|
63
|
+
replacement = replacement(arguments)
|
64
|
+
message = format(MSG, replacement: replacement)
|
65
|
+
|
66
|
+
add_offense(range, message: message) do |corrector|
|
67
|
+
corrector.replace(range, replacement)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
alias on_csend on_send
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def last_fetch_non_nil?(node)
|
75
|
+
# When chaining `fetch` methods, `fetch(x, {})` is acceptable within
|
76
|
+
# the chain, as long as the last method in the chain has a `nil`
|
77
|
+
# default value.
|
78
|
+
|
79
|
+
return false unless node.method?(:fetch)
|
80
|
+
|
81
|
+
!node.last_argument&.nil_type?
|
82
|
+
end
|
83
|
+
|
84
|
+
def inspect_chain(node)
|
85
|
+
arguments = []
|
86
|
+
|
87
|
+
while (arg = diggable?(node))
|
88
|
+
arguments.unshift(arg)
|
89
|
+
ignore_node(node)
|
90
|
+
last_replaceable_node = node
|
91
|
+
node = node.receiver
|
92
|
+
end
|
93
|
+
|
94
|
+
[last_replaceable_node, arguments]
|
95
|
+
end
|
96
|
+
|
97
|
+
def replacement(arguments)
|
98
|
+
values = arguments.map(&:source).join(', ')
|
99
|
+
"dig(#{values})"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for usages of `Hash#reject`, `Hash#select`, and `Hash#filter` methods
|
7
|
+
# that can be replaced with `Hash#slice` method.
|
8
|
+
#
|
9
|
+
# This cop should only be enabled on Ruby version 2.5 or higher.
|
10
|
+
# (`Hash#slice` was added in Ruby 2.5.)
|
11
|
+
#
|
12
|
+
# For safe detection, it is limited to commonly used string and symbol comparisons
|
13
|
+
# when using `==` or `!=`.
|
14
|
+
#
|
15
|
+
# This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
|
16
|
+
# modify the receiver.
|
17
|
+
#
|
18
|
+
# @safety
|
19
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
20
|
+
# is a `Hash` or responds to the replacement method.
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
#
|
24
|
+
# # bad
|
25
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| k == :bar }
|
26
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| k != :bar }
|
27
|
+
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| k == :bar }
|
28
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| k.eql?(:bar) }
|
29
|
+
#
|
30
|
+
# # bad
|
31
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].include?(k) }
|
32
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].include?(k) }
|
33
|
+
# {foo: 1, bar: 2, baz: 3}.filter {|k, v| %i[bar].include?(k) }
|
34
|
+
#
|
35
|
+
# # good
|
36
|
+
# {foo: 1, bar: 2, baz: 3}.slice(:bar)
|
37
|
+
#
|
38
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: false (default)
|
39
|
+
#
|
40
|
+
# # good
|
41
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].exclude?(k) }
|
42
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].exclude?(k) }
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| k.in?(%i[bar]) }
|
46
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| !k.in?(%i[bar]) }
|
47
|
+
#
|
48
|
+
# @example AllCops:ActiveSupportExtensionsEnabled: true
|
49
|
+
#
|
50
|
+
# # bad
|
51
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].exclude?(k) }
|
52
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].exclude?(k) }
|
53
|
+
#
|
54
|
+
# # bad
|
55
|
+
# {foo: 1, bar: 2, baz: 3}.select {|k, v| k.in?(%i[bar]) }
|
56
|
+
# {foo: 1, bar: 2, baz: 3}.reject {|k, v| !k.in?(%i[bar]) }
|
57
|
+
#
|
58
|
+
# # good
|
59
|
+
# {foo: 1, bar: 2, baz: 3}.slice(:bar)
|
60
|
+
#
|
61
|
+
class HashSlice < Base
|
62
|
+
include HashSubset
|
63
|
+
extend TargetRubyVersion
|
64
|
+
extend AutoCorrector
|
65
|
+
|
66
|
+
minimum_target_ruby_version 2.5
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def semantically_subset_method?(node)
|
71
|
+
semantically_slice_method?(node)
|
72
|
+
end
|
73
|
+
|
74
|
+
def preferred_method_name
|
75
|
+
'slice'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -76,6 +76,9 @@ module RuboCop
|
|
76
76
|
# # good
|
77
77
|
# {foo:, bar:}
|
78
78
|
#
|
79
|
+
# # good - allowed to mix syntaxes
|
80
|
+
# {foo:, bar: baz}
|
81
|
+
#
|
79
82
|
# @example EnforcedShorthandSyntax: never
|
80
83
|
#
|
81
84
|
# # bad
|
@@ -137,6 +140,7 @@ module RuboCop
|
|
137
140
|
MSG_19 = 'Use the new Ruby 1.9 hash syntax.'
|
138
141
|
MSG_NO_MIXED_KEYS = "Don't mix styles in the same hash."
|
139
142
|
MSG_HASH_ROCKETS = 'Use hash rockets syntax.'
|
143
|
+
NO_MIXED_KEYS_STYLES = %i[ruby19_no_mixed_keys no_mixed_keys].freeze
|
140
144
|
|
141
145
|
def on_hash(node)
|
142
146
|
pairs = node.pairs
|
@@ -196,7 +200,7 @@ module RuboCop
|
|
196
200
|
def autocorrect(corrector, node)
|
197
201
|
if style == :hash_rockets || force_hash_rockets?(node.parent.pairs)
|
198
202
|
autocorrect_hash_rockets(corrector, node)
|
199
|
-
elsif style
|
203
|
+
elsif NO_MIXED_KEYS_STYLES.include?(style)
|
200
204
|
autocorrect_no_mixed_keys(corrector, node)
|
201
205
|
else
|
202
206
|
autocorrect_ruby19(corrector, node)
|
@@ -208,7 +212,7 @@ module RuboCop
|
|
208
212
|
end
|
209
213
|
|
210
214
|
def word_symbol_pair?(pair)
|
211
|
-
return false unless pair.key.
|
215
|
+
return false unless pair.key.type?(:sym, :dsym)
|
212
216
|
|
213
217
|
acceptable_19_syntax_symbol?(pair.key.source)
|
214
218
|
end
|
@@ -272,7 +276,9 @@ module RuboCop
|
|
272
276
|
end
|
273
277
|
|
274
278
|
def argument_without_space?(node)
|
275
|
-
node.argument?
|
279
|
+
return false if !node.argument? || !node.parent.loc.selector
|
280
|
+
|
281
|
+
node.source_range.begin_pos == node.parent.loc.selector.end_pos
|
276
282
|
end
|
277
283
|
|
278
284
|
def autocorrect_hash_rockets(corrector, pair_node)
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Looks for uses of
|
7
|
-
#
|
6
|
+
# Looks for uses of `+_.each_with_object({}) {...}+`,
|
7
|
+
# `+_.map {...}.to_h+`, and `+Hash[_.map {...}]+` that are actually just
|
8
8
|
# transforming the keys of a hash, and tries to use a simpler & faster
|
9
9
|
# call to `transform_keys` instead.
|
10
10
|
# It should only be enabled on Ruby version 2.5 or newer.
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# Looks for uses of
|
7
|
-
#
|
6
|
+
# Looks for uses of `+_.each_with_object({}) {...}+`,
|
7
|
+
# `+_.map {...}.to_h+`, and `+Hash[_.map {...}]+` that are actually just
|
8
8
|
# transforming the values of a hash, and tries to use a simpler & faster
|
9
9
|
# call to `transform_values` instead.
|
10
10
|
#
|
@@ -189,7 +189,7 @@ module RuboCop
|
|
189
189
|
end
|
190
190
|
end
|
191
191
|
|
192
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
192
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
193
193
|
def check_expressions(node, expressions, insert_position)
|
194
194
|
return if expressions.any?(&:nil?)
|
195
195
|
|
@@ -197,22 +197,41 @@ module RuboCop
|
|
197
197
|
|
198
198
|
expressions.each do |expression|
|
199
199
|
add_offense(expression) do |corrector|
|
200
|
-
next if node.if_type? && node.ternary?
|
200
|
+
next if node.if_type? && (node.ternary? || node.then?)
|
201
201
|
|
202
202
|
range = range_by_whole_lines(expression.source_range, include_final_newline: true)
|
203
203
|
corrector.remove(range)
|
204
204
|
next if inserted_expression
|
205
205
|
|
206
|
-
if
|
207
|
-
corrector
|
206
|
+
if node.parent&.assignment?
|
207
|
+
correct_assignment(corrector, node, expression, insert_position)
|
208
208
|
else
|
209
|
-
corrector
|
209
|
+
correct_no_assignment(corrector, node, expression, insert_position)
|
210
210
|
end
|
211
|
+
|
211
212
|
inserted_expression = true
|
212
213
|
end
|
213
214
|
end
|
214
215
|
end
|
215
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
216
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
217
|
+
|
218
|
+
def correct_assignment(corrector, node, expression, insert_position)
|
219
|
+
if insert_position == :after_condition
|
220
|
+
assignment = node.parent.source_range.with(end_pos: node.source_range.begin_pos)
|
221
|
+
corrector.remove(assignment)
|
222
|
+
corrector.insert_after(node, "\n#{assignment.source}#{expression.source}")
|
223
|
+
else
|
224
|
+
corrector.insert_before(node.parent, "#{expression.source}\n")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def correct_no_assignment(corrector, node, expression, insert_position)
|
229
|
+
if insert_position == :after_condition
|
230
|
+
corrector.insert_after(node, "\n#{expression.source}")
|
231
|
+
else
|
232
|
+
corrector.insert_before(node, "#{expression.source}\n")
|
233
|
+
end
|
234
|
+
end
|
216
235
|
|
217
236
|
def last_child_of_parent?(node)
|
218
237
|
return true unless (parent = node.parent)
|