rubocop 1.67.0 → 1.73.0
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 +168 -19
- data/config/internal_affairs.yml +16 -0
- 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/comment_config.rb +2 -2
- data/lib/rubocop/config.rb +17 -4
- data/lib/rubocop/config_loader.rb +48 -8
- data/lib/rubocop/config_loader_resolver.rb +35 -10
- data/lib/rubocop/config_validator.rb +19 -9
- 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 +4 -2
- 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 +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_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 +7 -1
- data/lib/rubocop/cop/internal_affairs.rb +6 -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/class_structure.rb +9 -9
- 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 +2 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +29 -4
- 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_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 +7 -7
- data/lib/rubocop/cop/layout/leading_comment_space.rb +44 -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/array_literal_in_regexp.rb +119 -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/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_methods.rb +0 -14
- 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_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/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 +105 -7
- 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_super.rb +2 -2
- data/lib/rubocop/cop/lint/mixed_case_range.rb +4 -7
- 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 +1 -5
- 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 +252 -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 +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/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 +1 -1
- 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/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 +80 -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 +14 -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/allowed_pattern.rb +4 -4
- 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 +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 +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -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 +3 -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 +15 -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/memoized_instance_variable_name.rb +11 -12
- 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 +63 -6
- data/lib/rubocop/cop/naming/variable_number.rb +2 -3
- data/lib/rubocop/cop/offense.rb +2 -3
- 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 +39 -23
- 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 +41 -24
- 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_methods.rb +1 -1
- data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +11 -1
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +25 -25
- 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 +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 +4 -2
- data/lib/rubocop/cop/style/empty_literal.rb +1 -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 +1 -1
- 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 +15 -2
- data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -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 +6 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +0 -1
- 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 +20 -9
- 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_call.rb +3 -2
- data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
- data/lib/rubocop/cop/style/map_into_array.rb +7 -2
- 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 +20 -13
- 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 +1 -1
- 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/not.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +14 -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 +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 +1 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +72 -23
- 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 +250 -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_line_continuation.rb +54 -15
- data/lib/rubocop/cop/style/redundant_parentheses.rb +36 -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/rescue_modifier.rb +2 -3
- data/lib/rubocop/cop/style/return_nil.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +14 -2
- data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
- data/lib/rubocop/cop/style/select_by_regexp.rb +1 -1
- 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 +12 -3
- 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 +4 -5
- 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 +65 -17
- data/lib/rubocop/cop/style/swap_values.rb +4 -15
- data/lib/rubocop/cop/style/ternary_parentheses.rb +25 -4
- 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_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 +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 +44 -23
- data/lib/rubocop/directive_comment.rb +44 -10
- 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 +17 -49
- data/lib/rubocop/lsp/server.rb +0 -2
- 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 +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 +9 -0
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/rspec/shared_contexts.rb +19 -1
- data/lib/rubocop/rspec/support.rb +2 -2
- data/lib/rubocop/runner.rb +21 -14
- data/lib/rubocop/server/cache.rb +35 -2
- data/lib/rubocop/server/cli.rb +2 -2
- data/lib/rubocop/target_finder.rb +1 -0
- data/lib/rubocop/target_ruby.rb +16 -1
- data/lib/rubocop/version.rb +41 -7
- data/lib/rubocop.rb +27 -1
- data/lib/ruby_lsp/rubocop/addon.rb +75 -0
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +47 -0
- metadata +73 -20
- data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for usage of `File.open` in append mode with empty block.
|
7
|
+
#
|
8
|
+
# Such a usage only creates a new file, but it doesn't update
|
9
|
+
# timestamps for an existing file, which might have been the intention.
|
10
|
+
#
|
11
|
+
# For example, for an existing file `foo.txt`:
|
12
|
+
#
|
13
|
+
# ruby -e "puts File.mtime('foo.txt')"
|
14
|
+
# # 2024-11-26 12:17:23 +0100
|
15
|
+
#
|
16
|
+
# ruby -e "File.open('foo.txt', 'a') {}"
|
17
|
+
#
|
18
|
+
# ruby -e "puts File.mtime('foo.txt')"
|
19
|
+
# # 2024-11-26 12:17:23 +0100 -> unchanged
|
20
|
+
#
|
21
|
+
# If the intention was to update timestamps, `FileUtils.touch('foo.txt')`
|
22
|
+
# should be used instead.
|
23
|
+
#
|
24
|
+
# @safety
|
25
|
+
# Autocorrection is unsafe for this cop because unlike `File.open`,
|
26
|
+
# `FileUtils.touch` updates an existing file's timestamps.
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# # bad
|
30
|
+
# File.open(filename, 'a') {}
|
31
|
+
# File.open(filename, 'a+') {}
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# FileUtils.touch(filename)
|
35
|
+
#
|
36
|
+
class FileTouch < Base
|
37
|
+
extend AutoCorrector
|
38
|
+
|
39
|
+
MSG = 'Use `FileUtils.touch(%<argument>s)` instead of `File.open` in ' \
|
40
|
+
'append mode with empty block.'
|
41
|
+
|
42
|
+
RESTRICT_ON_SEND = %i[open].freeze
|
43
|
+
|
44
|
+
APPEND_FILE_MODES = %w[a a+ ab a+b at a+t].to_set.freeze
|
45
|
+
|
46
|
+
# @!method file_open?(node)
|
47
|
+
def_node_matcher :file_open?, <<~PATTERN
|
48
|
+
(send
|
49
|
+
(const {nil? cbase} :File) :open
|
50
|
+
$(...)
|
51
|
+
(str %APPEND_FILE_MODES))
|
52
|
+
PATTERN
|
53
|
+
|
54
|
+
def on_send(node)
|
55
|
+
filename = file_open?(node)
|
56
|
+
parent = node.parent
|
57
|
+
|
58
|
+
return unless filename
|
59
|
+
return unless parent && empty_block?(parent)
|
60
|
+
|
61
|
+
message = format(MSG, argument: filename.source)
|
62
|
+
add_offense(parent, message: message) do |corrector|
|
63
|
+
corrector.replace(parent, "FileUtils.touch(#{filename.source})")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def empty_block?(node)
|
70
|
+
node.block_type? && !node.body
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -65,19 +65,23 @@ module RuboCop
|
|
65
65
|
|
66
66
|
# @!method right_coerce?(node)
|
67
67
|
def_node_matcher :right_coerce?, <<~PATTERN
|
68
|
-
(send _ :/
|
68
|
+
(send _ :/ #to_f_method?)
|
69
69
|
PATTERN
|
70
70
|
# @!method left_coerce?(node)
|
71
71
|
def_node_matcher :left_coerce?, <<~PATTERN
|
72
|
-
(send
|
72
|
+
(send #to_f_method? :/ _)
|
73
73
|
PATTERN
|
74
74
|
# @!method both_coerce?(node)
|
75
75
|
def_node_matcher :both_coerce?, <<~PATTERN
|
76
|
-
(send
|
76
|
+
(send #to_f_method? :/ #to_f_method?)
|
77
77
|
PATTERN
|
78
78
|
# @!method any_coerce?(node)
|
79
79
|
def_node_matcher :any_coerce?, <<~PATTERN
|
80
|
-
{(send _ :/
|
80
|
+
{(send _ :/ #to_f_method?) (send #to_f_method? :/ _)}
|
81
|
+
PATTERN
|
82
|
+
# @!method to_f_method?(node)
|
83
|
+
def_node_matcher :to_f_method?, <<~PATTERN
|
84
|
+
(send !nil? :to_f)
|
81
85
|
PATTERN
|
82
86
|
|
83
87
|
def on_send(node)
|
@@ -264,7 +264,7 @@ module RuboCop
|
|
264
264
|
|
265
265
|
def and_or_guard_clause?(guard_clause)
|
266
266
|
parent = guard_clause.parent
|
267
|
-
parent.
|
267
|
+
parent.operator_keyword?
|
268
268
|
end
|
269
269
|
|
270
270
|
def too_long_for_single_line?(node, example)
|
@@ -283,7 +283,8 @@ module RuboCop
|
|
283
283
|
end
|
284
284
|
|
285
285
|
def accepted_if?(node, ending)
|
286
|
-
return true if node.modifier_form? || node.ternary? || node.elsif_conditional?
|
286
|
+
return true if node.modifier_form? || node.ternary? || node.elsif_conditional? ||
|
287
|
+
assigned_lvar_used_in_if_branch?(node)
|
287
288
|
|
288
289
|
if ending
|
289
290
|
node.else?
|
@@ -292,6 +293,18 @@ module RuboCop
|
|
292
293
|
end
|
293
294
|
end
|
294
295
|
|
296
|
+
def assigned_lvar_used_in_if_branch?(node)
|
297
|
+
return false unless (if_branch = node.if_branch)
|
298
|
+
|
299
|
+
assigned_lvars_in_condition = node.condition.each_descendant(:lvasgn).map do |lvasgn|
|
300
|
+
lvar_name, = *lvasgn
|
301
|
+
lvar_name.to_s
|
302
|
+
end
|
303
|
+
used_lvars_in_branch = if_branch.each_descendant(:lvar).map(&:source) || []
|
304
|
+
|
305
|
+
(assigned_lvars_in_condition & used_lvars_in_branch).any?
|
306
|
+
end
|
307
|
+
|
295
308
|
def remove_whole_lines(corrector, range)
|
296
309
|
corrector.remove(range_by_whole_lines(range, include_final_newline: true))
|
297
310
|
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)
|
@@ -162,10 +162,7 @@ module RuboCop
|
|
162
162
|
|
163
163
|
def use_array_converter_method_as_preceding?(node)
|
164
164
|
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
|
165
|
+
return false unless preceding_method.type?(:call, :any_block)
|
169
166
|
|
170
167
|
ARRAY_CONVERTER_METHODS.include?(preceding_method.method_name)
|
171
168
|
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,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
|
@@ -137,6 +137,7 @@ module RuboCop
|
|
137
137
|
MSG_19 = 'Use the new Ruby 1.9 hash syntax.'
|
138
138
|
MSG_NO_MIXED_KEYS = "Don't mix styles in the same hash."
|
139
139
|
MSG_HASH_ROCKETS = 'Use hash rockets syntax.'
|
140
|
+
NO_MIXED_KEYS_STYLES = %i[ruby19_no_mixed_keys no_mixed_keys].freeze
|
140
141
|
|
141
142
|
def on_hash(node)
|
142
143
|
pairs = node.pairs
|
@@ -196,7 +197,7 @@ module RuboCop
|
|
196
197
|
def autocorrect(corrector, node)
|
197
198
|
if style == :hash_rockets || force_hash_rockets?(node.parent.pairs)
|
198
199
|
autocorrect_hash_rockets(corrector, node)
|
199
|
-
elsif style
|
200
|
+
elsif NO_MIXED_KEYS_STYLES.include?(style)
|
200
201
|
autocorrect_no_mixed_keys(corrector, node)
|
201
202
|
else
|
202
203
|
autocorrect_ruby19(corrector, node)
|
@@ -208,7 +209,7 @@ module RuboCop
|
|
208
209
|
end
|
209
210
|
|
210
211
|
def word_symbol_pair?(pair)
|
211
|
-
return false unless pair.key.
|
212
|
+
return false unless pair.key.type?(:sym, :dsym)
|
212
213
|
|
213
214
|
acceptable_19_syntax_symbol?(pair.key.source)
|
214
215
|
end
|
@@ -272,7 +273,9 @@ module RuboCop
|
|
272
273
|
end
|
273
274
|
|
274
275
|
def argument_without_space?(node)
|
275
|
-
node.argument?
|
276
|
+
return false if !node.argument? || !node.parent.loc.selector
|
277
|
+
|
278
|
+
node.source_range.begin_pos == node.parent.loc.selector.end_pos
|
276
279
|
end
|
277
280
|
|
278
281
|
def autocorrect_hash_rockets(corrector, pair_node)
|
@@ -203,17 +203,36 @@ module RuboCop
|
|
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
216
|
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
216
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
|
235
|
+
|
217
236
|
def last_child_of_parent?(node)
|
218
237
|
return true unless (parent = node.parent)
|
219
238
|
|
@@ -103,7 +103,7 @@ module RuboCop
|
|
103
103
|
|
104
104
|
def defined_argument_is_undefined?(if_node, defined_node)
|
105
105
|
defined_argument = defined_node.first_argument
|
106
|
-
return false unless defined_argument.
|
106
|
+
return false unless defined_argument.type?(:lvar, :send)
|
107
107
|
|
108
108
|
if_node.left_siblings.none? do |sibling|
|
109
109
|
sibling.respond_to?(:lvasgn_type?) && sibling.lvasgn_type? &&
|
@@ -112,11 +112,11 @@ module RuboCop
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def pattern_matching_nodes(condition)
|
115
|
-
if condition.
|
115
|
+
if condition.type?(:match_pattern, :match_pattern_p)
|
116
116
|
[condition]
|
117
117
|
else
|
118
118
|
condition.each_descendant.select do |node|
|
119
|
-
node.
|
119
|
+
node.type?(:match_pattern, :match_pattern_p)
|
120
120
|
end
|
121
121
|
end
|
122
122
|
end
|
@@ -67,7 +67,7 @@ module RuboCop
|
|
67
67
|
|
68
68
|
# @!method if_with_boolean_literal_branches?(node)
|
69
69
|
def_node_matcher :if_with_boolean_literal_branches?, <<~PATTERN
|
70
|
-
(if #return_boolean_value?
|
70
|
+
(if #return_boolean_value? <true false>)
|
71
71
|
PATTERN
|
72
72
|
# @!method double_negative?(node)
|
73
73
|
def_node_matcher :double_negative?, '(send (send _ :!) :!)'
|
@@ -155,8 +155,7 @@ module RuboCop
|
|
155
155
|
end
|
156
156
|
|
157
157
|
def require_parentheses?(condition)
|
158
|
-
condition.
|
159
|
-
(condition.send_type? && condition.comparison_method?)
|
158
|
+
condition.operator_keyword? || (condition.send_type? && condition.comparison_method?)
|
160
159
|
end
|
161
160
|
end
|
162
161
|
end
|