class RuboCop::Cop::Style::DoubleNegation
Checks for uses of double negation (‘!!`) to convert something to a boolean value.
When using ‘EnforcedStyle: allowed_in_returns`, allow double negation in contexts that use boolean as a return value. When using `EnforcedStyle: forbidden`, double negation should be forbidden always.
NOTE: when ‘something` is a boolean value `!!something` and `!something.nil?` are not the same thing. As you’re unlikely to write code that can accept values of any type this is rarely a problem in practice.
@safety
Autocorrection is unsafe when the value is `false`, because the result of the expression will change. [source,ruby] ---- !!false #=> false !false.nil? #=> true ----
@example
# bad !!something # good !something.nil?
@example EnforcedStyle: allowed_in_returns (default)
# good def foo? !!return_value end define_method :foo? do !!return_value end define_singleton_method :foo? do !!return_value end
@example EnforcedStyle: forbidden
# bad def foo? !!return_value end define_method :foo? do !!return_value end define_singleton_method :foo? do !!return_value end
Constants
- MSG
- RESTRICT_ON_SEND
Public Instance Methods
Source
# File lib/rubocop/cop/style/double_negation.rb, line 71 def on_send(node) return unless double_negative?(node) && node.prefix_bang? return if style == :allowed_in_returns && allowed_in_returns?(node) location = node.loc.selector add_offense(location) do |corrector| corrector.remove(location) corrector.insert_after(node, '.nil?') end end
Private Instance Methods
Source
# File lib/rubocop/cop/style/double_negation.rb, line 84 def allowed_in_returns?(node) node.parent&.return_type? || end_of_method_definition?(node) end
Source
# File lib/rubocop/cop/style/double_negation.rb, line 111 def define_method?(node) return false unless node.any_block_type? child = node.child_nodes.first return false unless child.send_type? child.method?(:define_method) || child.method?(:define_singleton_method) end
Source
# File lib/rubocop/cop/style/double_negation.rb, line 138 def double_negative_condition_return_value?(node, last_child, conditional_node) parent = find_parent_not_enumerable(node) if parent.begin_type? node.loc.line == parent.loc.last_line else last_child.last_line <= conditional_node.last_line end end
Source
# File lib/rubocop/cop/style/double_negation.rb, line 88 def end_of_method_definition?(node) return false unless (def_node = find_def_node_from_ascendant(node)) conditional_node = find_conditional_node_from_ascendant(node) last_child = find_last_child(def_node.send_type? ? def_node : def_node.body) if conditional_node double_negative_condition_return_value?(node, last_child, conditional_node) elsif last_child.type?(:pair, :hash) || last_child.parent.array_type? false else last_child.last_line <= node.last_line end end
Source
# File lib/rubocop/cop/style/double_negation.rb, line 120 def find_conditional_node_from_ascendant(node) return unless (parent = node.parent) return parent if parent.conditional? find_conditional_node_from_ascendant(parent) end
Source
# File lib/rubocop/cop/style/double_negation.rb, line 103 def find_def_node_from_ascendant(node) return unless (parent = node.parent) return parent if parent.any_def_type? return node.parent.child_nodes.first if define_method?(parent) find_def_node_from_ascendant(node.parent) end
Source
# File lib/rubocop/cop/style/double_negation.rb, line 127 def find_last_child(node) case node.type when :rescue find_last_child(node.body) when :ensure find_last_child(node.child_nodes.first) else node.child_nodes.last end end
Source
# File lib/rubocop/cop/style/double_negation.rb, line 147 def find_parent_not_enumerable(node) return unless (parent = node.parent) if parent.type?(:pair, :hash, :array) find_parent_not_enumerable(parent) else parent end end