rubocop 1.69.2 → 1.73.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/LICENSE.txt +1 -1
 - data/README.md +4 -4
 - data/config/default.yml +90 -13
 - data/config/internal_affairs.yml +16 -0
 - data/lib/rubocop/cli/command/execute_runner.rb +3 -3
 - data/lib/rubocop/cli/command/show_cops.rb +24 -2
 - data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
 - 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 +1 -1
 - data/lib/rubocop/cop/base.rb +6 -0
 - data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
 - data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
 - 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/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/on_send_without_on_csend.rb +90 -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/undefined_config.rb +7 -1
 - data/lib/rubocop/cop/internal_affairs.rb +5 -16
 - data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
 - data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
 - data/lib/rubocop/cop/layout/block_alignment.rb +3 -1
 - 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/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 +1 -1
 - data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
 - data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +27 -1
 - data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
 - data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
 - 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/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 +4 -3
 - 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 +1 -0
 - data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
 - data/lib/rubocop/cop/layout/redundant_line_break.rb +7 -6
 - data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
 - 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 +1 -0
 - data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
 - data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
 - 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/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 +1 -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 +1 -1
 - 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_conditional_body.rb +10 -5
 - data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
 - data/lib/rubocop/cop/lint/float_comparison.rb +6 -8
 - data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
 - data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
 - data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
 - data/lib/rubocop/cop/lint/literal_as_condition.rb +99 -9
 - 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 +3 -3
 - data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
 - data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -4
 - data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
 - data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
 - data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
 - data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
 - data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
 - data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
 - 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_string_coercion.rb +2 -2
 - data/lib/rubocop/cop/lint/redundant_type_conversion.rb +252 -0
 - data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
 - data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -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 +1 -4
 - 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 +1 -1
 - data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
 - 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_method_definition.rb +1 -1
 - data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
 - data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
 - data/lib/rubocop/cop/lint/void.rb +11 -9
 - data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
 - data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
 - data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
 - 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/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_line_breakable.rb +11 -11
 - data/lib/rubocop/cop/mixin/comments_help.rb +4 -2
 - data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
 - data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
 - 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/method_complexity.rb +1 -1
 - data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
 - data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
 - data/lib/rubocop/cop/mixin/range_help.rb +3 -3
 - 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/trailing_comma.rb +15 -3
 - data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
 - data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
 - data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
 - data/lib/rubocop/cop/naming/variable_name.rb +64 -6
 - data/lib/rubocop/cop/security/compound_hash.rb +1 -0
 - data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
 - data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
 - 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/block_delimiters.rb +7 -20
 - 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 +1 -1
 - data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
 - data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
 - data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
 - data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
 - 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 +163 -18
 - data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
 - data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
 - 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 +1 -1
 - data/lib/rubocop/cop/style/float_division.rb +8 -4
 - data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
 - data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
 - data/lib/rubocop/cop/style/hash_except.rb +24 -148
 - 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_unless_modifier.rb +3 -3
 - data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
 - data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
 - data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
 - data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
 - data/lib/rubocop/cop/style/it_assignment.rb +36 -0
 - data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
 - data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
 - data/lib/rubocop/cop/style/map_into_array.rb +1 -1
 - 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 +19 -12
 - data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
 - data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
 - 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/multiline_block_chain.rb +1 -1
 - data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
 - data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
 - data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
 - data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
 - data/lib/rubocop/cop/style/object_then.rb +13 -15
 - data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
 - data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
 - 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 +6 -4
 - data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
 - data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
 - data/lib/rubocop/cop/style/redundant_condition.rb +48 -2
 - 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 +34 -13
 - data/lib/rubocop/cop/style/redundant_parentheses.rb +28 -14
 - data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -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_self_assignment.rb +14 -28
 - data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
 - data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
 - data/lib/rubocop/cop/style/return_nil.rb +1 -1
 - data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
 - 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/single_line_block_params.rb +1 -1
 - data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
 - 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 +2 -2
 - data/lib/rubocop/cop/style/string_concatenation.rb +2 -2
 - 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/ternary_parentheses.rb +1 -1
 - 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/trivial_accessors.rb +1 -1
 - 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/variable.rb +14 -2
 - data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
 - data/lib/rubocop/cops_documentation_generator.rb +25 -14
 - data/lib/rubocop/directive_comment.rb +44 -10
 - 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/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 +5 -6
 - 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 +15 -0
 - data/lib/rubocop/version.rb +17 -2
 - data/lib/rubocop.rb +11 -1
 - data/lib/ruby_lsp/rubocop/addon.rb +75 -0
 - data/lib/ruby_lsp/rubocop/runtime_adapter.rb +47 -0
 - metadata +53 -16
 - data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
 - data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
 
| 
         @@ -0,0 +1,229 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RuboCop
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Cop
         
     | 
| 
      
 5 
     | 
    
         
            +
                module InternalAffairs
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Use node groups (`any_block`, `argument`, `boolean`, `call`, `numeric`, `range`)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # in node patterns instead of a union (`{ ... }`) of the member types of the group.
         
     | 
| 
      
 8 
     | 
    
         
            +
                  #
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #   # bad
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #   def_node_matcher :my_matcher, <<~PATTERN
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #     {send csend}
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #   PATTERN
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #   def_node_matcher :my_matcher, <<~PATTERN
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #     call
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #   PATTERN
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
      
 20 
     | 
    
         
            +
                  class NodePatternGroups < Base
         
     | 
| 
      
 21 
     | 
    
         
            +
                    require_relative 'node_pattern_groups/ast_processor'
         
     | 
| 
      
 22 
     | 
    
         
            +
                    require_relative 'node_pattern_groups/ast_walker'
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    include RangeHelp
         
     | 
| 
      
 25 
     | 
    
         
            +
                    extend AutoCorrector
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    MSG = 'Replace `%<names>s` in node pattern union with `%<replacement>s`.'
         
     | 
| 
      
 28 
     | 
    
         
            +
                    RESTRICT_ON_SEND = %i[def_node_matcher def_node_search].freeze
         
     | 
