Class: RuboCop::Cop::Performance::CaseWhenSplat

Inherits:
Cop
  • Object
show all
Includes:
Alignment
Defined in:
lib/rubocop/cop/performance/case_when_splat.rb

Overview

Place when conditions that use splat at the end of the list of when branches.

Ruby has to allocate memory for the splat expansion every time that the case when statement is run. Since Ruby does not support fall through inside of case when, like some other languages do, the order of the when branches does not matter. By placing any splat expansions at the end of the list of when branches we will reduce the number of times that memory has to be allocated for the expansion.

This is not a guaranteed performance improvement. If the data being processed by the case condition is normalized in a manner that favors hitting a condition in the splat expansion, it is possible that moving the splat condition to the end will use more memory, and run slightly slower.

Examples:

# bad
case foo
when *condition
  bar
when baz
  foobar
end

case foo
when *[1, 2, 3, 4]
  bar
when 5
  baz
end

# good
case foo
when baz
  foobar
when *condition
  bar
end

case foo
when 1, 2, 3, 4
  bar
when 5
  baz
end

Constant Summary collapse

MSG =
'Place `when` conditions with a splat ' \
'at the end of the `when` branches.'.freeze
ARRAY_MSG =
'Do not expand array literals in `when` conditions.'.freeze

Constants included from Util

Util::ASGN_NODES, Util::BYTE_ORDER_MARK, Util::CONDITIONAL_NODES, Util::EQUALS_ASGN_NODES, Util::LITERAL_REGEX, Util::LOGICAL_OPERATOR_NODES, Util::MODIFIER_NODES, Util::OPERATOR_METHODS, Util::SHORTHAND_ASGN_NODES

Instance Attribute Summary

Attributes inherited from Cop

#config, #corrections, #offenses, #processed_source

Instance Method Summary collapse

Methods inherited from Cop

#add_offense, all, autocorrect_incompatible_with, badge, #config_to_allow_offenses, #config_to_allow_offenses=, #cop_config, cop_name, #cop_name, #correct, department, #duplicate_location?, #excluded_file?, #find_location, #highlights, inherited, #initialize, #join_force?, lint?, match?, #message, #messages, non_rails, #parse, qualified_cop_name, #relevant_file?, #target_rails_version, #target_ruby_version

Methods included from AST::Sexp

#s

Methods included from NodePattern::Macros

#def_node_matcher, #def_node_search, #node_search, #node_search_all, #node_search_body, #node_search_first

Methods included from AutocorrectLogic

#autocorrect?, #autocorrect_enabled?, #autocorrect_requested?, #support_autocorrect?

Methods included from IgnoredNode

#ignore_node, #ignored_node?, #part_of_ignored_node?

Methods included from Util

begins_its_line?, comment_line?, double_quotes_required?, effective_column, ends_its_line?, escape_string, first_part_of_call_chain, interpret_string_escapes, line_range, needs_escaping?, on_node, operator?, parentheses?, parenthesized_call?, precede?, range_between, range_by_whole_lines, range_with_surrounding_comma, range_with_surrounding_space, same_line?, source_range, strip_quotes, stripped_source_upto, symbol_without_quote?, to_string_literal, to_supported_styles, to_symbol_literal, within_node?

Methods included from PathUtil

absolute?, find_file_upwards, match_path?, pwd, relative_path, reset_pwd, smart_path

Constructor Details

This class inherits a constructor from RuboCop::Cop::Cop

Instance Method Details

#autocorrect(when_node) ⇒ Object



71
72
73
74
75
76
77
78
79
# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 71

def autocorrect(when_node)
  lambda do |corrector|
    if needs_reorder?(when_node)
      reorder_condition(corrector, when_node)
    else
      inline_fix_branch(corrector, when_node)
    end
  end
end

#on_case(case_node) ⇒ Object



60
61
62
63
64
65
66
67
68
69
# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 60

def on_case(case_node)
  when_conditions = case_node.when_branches.flat_map(&:conditions)

  splat_offenses(when_conditions).reverse_each do |condition|
    range = condition.parent.loc.keyword.join(condition.source_range)
    variable, = *condition
    message = variable.array_type? ? ARRAY_MSG : MSG
    add_offense(condition.parent, location: range, message: message)
  end
end