2024-08-12 10:30:59 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# typed: true # rubocop:todo Sorbet/StrictSigil
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# frozen_string_literal: true
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								module RuboCop
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								  module Cop
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    module Homebrew
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # Checks if collection can be blank-compacted with `compact_blank`.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      # NOTE: It is unsafe by default because false positives may occur in the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #       blank check of block arguments to the receiver object.
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      #       For example, `[[1, 2], [3, nil]].reject { |first, second| second.blank? }` and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #       `[[1, 2], [3, nil]].compact_blank` are not compatible. The same is true for `blank?`.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #       This will work fine when the receiver is a hash object.
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-30 11:10:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      #       And `compact_blank!` has different implementations for `Array`, `Hash` and
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      #       `ActionController::Parameters`.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #       `Array#compact_blank!`, `Hash#compact_blank!` are equivalent to `delete_if(&:blank?)`.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #       `ActionController::Parameters#compact_blank!` is equivalent to `reject!(&:blank?)`.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #       If the cop makes a mistake, autocorrected code may get unexpected behavior.
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      # ### Examples
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      # ```ruby
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # # bad
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # collection.reject(&:blank?)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # collection.reject { |_k, v| v.blank? }
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      # # good
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # collection.compact_blank
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # ```
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      # ```ruby
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # # bad
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # collection.delete_if(&:blank?)           # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # collection.delete_if { |_, v| v.blank? } # Same behavior as `Array#compact_blank!` and `Hash#compact_blank!`
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # collection.reject!(&:blank?)             # Same behavior as `ActionController::Parameters#compact_blank!`
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # collection.reject! { |_k, v| v.blank? }  # Same behavior as `ActionController::Parameters#compact_blank!`
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      # # good
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # collection.compact_blank!
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      # ```
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      class CompactBlank < Base
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        include RangeHelp
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        extend AutoCorrector
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        MSG = "Use `%<preferred_method>s` instead."
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-26 20:55:51 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        RESTRICT_ON_SEND = [:reject, :delete_if, :reject!].freeze
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def_node_matcher :reject_with_block?, <<~PATTERN
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          (block
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            (send _ {:reject :delete_if :reject!})
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            $(args ...)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            (send
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              $(lvar _) :blank?))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        PATTERN
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def_node_matcher :reject_with_block_pass?, <<~PATTERN
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          (send _ {:reject :delete_if :reject!}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            (block_pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              (sym :blank?)))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        PATTERN
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-02-01 23:54:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        sig { params(node: RuboCop::AST::SendNode).void }
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def on_send(node)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          return unless bad_method?(node)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          range = offense_range(node)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          preferred_method = preferred_method(node)
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-07 16:20:20 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          add_offense(range, message: format(MSG, preferred_method:)) do |corrector|
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            corrector.replace(range, preferred_method)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        private
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-02-01 23:54:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        sig { params(node: RuboCop::AST::SendNode).returns(T::Boolean) }
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def bad_method?(node)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          return true if reject_with_block_pass?(node)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          if (arguments, receiver_in_block = reject_with_block?(node.parent))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return use_single_value_block_argument?(arguments, receiver_in_block) ||
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   use_hash_value_block_argument?(arguments, receiver_in_block)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          false
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def use_single_value_block_argument?(arguments, receiver_in_block)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          arguments.length == 1 && arguments[0].source == receiver_in_block.source
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def use_hash_value_block_argument?(arguments, receiver_in_block)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          arguments.length == 2 && arguments[1].source == receiver_in_block.source
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-02-01 23:54:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        sig { params(node: RuboCop::AST::SendNode).returns(Parser::Source::Range) }
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def offense_range(node)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end_pos = if node.parent&.block_type? && node.parent&.send_node == node
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            node.parent.source_range.end_pos
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          else
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            node.source_range.end_pos
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          range_between(node.loc.selector.begin_pos, end_pos)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-02-01 23:54:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        sig { params(node: RuboCop::AST::SendNode).returns(String) }
							 | 
						
					
						
							
								
									
										
										
										
											2024-01-26 13:24:32 -08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def preferred_method(node)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          node.method?(:reject) ? "compact_blank" : "compact_blank!"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								  end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								end
							 |