| 
      
 29 
     | 
    
         
            +
                    NODE_GROUPS = {
         
     | 
| 
      
 30 
     | 
    
         
            +
                      any_block: %i[block numblock],
         
     | 
| 
      
 31 
     | 
    
         
            +
                      argument: %i[arg optarg restarg kwarg kwoptarg kwrestarg blockarg forward_arg shadowarg],
         
     | 
| 
      
 32 
     | 
    
         
            +
                      boolean: %i[true false],
         
     | 
| 
      
 33 
     | 
    
         
            +
                      call: %i[send csend],
         
     | 
| 
      
 34 
     | 
    
         
            +
                      numeric: %i[int float rational complex],
         
     | 
| 
      
 35 
     | 
    
         
            +
                      range: %i[irange erange]
         
     | 
| 
      
 36 
     | 
    
         
            +
                    }.freeze
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    def on_new_investigation
         
     | 
| 
      
 39 
     | 
    
         
            +
                      @walker = ASTWalker.new
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    # When a Node Pattern matcher is defined, investigate the pattern string to search
         
     | 
| 
      
 43 
     | 
    
         
            +
                    # for node types that can be replaced with a node group (ie. `{send csend}` can be
         
     | 
| 
      
 44 
     | 
    
         
            +
                    # replaced with `call`).
         
     | 
| 
      
 45 
     | 
    
         
            +
                    #
         
     | 
| 
      
 46 
     | 
    
         
            +
                    # In order to deal with node patterns in an efficient and non-brittle way, we will
         
     | 
| 
      
 47 
     | 
    
         
            +
                    # parse the Node Pattern string given to this `send` node using
         
     | 
| 
      
 48 
     | 
    
         
            +
                    # `RuboCop::AST::NodePattern::Parser::WithMeta`. `WithMeta` is important! We need
         
     | 
| 
      
 49 
     | 
    
         
            +
                    # location information so that we can calculate the exact locations within the
         
     | 
| 
      
 50 
     | 
    
         
            +
                    # pattern to report and correct.
         
     | 
| 
      
 51 
     | 
    
         
            +
                    #
         
     | 
| 
      
 52 
     | 
    
         
            +
                    # The resulting AST is processed by `NodePatternGroups::ASTProccessor` which rewrites
         
     | 
| 
      
 53 
     | 
    
         
            +
                    # the AST slightly to handle node sequences (ie. `(send _ :foo ...)`). See the
         
     | 
| 
      
 54 
     | 
    
         
            +
                    # documentation of that class for more details.
         
     | 
| 
      
 55 
     | 
    
         
            +
                    #
         
     | 
| 
      
 56 
     | 
    
         
            +
                    # Then the processed AST is walked, and metadata is collected for node types that
         
     | 
| 
      
 57 
     | 
    
         
            +
                    # can be replaced with a node group.
         
     | 
| 
      
 58 
     | 
    
         
            +
                    #
         
     | 
| 
      
 59 
     | 
    
         
            +
                    # Finally, the metadata is used to register offenses and make corrections, using
         
     | 
| 
      
 60 
     | 
    
         
            +
                    # the location data captured earlier. The ranges captured while parsing the Node
         
     | 
| 
      
 61 
     | 
    
         
            +
                    # Pattern are offset using the string argument to this `send` node to ensure
         
     | 
| 
      
 62 
     | 
    
         
            +
                    # that offenses are registered at the correct location.
         
     | 
| 
      
 63 
     | 
    
         
            +
                    #
         
     | 
| 
      
 64 
     | 
    
         
            +
                    def on_send(node)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      pattern_node = node.arguments[1]
         
     | 
| 
      
 66 
     | 
    
         
            +
                      return unless acceptable_heredoc?(pattern_node) || pattern_node.str_type?
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                      process_pattern(pattern_node)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      return if node_groups.nil?
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                      apply_range_offsets(pattern_node)
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                      node_groups.each_with_index do |group, index|
         
     | 
| 
      
 74 
     | 
    
         
            +
                        register_offense(group, index)
         
     | 
| 
      
 75 
     | 
    
         
            +
                      end
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                    def after_send(_)
         
     | 
| 
      
 79 
     | 
    
         
            +
                      @walker.reset!
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    private
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    def node_groups
         
     | 
| 
      
 85 
     | 
    
         
            +
                      @walker.node_groups
         
     | 
| 
      
 86 
     | 
    
         
            +
                    end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                    # rubocop:disable InternalAffairs/RedundantSourceRange -- `node` here is a NodePatternNode
         
     | 
| 
      
 89 
     | 
    
         
            +
                    def register_offense(group, index)
         
     | 
| 
      
 90 
     | 
    
         
            +
                      replacement = replacement(group)
         
     | 
| 
      
 91 
     | 
    
         
            +
                      message = format(
         
     | 
| 
      
 92 
     | 
    
         
            +
                        MSG,
         
     | 
| 
      
 93 
     | 
    
         
            +
                        names: group.node_types.map { |node| node.source_range.source }.join('`, `'),
         
     | 
| 
      
 94 
     | 
    
         
            +
                        replacement: replacement
         
     | 
| 
      
 95 
     | 
    
         
            +
                      )
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                      add_offense(group.offense_range, message: message) do |corrector|
         
     | 
| 
      
 98 
     | 
    
         
            +
                        # Only correct one group at a time to avoid clobbering.
         
     | 
| 
      
 99 
     | 
    
         
            +
                        # Other offenses will be corrected in the subsequent iterations of the
         
     | 
| 
      
 100 
     | 
    
         
            +
                        # correction loop.
         
     | 
| 
      
 101 
     | 
    
         
            +
                        next if index.positive?
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                        if group.other_elements?
         
     | 
| 
      
 104 
     | 
    
         
            +
                          replace_types_with_node_group(corrector, group, replacement)
         
     | 
| 
      
 105 
     | 
    
         
            +
                        else
         
     | 
| 
      
 106 
     | 
    
         
            +
                          replace_union(corrector, group, replacement)
         
     | 
| 
      
 107 
     | 
    
         
            +
                        end
         
     | 
| 
      
 108 
     | 
    
         
            +
                      end
         
     | 
| 
      
 109 
     | 
    
         
            +
                    end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                    def replacement(group)
         
     | 
| 
      
 112 
     | 
    
         
            +
                      if group.sequence?
         
     | 
| 
      
 113 
     | 
    
         
            +
                        # If the original nodes were in a sequence (ie. wrapped in parentheses),
         
     | 
| 
      
 114 
     | 
    
         
            +
                        # use it to generate the resulting NodePattern syntax.
         
     | 
| 
      
 115 
     | 
    
         
            +
                        first_node_type = group.node_types.first
         
     | 
