Class: RuboCop::Cop::Lint::Utils::NilReceiverChecker
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/rubocop/cop/lint/utils/nil_receiver_checker.rb |
Overview
Utility class that checks if the receiver can’t be nil.
Constant Summary
-
NIL_METHODS =
# File 'lib/rubocop/cop/lint/utils/nil_receiver_checker.rb', line 9(nil.methods + %i[!]).to_set.freeze
Class Method Summary
Instance Attribute Summary
- #cant_be_nil? ⇒ Boolean readonly
Instance Method Summary
- #_cant_be_nil?(node, receiver) ⇒ Boolean private
- #else_branch?(node) ⇒ Boolean private
- #find_top_if(node) private
- #non_nil_method?(method_name) ⇒ Boolean private
- #sole_condition_of_parent_if?(node) ⇒ Boolean private
Constructor Details
.new(receiver, additional_nil_methods) ⇒ NilReceiverChecker
# File 'lib/rubocop/cop/lint/utils/nil_receiver_checker.rb', line 11
def initialize(receiver, additional_nil_methods) @receiver = receiver @additional_nil_methods = additional_nil_methods @checked_nodes = {}.compare_by_identity end
Instance Attribute Details
#cant_be_nil? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'lib/rubocop/cop/lint/utils/nil_receiver_checker.rb', line 17
def cant_be_nil? sole_condition_of_parent_if?(@receiver) || _cant_be_nil?(@receiver.parent, @receiver) end
Instance Method Details
#_cant_be_nil?(node, receiver) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/lint/utils/nil_receiver_checker.rb', line 24
def _cant_be_nil?(node, receiver) return false unless node # For some nodes, we check their parent and then some children for these parents. # This is added to avoid infinite loops. return false if @checked_nodes.key?(node) @checked_nodes[node] = true case node.type when :def, :class, :module, :sclass return false when :send return non_nil_method?(node.method_name) if node.receiver == receiver node.arguments.each do |argument| return true if _cant_be_nil?(argument, receiver) end return true if _cant_be_nil?(node.receiver, receiver) when :begin return true if _cant_be_nil?(node.children.first, receiver) when :if, :case return true if _cant_be_nil?(node.condition, receiver) when :and, :or return true if _cant_be_nil?(node.lhs, receiver) when :pair if _cant_be_nil?(node.key, receiver) || _cant_be_nil?(node.value, receiver) return true end when :when node.each_condition do |condition| return true if _cant_be_nil?(condition, receiver) end when :lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn return true if _cant_be_nil?(node.expression, receiver) end # Due to how `if/else` are implemented (`elsif` is a child of `if` or another `elsif`), # using left_siblings will not work correctly for them. if !else_branch?(node) || (node.if_type? && !node.elsif?) node.left_siblings.reverse_each do |sibling| next unless sibling.is_a?(AST::Node) return true if _cant_be_nil?(sibling, receiver) end end if node.parent _cant_be_nil?(node.parent, receiver) else false end end
#else_branch?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/lint/utils/nil_receiver_checker.rb', line 108
def else_branch?(node) node.parent&.if_type? && node.parent.else_branch == node end
#find_top_if(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/lint/utils/nil_receiver_checker.rb', line 112
def find_top_if(node) node = node.parent while node.elsif? node end
#non_nil_method?(method_name) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/lint/utils/nil_receiver_checker.rb', line 81
def non_nil_method?(method_name) !NIL_METHODS.include?(method_name) && !@additional_nil_methods.include?(method_name) end
#sole_condition_of_parent_if?(node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/lint/utils/nil_receiver_checker.rb', line 86
def sole_condition_of_parent_if?(node) parent = node.parent while parent if parent.if_type? if parent.condition == node return true elsif parent.elsif? parent = find_top_if(parent) end elsif else_branch?(parent) # Find the top `if` for `else`. parent = parent.parent end parent = parent&.parent end false end