class RuboCop::Cop::Style::MultipleComparison
Checks against comparing a variable with multiple items, where ‘Array#include?`, `Set#include?` or a `case` could be used instead to avoid code repetition. It accepts comparisons of multiple method calls to avoid unnecessary method calls by default. It can be configured by `AllowMethodComparison` option.
@example
# bad a = 'a' foo if a == 'a' || a == 'b' || a == 'c' # good a = 'a' foo if ['a', 'b', 'c'].include?(a) VALUES = Set['a', 'b', 'c'].freeze # elsewhere... foo if VALUES.include?(a) case foo when 'a', 'b', 'c' then foo # ... end # accepted (but consider `case` as above) foo if a == b.lightweight || a == b.heavyweight
@example AllowMethodComparison: true (default)
# good foo if a == b.lightweight || a == b.heavyweight
@example AllowMethodComparison: false
# bad foo if a == b.lightweight || a == b.heavyweight # good foo if [b.lightweight, b.heavyweight].include?(a)
@example ComparisonsThreshold: 2 (default)
# bad foo if a == 'a' || a == 'b'
@example ComparisonsThreshold: 3
# good foo if a == 'a' || a == 'b'
Constants
- MSG
Public Instance Methods
on_or(node)
click to toggle source
# File lib/rubocop/cop/style/multiple_comparison.rb, line 58 def on_or(node) root_of_or_node = root_of_or_node(node) return unless node == root_of_or_node return unless nested_comparison?(node) return unless (variable, values = find_offending_var(node)) return if values.size < comparisons_threshold add_offense(node) do |corrector| elements = values.map(&:source).join(', ') prefer_method = "[#{elements}].include?(#{variable_name(variable)})" corrector.replace(node, prefer_method) end end
Private Instance Methods
allow_method_comparison?()
click to toggle source
# File lib/rubocop/cop/style/multiple_comparison.rb, line 142 def allow_method_comparison? cop_config.fetch('AllowMethodComparison', true) end
comparison?(node)
click to toggle source
# File lib/rubocop/cop/style/multiple_comparison.rb, line 121 def comparison?(node) simple_comparison?(node) || nested_comparison?(node) end
comparisons_threshold()
click to toggle source
# File lib/rubocop/cop/style/multiple_comparison.rb, line 146 def comparisons_threshold cop_config.fetch('ComparisonsThreshold', 2) end
find_offending_var(node, variables = Set.new, values = [])
click to toggle source
rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# File lib/rubocop/cop/style/multiple_comparison.rb, line 90 def find_offending_var(node, variables = Set.new, values = []) if node.or_type? find_offending_var(node.lhs, variables, values) find_offending_var(node.rhs, variables, values) elsif simple_double_comparison?(node) return elsif (var, obj = simple_comparison?(node)) return if allow_method_comparison? && obj.send_type? variables << var return if variables.size > 1 values << obj end [variables.first, values] if variables.any? end
nested_comparison?(node)
click to toggle source
# File lib/rubocop/cop/style/multiple_comparison.rb, line 113 def nested_comparison?(node) if node.or_type? node.node_parts.all? { |node_part| comparison? node_part } else false end end
root_of_or_node(or_node)
click to toggle source
# File lib/rubocop/cop/style/multiple_comparison.rb, line 132 def root_of_or_node(or_node) return or_node unless or_node.parent if or_node.parent.or_type? root_of_or_node(or_node.parent) else or_node end end
simple_comparison?(node)
click to toggle source
# File lib/rubocop/cop/style/multiple_comparison.rb, line 125 def simple_comparison?(node) if (var, obj = simple_comparison_lhs?(node)) || (obj, var = simple_comparison_rhs?(node)) [var, obj] end end
variable_name(node)
click to toggle source
rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# File lib/rubocop/cop/style/multiple_comparison.rb, line 109 def variable_name(node) node.children[0] end