| 
      
 116 
     | 
    
         
            +
                        template = first_node_type.source_range.source
         
     | 
| 
      
 117 
     | 
    
         
            +
                        template.sub(first_node_type.child.to_s, group.name.to_s)
         
     | 
| 
      
 118 
     | 
    
         
            +
                      else
         
     | 
| 
      
 119 
     | 
    
         
            +
                        group.name
         
     | 
| 
      
 120 
     | 
    
         
            +
                      end
         
     | 
| 
      
 121 
     | 
    
         
            +
                    end
         
     | 
| 
      
 122 
     | 
    
         
            +
                    # rubocop:enable InternalAffairs/RedundantSourceRange
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                    # When there are other elements in the union, remove the node types that can be replaced.
         
     | 
| 
      
 125 
     | 
    
         
            +
                    def replace_types_with_node_group(corrector, group, replacement)
         
     | 
| 
      
 126 
     | 
    
         
            +
                      ranges = group.ranges.map.with_index do |range, index|
         
     | 
| 
      
 127 
     | 
    
         
            +
                        # Collect whitespace and pipes preceding each element
         
     | 
| 
      
 128 
     | 
    
         
            +
                        range_for_full_union_element(range, index, group.pipe)
         
     | 
| 
      
 129 
     | 
    
         
            +
                      end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                      ranges.each { |range| corrector.remove(range) }
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                      corrector.insert_before(ranges.first, replacement)
         
     | 
| 
      
 134 
     | 
    
         
            +
                    end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                    # If the union contains pipes, remove the pipe character as well.
         
     | 
| 
      
 137 
     | 
    
         
            +
                    # Unfortunately we don't get the location of the pipe in `loc` object, so we have
         
     | 
| 
      
 138 
     | 
    
         
            +
                    # to find it.
         
     | 
| 
      
 139 
     | 
    
         
            +
                    def range_for_full_union_element(range, index, pipe)
         
     | 
| 
      
 140 
     | 
    
         
            +
                      if index.positive?
         
     | 
| 
      
 141 
     | 
    
         
            +
                        range = if pipe
         
     | 
| 
      
 142 
     | 
    
         
            +
                                  range_with_preceding_pipe(range)
         
     | 
| 
      
 143 
     | 
    
         
            +
                                else
         
     | 
| 
      
 144 
     | 
    
         
            +
                                  range_with_surrounding_space(range: range, side: :left, newlines: true)
         
     | 
| 
      
 145 
     | 
    
         
            +
                                end
         
     | 
| 
      
 146 
     | 
    
         
            +
                      end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                      range
         
     | 
| 
      
 149 
     | 
    
         
            +
                    end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                    # Collect a preceding pipe and any whitespace left of the pipe
         
     | 
| 
      
 152 
     | 
    
         
            +
                    def range_with_preceding_pipe(range)
         
     | 
| 
      
 153 
     | 
    
         
            +
                      pos = range.begin_pos - 1
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                      while pos
         
     | 
| 
      
 156 
     | 
    
         
            +
                        unless processed_source.buffer.source[pos].match?(/[\s|]/)
         
     | 
| 
      
 157 
     | 
    
         
            +
                          return range.with(begin_pos: pos + 1)
         
     | 
| 
      
 158 
     | 
    
         
            +
                        end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                        pos -= 1
         
     | 
| 
      
 161 
     | 
    
         
            +
                      end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                      range
         
     | 
| 
      
 164 
     | 
    
         
            +
                    end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                    # When there are no other elements, the entire union can be replaced
         
     | 
| 
      
 167 
     | 
    
         
            +
                    def replace_union(corrector, group, replacement)
         
     | 
| 
      
 168 
     | 
    
         
            +
                      corrector.replace(group.ranges.first, replacement)
         
     | 
| 
      
 169 
     | 
    
         
            +
                    end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                    # rubocop:disable Metrics/AbcSize
         
     | 
| 
      
 172 
     | 
    
         
            +
                    # Calculate the ranges for each node within the pattern string that will
         
     | 
| 
      
 173 
     | 
    
         
            +
                    # be replaced or removed. Takes the offset of the string node into account.
         
     | 
| 
      
 174 
     | 
    
         
            +
                    def apply_range_offsets(pattern_node)
         
     | 
| 
      
 175 
     | 
    
         
            +
                      range, offset = range_with_offset(pattern_node)
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                      node_groups.each do |node_group|
         
     | 
| 
      
 178 
     | 
    
         
            +
                        node_group.ranges ||= []
         
     | 
| 
      
 179 
     | 
    
         
            +
                        node_group.offense_range = pattern_range(range, node_group.union, offset)
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                        if node_group.other_elements?
         
     | 
| 
      
 182 
     | 
    
         
            +
                          node_group.node_types.each do |node_type|
         
     | 
| 
      
 183 
     | 
    
         
            +
                            node_group.ranges << pattern_range(range, node_type, offset)
         
     | 
| 
      
 184 
     | 
    
         
            +
                          end
         
     | 
| 
      
 185 
     | 
    
         
            +
                        else
         
     | 
| 
      
 186 
     | 
    
         
            +
                          node_group.ranges << node_group.offense_range
         
     | 
| 
      
 187 
     | 
    
         
            +
                        end
         
     | 
| 
      
 188 
     | 
    
         
            +
                      end
         
     | 
| 
      
 189 
     | 
    
         
            +
                    end
         
     | 
| 
      
 190 
     | 
    
         
            +
                    # rubocop:enable Metrics/AbcSize
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                    def pattern_range(range, node, offset)
         
     | 
| 
      
 193 
     | 
    
         
            +
                      begin_pos = node.source_range.begin_pos
         
     | 
| 
      
 194 
     | 
    
         
            +
                      end_pos = node.source_range.end_pos
         
     | 
| 
      
 195 
     | 
    
         
            +
                      size = end_pos - begin_pos
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                      range.adjust(begin_pos: begin_pos + offset).resize(size)
         
     | 
| 
      
 198 
     | 
    
         
            +
                    end
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                    def range_with_offset(pattern_node)
         
     | 
| 
      
 201 
     | 
    
         
            +
                      if pattern_node.heredoc?
         
     | 
| 
      
 202 
     | 
    
         
            +
                        [pattern_node.loc.heredoc_body, 0]
         
     | 
| 
      
 203 
     | 
    
         
            +
                      else
         
     | 
| 
      
 204 
     | 
    
         
            +
                        [pattern_node.source_range, pattern_node.loc.begin.size]
         
     | 
| 
      
 205 
     | 
    
         
            +
                      end
         
     | 
| 
      
 206 
     | 
    
         
            +
                    end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                    # A heredoc can be a `dstr` without interpolation, but if there is interpolation
         
     | 
| 
      
 209 
     | 
    
         
            +
                    # there'll be a `begin` node, in which case, we cannot evaluate the pattern.
         
     | 
| 
      
 210 
     | 
    
         
            +
                    def acceptable_heredoc?(node)
         
     | 
| 
      
 211 
     | 
    
         
            +
                      node.type?(:str, :dstr) && node.heredoc? && node.each_child_node(:begin).none?
         
     | 
| 
      
 212 
     | 
    
         
            +
                    end
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                    def process_pattern(pattern_node)
         
     | 
| 
      
 215 
     | 
    
         
            +
                      parser = RuboCop::AST::NodePattern::Parser::WithMeta.new
         
     | 
| 
      
 216 
     | 
    
         
            +
                      ast = parser.parse(pattern_value(pattern_node))
         
     | 
| 
      
 217 
     | 
    
         
            +
                      ast = ASTProcessor.new.process(ast)
         
     | 
| 
      
 218 
     | 
    
         
            +
                      @walker.walk(ast)
         
     | 
| 
      
 219 
     | 
    
         
            +
                    rescue RuboCop::AST::NodePattern::Invalid
         
     | 
| 
      
 220 
     | 
    
         
            +
                      # if the pattern is invalid, no offenses will be registered
         
     | 
| 
      
 221 
     | 
    
         
            +
                    end
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                    def pattern_value(pattern_node)
         
     | 
| 
      
 224 
     | 
    
         
            +
                      pattern_node.heredoc? ? pattern_node.loc.heredoc_body.source : pattern_node.value
         
     | 
| 
      
 225 
     | 
    
         
            +
                    end
         
     | 
| 
      
 226 
     | 
    
         
            +
                  end
         
     | 
| 
      
 227 
     | 
    
         
            +
                end
         
     | 
| 
      
 228 
     | 
    
         
            +
              end
         
     | 
| 
      
 229 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,126 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RuboCop
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Cop
         
     | 
| 
      
 5 
     | 
    
         
            +
                module InternalAffairs
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Use `node.type?(:foo, :bar)` instead of `node.foo_type? || node.bar_type?`,
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # and `!node.type?(:foo, :bar)` instead of `!node.foo_type? && !node.bar_type?`.
         
     | 
| 
      
 8 
     | 
    
         
            +
                  #
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #   # bad
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #   node.str_type? || node.sym_type?
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #   node.type?(:str, :sym)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #   # bad
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #   node.type?(:str, :sym) || node.boolean_type?
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 21 
     | 
    
         
            +
                  #   node.type?(:str, :sym, :boolean)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #   # bad
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #   !node.str_type? && !node.sym_type?
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #   !node.type?(:str, :sym)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #
         
     | 
| 
      
 29 
     | 
    
         
            +
                  #   # bad
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #   !node.type?(:str, :sym) && !node.boolean_type?
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #   # good
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #   !node.type?(:str, :sym, :boolean)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #
         
     | 
| 
      
 35 
     | 
    
         
            +
                  class NodeTypeMultiplePredicates < Base
         
     | 
| 
      
 36 
     | 
    
         
            +
                    extend AutoCorrector
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    MSG_OR = 'Use `%<replacement>s` instead of checking for multiple node types.'
         
     | 
| 
      
 39 
     | 
    
         
            +
                    MSG_AND = 'Use `%<replacement>s` instead of checking against multiple node types.'
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    # @!method one_of_node_types?(node)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    def_node_matcher :one_of_node_types?, <<~PATTERN
         
     | 
| 
      
 43 
     | 
    
         
            +
                      (or $(call _receiver #type_predicate?) (call _receiver #type_predicate?))
         
     | 
| 
      
 44 
     | 
    
         
            +
                    PATTERN
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    # @!method or_another_type?(node)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    def_node_matcher :or_another_type?, <<~PATTERN
         
     | 
| 
      
 48 
     | 
    
         
            +
                      (or {
         
     | 
| 
      
 49 
     | 
    
         
            +
                        $(call _receiver :type? sym+) (call _receiver #type_predicate?) |
         
     | 
| 
      
 50 
     | 
    
         
            +
                        (call _receiver #type_predicate?) $(call _receiver :type? sym+)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      })
         
     | 
| 
      
 52 
     | 
    
         
            +
                    PATTERN
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    # @!method none_of_node_types?(node)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    def_node_matcher :none_of_node_types?, <<~PATTERN
         
     | 
| 
      
 56 
     | 
    
         
            +
                      (and
         
     | 
| 
      
 57 
     | 
    
         
            +
                        (send $(call _receiver #type_predicate?) :!)
         
     | 
| 
      
 58 
     | 
    
         
            +
                        (send (call _receiver #type_predicate?) :!)
         
     | 
| 
      
 59 
     | 
    
         
            +
                      )
         
     | 
| 
      
 60 
     | 
    
         
            +
                    PATTERN
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                    # @!method and_not_another_type?(node)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    def_node_matcher :and_not_another_type?, <<~PATTERN
         
     | 
| 
      
 64 
     | 
    
         
            +
                      (and {
         
     | 
| 
      
 65 
     | 
    
         
            +
                        (send $(call _receiver :type? sym+) :!) (send (call _receiver #type_predicate?) :!) |
         
     | 
| 
      
 66 
     | 
    
         
            +
                        (send (call _receiver #type_predicate?) :!) (send $(call _receiver :type? sym+) :!)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      })
         
     | 
| 
      
 68 
     | 
    
         
            +
                    PATTERN
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    def on_or(node)
         
     | 
| 
      
 71 
     | 
    
         
            +
                      return unless (send_node = one_of_node_types?(node) || or_another_type?(node))
         
     | 
| 
      
 72 
     | 
    
         
            +
                      return unless send_node.receiver
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                      replacement = replacement(node, send_node)
         
     | 
| 
      
 75 
     | 
    
         
            +
                      add_offense(node, message: format(MSG_OR, replacement: replacement)) do |corrector|
         
     | 
| 
      
 76 
     | 
    
         
            +
                        corrector.replace(node, replacement)
         
     | 
| 
      
 77 
     | 
    
         
            +
                      end
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                    def on_and(node)
         
     | 
| 
      
 81 
     | 
    
         
            +
                      return unless (send_node = none_of_node_types?(node) || and_not_another_type?(node))
         
     | 
| 
      
 82 
     | 
    
         
            +
                      return unless send_node.receiver
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                      replacement = "!#{replacement(node, send_node)}"
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                      add_offense(node, message: format(MSG_AND, replacement: replacement)) do |corrector|
         
     | 
| 
      
 87 
     | 
    
         
            +
                        corrector.replace(node, replacement)
         
     | 
| 
      
 88 
     | 
    
         
            +
                      end
         
     | 
| 
      
 89 
     | 
    
         
            +
                    end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                    private
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                    def type_predicate?(method_name)
         
     | 
| 
      
 94 
     | 
    
         
            +
                      method_name.end_with?('_type?')
         
     | 
| 
      
 95 
     | 
    
         
            +
                    end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                    def replacement(node, send_node)
         
     | 
| 
      
 98 
     | 
    
         
            +
                      send_node = send_node.children.first if send_node.method?(:!)
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                      types = types(node)
         
     | 
| 
      
 101 
     | 
    
         
            +
                      receiver = send_node.receiver.source
         
     | 
| 
      
 102 
     | 
    
         
            +
                      dot = send_node.loc.dot.source
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                      "#{receiver}#{dot}type?(:#{types.join(', :')})"
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                    def types(node)
         
     | 
| 
      
 108 
     | 
    
         
            +
                      [types_in_branch(node.lhs), types_in_branch(node.rhs)]
         
     | 
| 
      
 109 
     | 
    
         
            +
                    end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                    def types_in_branch(branch)
         
     | 
| 
      
 112 
     | 
    
         
            +
                      branch = branch.children.first if branch.method?(:!)
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                      if branch.method?(:type?)
         
     | 
| 
      
 115 
     | 
    
         
            +
                        branch.arguments.map(&:value)
         
     | 
| 
      
 116 
     | 
    
         
            +
                      elsif branch.method?(:defined_type?)
         
     | 
| 
      
 117 
     | 
    
         
            +
                        # `node.defined_type?` relates to `node.type == :defined?`
         
     | 
| 
      
 118 
     | 
    
         
            +
                        'defined?'
         
     | 
| 
      
 119 
     | 
    
         
            +
                      else
         
     | 
| 
      
 120 
     | 
    
         
            +
                        branch.method_name.to_s.delete_suffix('_type?')
         
     | 
| 
      
 121 
     | 
    
         
            +
                      end
         
     | 
| 
      
 122 
     | 
    
         
            +
                    end
         
     | 
| 
      
 123 
     | 
    
         
            +
                  end
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
              end
         
     | 
| 
      
 126 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -21,16 +21,17 @@ module RuboCop 
     | 
|
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                    # @!method node_type_check(node)
         
     | 
| 
       23 
23 
     | 
    
         
             
                    def_node_matcher :node_type_check, <<~PATTERN
         
     | 
| 
       24 
     | 
    
         
            -
                      (send ( 
     | 
| 
      
 24 
     | 
    
         
            +
                      (send (call _ :type) :== (sym $_))
         
     | 
| 
       25 
25 
     | 
    
         
             
                    PATTERN
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
27 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       28 
     | 
    
         
            -
                      node_type_check(node) do | 
     | 
| 
      
 28 
     | 
    
         
            +
                      node_type_check(node) do |node_type|
         
     | 
| 
       29 
29 
     | 
    
         
             
                        return unless Parser::Meta::NODE_TYPES.include?(node_type)
         
     | 
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
                        message = format(MSG, type: node_type)
         
     | 
| 
       32 
32 
     | 
    
         
             
                        add_offense(node, message: message) do |corrector|
         
     | 
| 
       33 
     | 
    
         
            -
                          range = node. 
     | 
| 
      
 33 
     | 
    
         
            +
                          range = node.receiver.loc.selector.join(node.source_range.end)
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
       34 
35 
     | 
    
         
             
                          corrector.replace(range, "#{node_type}_type?")
         
     | 
| 
       35 
36 
     | 
    
         
             
                        end
         
     | 
| 
       36 
37 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -0,0 +1,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module RuboCop
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Cop
         
     | 
| 
      
 5 
     | 
    
         
            +
                module InternalAffairs
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # Checks for cops that define `on_send` without define `on_csend`.
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # Although in some cases it can be predetermined that safe navigation
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # will never be used with the code checked by a specific cop, in general
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # it is good practice to handle safe navigation methods if handling any
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # `send` node.
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # NOTE: It is expected to disable this cop for cops that check for method calls
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # on receivers that cannot be nil (`self`, a literal, a constant), and
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # method calls that will never have a receiver (ruby keywords like `raise`,
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # macros like `attr_reader`, DSL methods, etc.), and other checks that wouldn't
         
     | 
| 
      
 17 
     | 
    
         
            +
                  # make sense to support safe navigation.
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #   # bad
         
     | 
| 
      
 21 
     | 
    
         
            +
                  #   class MyCop < RuboCop::Cop:Base
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #     def on_send(node)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #       # ...
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #     end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #   # good - explicit method definition
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #   class MyCop < RuboCop::Cop:Base
         
     | 
| 
      
 29 
     | 
    
         
            +
                  #     def on_send(node)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #       # ...
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #     end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #     def on_csend(node)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #       # ...
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #     end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #   # good - alias
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #   class MyCop < RuboCop::Cop:Base
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #     def on_send(node)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  #       # ...
         
     | 
| 
      
 42 
     | 
    
         
            +
                  #     end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  #     alias on_csend on_send
         
     | 
| 
      
 44 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  #
         
     | 
| 
      
 46 
     | 
    
         
            +
                  #   # good - alias_method
         
     | 
| 
      
 47 
     | 
    
         
            +
                  #   class MyCop < RuboCop::Cop:Base
         
     | 
| 
      
 48 
     | 
    
         
            +
                  #     def on_send(node)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  #       # ...
         
     | 
| 
      
 50 
     | 
    
         
            +
                  #     end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  #     alias_method :on_csend, :on_send
         
     | 
| 
      
 52 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  class OnSendWithoutOnCSend < Base
         
     | 
| 
      
 54 
     | 
    
         
            +
                    RESTRICT_ON_SEND = %i[alias_method].freeze
         
     | 
| 
      
 55 
     | 
    
         
            +
                    MSG = 'Cop defines `on_send` but not `on_csend`.'
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    def on_new_investigation
         
     | 
| 
      
 58 
     | 
    
         
            +
                      @on_send_definition = nil
         
     | 
| 
      
 59 
     | 
    
         
            +
                      @on_csend_definition = nil
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                    def on_investigation_end
         
     | 
| 
      
 63 
     | 
    
         
            +
                      return unless @on_send_definition && !@on_csend_definition
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                      add_offense(@on_send_definition)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    def on_def(node)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      @on_send_definition = node if node.method?(:on_send)
         
     | 
| 
      
 70 
     | 
    
         
            +
                      @on_csend_definition = node if node.method?(:on_csend)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    def on_alias(node)
         
     | 
| 
      
 74 
     | 
    
         
            +
                      @on_send_definition = node if node.new_identifier.value == :on_send
         
     | 
| 
      
 75 
     | 
    
         
            +
                      @on_csend_definition = node if node.new_identifier.value == :on_csend
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                    def on_send(node) # rubocop:disable InternalAffairs/OnSendWithoutOnCSend
         
     | 
| 
      
 79 
     | 
    
         
            +
                      new_identifier = node.first_argument
         
     | 
| 
      
 80 
     | 
    
         
            +
                      return unless new_identifier.basic_literal?
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                      new_identifier = new_identifier.value
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                      @on_send_definition = node if new_identifier == :on_send
         
     | 
| 
      
 85 
     | 
    
         
            +
                      @on_csend_definition = node if new_identifier == :on_csend
         
     | 
| 
      
 86 
     | 
    
         
            +
                    end
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'lint_roller'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module RuboCop
         
     | 
| 
      
 6 
     | 
    
         
            +
              module InternalAffairs
         
     | 
| 
      
 7 
     | 
    
         
            +
                # A Plugin for `InternalAffairs` department, which has internal cops.
         
     | 
| 
      
 8 
     | 
    
         
            +
                class Plugin < LintRoller::Plugin
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def about
         
     | 
| 
      
 10 
     | 
    
         
            +
                    LintRoller::About.new(
         
     | 
| 
      
 11 
     | 
    
         
            +
                      name: 'rubocop-internal_affairs',
         
     | 
| 
      
 12 
     | 
    
         
            +
                      version: Version::STRING,
         
     | 
| 
      
 13 
     | 
    
         
            +
                      homepage: 'https://github.com/rubocop/rubocop/tree/master/lib/rubocop/cop/internal_affairs',
         
     | 
| 
      
 14 
     | 
    
         
            +
                      description: 'A collection of RuboCop cops to check for internal affairs.'
         
     | 
| 
      
 15 
     | 
    
         
            +
                    )
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def supported?(context)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    context.engine == :rubocop
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def rules(_context)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    require_relative '../internal_affairs'
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    LintRoller::Rules.new(
         
     | 
| 
      
 26 
     | 
    
         
            +
                      type: :path,
         
     | 
| 
      
 27 
     | 
    
         
            +
                      config_format: :rubocop,
         
     | 
| 
      
 28 
     | 
    
         
            +
                      value: Pathname.new(__dir__).join('../../../../config/internal_affairs.yml')
         
     | 
| 
      
 29 
     | 
    
         
            +
                    )
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -47,7 +47,7 @@ module RuboCop 
     | 
|
| 
       47 
47 
     | 
    
         
             
                    # @!method redundant_source_range(node)
         
     | 
| 
       48 
48 
     | 
    
         
             
                    def_node_matcher :redundant_source_range, <<~PATTERN
         
     | 
| 
       49 
49 
     | 
    
         
             
                      {
         
     | 
| 
       50 
     | 
    
         
            -
                        ( 
     | 
| 
      
 50 
     | 
    
         
            +
                        (call $(call _ :source_range) :source)
         
     | 
| 
       51 
51 
     | 
    
         
             
                        (send nil? :add_offense $(send _ :source_range) ...)
         
     | 
| 
       52 
52 
     | 
    
         
             
                        (send _ {
         
     | 
| 
       53 
53 
     | 
    
         
             
                          :replace :insert_before :insert_before_multi :insert_after :insert_after_multi
         
     | 
| 
         @@ -59,6 +59,7 @@ module RuboCop 
     | 
|
| 
       59 
59 
     | 
    
         | 
| 
       60 
60 
     | 
    
         
             
                    def on_send(node)
         
     | 
| 
       61 
61 
     | 
    
         
             
                      return unless (source_range = redundant_source_range(node))
         
     | 
| 
      
 62 
     | 
    
         
            +
                      return unless source_range.receiver
         
     | 
| 
       62 
63 
     | 
    
         
             
                      return if source_range.receiver.send_type? && source_range.receiver.method?(:buffer)
         
     | 
| 
       63 
64 
     | 
    
         | 
| 
       64 
65 
     | 
    
         
             
                      selector = source_range.loc.selector
         
     | 
| 
         @@ -67,6 +68,7 @@ module RuboCop 
     | 
|
| 
       67 
68 
     | 
    
         
             
                        corrector.remove(source_range.loc.dot.join(selector))
         
     | 
| 
       68 
69 
     | 
    
         
             
                      end
         
     | 
| 
       69 
70 
     | 
    
         
             
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
                    alias on_csend on_send
         
     | 
| 
       70 
72 
     | 
    
         
             
                  end
         
     | 
| 
       71 
73 
     | 
    
         
             
                end
         
     | 
| 
       72 
74 
     | 
    
         
             
              end
         
     | 
| 
         @@ -34,8 +34,8 @@ module RuboCop 
     | 
|
| 
       34 
34 
     | 
    
         
             
                    # @!method single_line_comparison(node)
         
     | 
| 
       35 
35 
     | 
    
         
             
                    def_node_matcher :single_line_comparison, <<~PATTERN
         
     | 
| 
       36 
36 
     | 
    
         
             
                      {
         
     | 
| 
       37 
     | 
    
         
            -
                        (send ( 
     | 
| 
       38 
     | 
    
         
            -
                        (send ( 
     | 
| 
      
 37 
     | 
    
         
            +
                        (send (call $_receiver {:line :first_line}) {:== :!=} (call _receiver :last_line))
         
     | 
| 
      
 38 
     | 
    
         
            +
                        (send (call $_receiver :last_line) {:== :!=} (call _receiver {:line :first_line}))
         
     | 
| 
       39 
39 
     | 
    
         
             
                      }
         
     | 
| 
       40 
40 
     | 
    
         
             
                    PATTERN
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
         @@ -43,7 +43,8 @@ module RuboCop 
     | 
|
| 
       43 
43 
     | 
    
         
             
                      return unless (receiver = single_line_comparison(node))
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
       45 
45 
     | 
    
         
             
                      bang = node.method?(:!=) ? '!' : ''
         
     | 
| 
       46 
     | 
    
         
            -
                       
     | 
| 
      
 46 
     | 
    
         
            +
                      dot = receiver.parent.loc.dot.source
         
     | 
| 
      
 47 
     | 
    
         
            +
                      preferred = "#{bang}#{extract_receiver(receiver)}#{dot}single_line?"
         
     | 
| 
       47 
48 
     | 
    
         | 
| 
       48 
49 
     | 
    
         
             
                      add_offense(node, message: format(MSG, preferred: preferred)) do |corrector|
         
     | 
| 
       49 
50 
     | 
    
         
             
                        corrector.replace(node, preferred)
         
     | 
| 
         @@ -53,7 +54,7 @@ module RuboCop 
     | 
|
| 
       53 
54 
     | 
    
         
             
                    private
         
     | 
| 
       54 
55 
     | 
    
         | 
| 
       55 
56 
     | 
    
         
             
                    def extract_receiver(node)
         
     | 
| 
       56 
     | 
    
         
            -
                      node = node.receiver if node. 
     | 
| 
      
 57 
     | 
    
         
            +
                      node = node.receiver if node.call_type? && %i[loc source_range].include?(node.method_name)
         
     | 
| 
       57 
58 
     | 
    
         
             
                      node.source
         
     | 
| 
       58 
59 
     | 
    
         
             
                    end
         
     | 
| 
       59 
60 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -17,7 +17,13 @@ module RuboCop 
     | 
|
| 
       17 
17 
     | 
    
         
             
                          'in `config/default.yml`.'
         
     | 
| 
       18 
18 
     | 
    
         
             
                    CONFIG_PATH = find_file_upwards('config/default.yml', Dir.pwd)
         
     | 
| 
       19 
19 
     | 
    
         
             
                    CONFIG = if CONFIG_PATH
         
     | 
| 
       20 
     | 
    
         
            -
                                
     | 
| 
      
 20 
     | 
    
         
            +
                               begin
         
     | 
| 
      
 21 
     | 
    
         
            +
                                 original_debug = ConfigLoader.debug
         
     | 
| 
      
 22 
     | 
    
         
            +
                                 ConfigLoader.debug = false
         
     | 
| 
      
 23 
     | 
    
         
            +
                                 ConfigLoader.load_yaml_configuration(CONFIG_PATH)
         
     | 
| 
      
 24 
     | 
    
         
            +
                               ensure
         
     | 
| 
      
 25 
     | 
    
         
            +
                                 ConfigLoader.debug = original_debug
         
     | 
| 
      
 26 
     | 
    
         
            +
                               end
         
     | 
| 
       21 
27 
     | 
    
         
             
                             else
         
     | 
| 
       22 
28 
     | 
    
         
             
                               {}
         
     | 
| 
       23 
29 
     | 
    
         
             
                             end
         
     | 
| 
         @@ -1,12 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require_relative 'internal_affairs/cop_description'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'internal_affairs/cop_enabled'
         
     | 
| 
       4 
5 
     | 
    
         
             
            require_relative 'internal_affairs/create_empty_file'
         
     | 
| 
       5 
6 
     | 
    
         
             
            require_relative 'internal_affairs/empty_line_between_expect_offense_and_correction'
         
     | 
| 
       6 
7 
     | 
    
         
             
            require_relative 'internal_affairs/example_description'
         
     | 
| 
       7 
8 
     | 
    
         
             
            require_relative 'internal_affairs/example_heredoc_delimiter'
         
     | 
| 
       8 
9 
     | 
    
         
             
            require_relative 'internal_affairs/inherit_deprecated_cop_class'
         
     | 
| 
       9 
10 
     | 
    
         
             
            require_relative 'internal_affairs/lambda_or_proc'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require_relative 'internal_affairs/location_exists'
         
     | 
| 
       10 
12 
     | 
    
         
             
            require_relative 'internal_affairs/location_expression'
         
     | 
| 
       11 
13 
     | 
    
         
             
            require_relative 'internal_affairs/location_line_equality_comparison'
         
     | 
| 
       12 
14 
     | 
    
         
             
            require_relative 'internal_affairs/method_name_end_with'
         
     | 
| 
         @@ -14,9 +16,12 @@ require_relative 'internal_affairs/method_name_equal' 
     | 
|
| 
       14 
16 
     | 
    
         
             
            require_relative 'internal_affairs/node_destructuring'
         
     | 
| 
       15 
17 
     | 
    
         
             
            require_relative 'internal_affairs/node_first_or_last_argument'
         
     | 
| 
       16 
18 
     | 
    
         
             
            require_relative 'internal_affairs/node_matcher_directive'
         
     | 
| 
      
 19 
     | 
    
         
            +
            require_relative 'internal_affairs/node_pattern_groups'
         
     | 
| 
      
 20 
     | 
    
         
            +
            require_relative 'internal_affairs/node_type_multiple_predicates'
         
     | 
| 
       17 
21 
     | 
    
         
             
            require_relative 'internal_affairs/node_type_predicate'
         
     | 
| 
       18 
22 
     | 
    
         
             
            require_relative 'internal_affairs/numblock_handler'
         
     | 
| 
       19 
23 
     | 
    
         
             
            require_relative 'internal_affairs/offense_location_keyword'
         
     | 
| 
      
 24 
     | 
    
         
            +
            require_relative 'internal_affairs/on_send_without_on_csend'
         
     | 
| 
       20 
25 
     | 
    
         
             
            require_relative 'internal_affairs/operator_keyword'
         
     | 
| 
       21 
26 
     | 
    
         
             
            require_relative 'internal_affairs/processed_source_buffer_name'
         
     | 
| 
       22 
27 
     | 
    
         
             
            require_relative 'internal_affairs/redundant_context_config_parameter'
         
     | 
| 
         @@ -32,19 +37,3 @@ require_relative 'internal_affairs/style_detected_api_use' 
     | 
|
| 
       32 
37 
     | 
    
         
             
            require_relative 'internal_affairs/undefined_config'
         
     | 
| 
       33 
38 
     | 
    
         
             
            require_relative 'internal_affairs/useless_message_assertion'
         
     | 
| 
       34 
39 
     | 
    
         
             
            require_relative 'internal_affairs/useless_restrict_on_send'
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
            module RuboCop
         
     | 
| 
       37 
     | 
    
         
            -
              # Patch in the InternalAffairs specific config values
         
     | 
| 
       38 
     | 
    
         
            -
              module InternalAffairs
         
     | 
| 
       39 
     | 
    
         
            -
                def self.inject!
         
     | 
| 
       40 
     | 
    
         
            -
                  path = File.join(ConfigLoader::RUBOCOP_HOME, 'config', 'internal_affairs.yml')
         
     | 
| 
       41 
     | 
    
         
            -
                  hash = ConfigLoader.load_yaml_configuration(path)
         
     | 
| 
       42 
     | 
    
         
            -
                  config = Config.new(hash, path)
         
     | 
| 
       43 
     | 
    
         
            -
                  puts "configuration from #{path}" if ConfigLoader.debug?
         
     | 
| 
       44 
     | 
    
         
            -
                  config = ConfigLoader.merge_with_default(config, path)
         
     | 
| 
       45 
     | 
    
         
            -
                  ConfigLoader.instance_variable_set(:@default_configuration, config)
         
     | 
| 
       46 
     | 
    
         
            -
                end
         
     | 
| 
       47 
     | 
    
         
            -
              end
         
     | 
| 
       48 
     | 
    
         
            -
            end
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
            RuboCop::InternalAffairs.inject!
         
     | 
| 
         @@ -4,7 +4,7 @@ module RuboCop 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module Cop
         
     | 
| 
       5 
5 
     | 
    
         
             
                module Layout
         
     | 
| 
       6 
6 
     | 
    
         
             
                  # Bare access modifiers (those not applying to specific methods) should be
         
     | 
| 
       7 
     | 
    
         
            -
                  # indented as deep as method definitions, or as deep as the class 
     | 
| 
      
 7 
     | 
    
         
            +
                  # indented as deep as method definitions, or as deep as the `class`/`module`
         
     | 
| 
       8 
8 
     | 
    
         
             
                  # keyword, depending on configuration.
         
     | 
| 
       9 
9 
     | 
    
         
             
                  #
         
     | 
| 
       10 
10 
     | 
    
         
             
                  # @example EnforcedStyle: indent (default)
         
     | 
| 
         @@ -3,7 +3,7 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            module RuboCop
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Cop
         
     | 
| 
       5 
5 
     | 
    
         
             
                module Layout
         
     | 
| 
       6 
     | 
    
         
            -
                  # Check that the arguments on a multi-line method  
     | 
| 
      
 6 
     | 
    
         
            +
                  # Check that the arguments on a multi-line method call are aligned.
         
     | 
| 
       7 
7 
     | 
    
         
             
                  #
         
     | 
| 
       8 
8 
     | 
    
         
             
                  # @example EnforcedStyle: with_first_argument (default)
         
     | 
| 
       9 
9 
     | 
    
         
             
                  #   # good
         
     | 
| 
         @@ -141,16 +141,10 @@ module RuboCop 
     | 
|
| 
       141 
141 
     | 
    
         
             
                    end
         
     | 
| 
       142 
142 
     | 
    
         | 
| 
       143 
143 
     | 
    
         
             
                    def enforce_hash_argument_with_separator?
         
     | 
| 
       144 
     | 
    
         
            -
                      return false unless hash_argument_config['Enabled']
         
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
144 
     | 
    
         
             
                      RuboCop::Cop::Layout::HashAlignment::SEPARATOR_ALIGNMENT_STYLES.any? do |style|
         
     | 
| 
       147 
     | 
    
         
            -
                         
     | 
| 
      
 145 
     | 
    
         
            +
                        config.for_enabled_cop('Layout/HashAlignment')[style]&.include?('separator')
         
     | 
| 
       148 
146 
     | 
    
         
             
                      end
         
     | 
| 
       149 
147 
     | 
    
         
             
                    end
         
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
                    def hash_argument_config
         
     | 
| 
       152 
     | 
    
         
            -
                      config.for_cop('Layout/HashAlignment')
         
     | 
| 
       153 
     | 
    
         
            -
                    end
         
     | 
| 
       154 
148 
     | 
    
         
             
                  end
         
     | 
| 
       155 
149 
     | 
    
         
             
                end
         
     | 
| 
       156 
150 
     | 
    
         
             
              end
         
     | 
| 
         @@ -73,6 +73,8 @@ module RuboCop 
     | 
|
| 
       73 
73 
     | 
    
         
             
                    # @!method block_end_align_target?(node, child)
         
     | 
| 
       74 
74 
     | 
    
         
             
                    def_node_matcher :block_end_align_target?, <<~PATTERN
         
     | 
| 
       75 
75 
     | 
    
         
             
                      {assignment?
         
     | 
| 
      
 76 
     | 
    
         
            +
                       def
         
     | 
| 
      
 77 
     | 
    
         
            +
                       defs
         
     | 
| 
       76 
78 
     | 
    
         
             
                       splat
         
     | 
| 
       77 
79 
     | 
    
         
             
                       and
         
     | 
| 
       78 
80 
     | 
    
         
             
                       or
         
     | 
| 
         @@ -188,7 +190,7 @@ module RuboCop 
     | 
|
| 
       188 
190 
     | 
    
         
             
                    # In offense message, we want to show the assignment LHS rather than
         
     | 
| 
       189 
191 
     | 
    
         
             
                    # the entire assignment.
         
     | 
| 
       190 
192 
     | 
    
         
             
                    def find_lhs_node(node)
         
     | 
| 
       191 
     | 
    
         
            -
                      node = node.lhs while node. 
     | 
| 
      
 193 
     | 
    
         
            +
                      node = node.lhs while node.type?(:op_asgn, :masgn)
         
     | 
| 
       192 
194 
     | 
    
         
             
                      node
         
     | 
| 
       193 
195 
     | 
    
         
             
                    end
         
     | 
| 
       194 
196 
     | 
    
         |