Class: RuboCop::Cop::Performance::CaseWhenSplat
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
AutoCorrector,
Base
|
|
Instance Chain:
self,
CommentsHelp,
RangeHelp,
Alignment,
Base
|
|
Inherits: |
Base
|
Defined in: | lib/rubocop/cop/performance/case_when_splat.rb |
Overview
Reordering when
conditions with a splat to the end
of the when
branches can improve performance.
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 should 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. The exception to this is if multiple of your when
conditions can be true for any given condition. A likely scenario for
this defining a higher level when condition to override a condition
that is inside of the splat expansion.
Constant Summary
-
ARRAY_MSG =
# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 65'Pass the contents of array literals directly to `when` conditions.'
-
MSG =
# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 64'Reordering `when` conditions with a splat to the end of the `when` branches can improve performance.'
Instance Method Summary
- #on_case(case_node)
- #autocorrect(corrector, when_node) private
- #indent_for(node) private
- #inline_fix_branch(corrector, when_node) private
- #needs_reorder?(when_node) ⇒ Boolean private
- #new_branch_without_then(node, new_condition) private
- #new_condition_with_then(node, new_condition) private
- #non_splat?(condition) ⇒ Boolean private
- #range(node) private
- #reorder_condition(corrector, when_node) private
- #reordering_correction(when_node) private
- #replacement(conditions) private
- #splat_offenses(when_conditions) private
- #when_branch_range(when_node) private
Instance Method Details
#autocorrect(corrector, when_node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 84
def autocorrect(corrector, when_node) if needs_reorder?(when_node) reorder_condition(corrector, when_node) else inline_fix_branch(corrector, when_node) end end
#indent_for(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 154
def indent_for(node) ' ' * node.loc.column end
#inline_fix_branch(corrector, when_node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 101
def inline_fix_branch(corrector, when_node) conditions = when_node.conditions range = range_between(conditions[0].source_range.begin_pos, conditions[-1].source_range.end_pos) corrector.replace(range, replacement(conditions)) end
#needs_reorder?(when_node) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 178
def needs_reorder?(when_node) following_branches = when_node.parent.when_branches[(when_node.branch_index + 1)..] following_branches.any? do |when_branch| when_branch.conditions.any? do |condition| non_splat?(condition) end end end
#new_branch_without_then(node, new_condition) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 144
def new_branch_without_then(node, new_condition) new_branch = "\n#{indent_for(node)}when #{new_condition}\n" if node.body "#{new_branch}#{indent_for(node.body)}#{node.body.source}" else new_branch end end
#new_condition_with_then(node, new_condition) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 140
def new_condition_with_then(node, new_condition) "\n#{indent_for(node)}when #{new_condition} then #{node.body.source}" end
#non_splat?(condition) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 172
def non_splat?(condition) variable, = *condition (condition.splat_type? && variable.array_type?) || !condition.splat_type? end
#on_case(case_node)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 67
def on_case(case_node) when_conditions = case_node.when_branches.flat_map(&:conditions) splat_offenses(when_conditions).reverse_each do |condition| next if ignored_node?(condition.parent) ignore_node(condition.parent) variable, = *condition = variable.array_type? ? ARRAY_MSG : MSG add_offense(range(condition), message: ) do |corrector| autocorrect(corrector, condition.parent) end end end
#range(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 92
def range(node) node.parent.loc.keyword.join(node.source_range) end
#reorder_condition(corrector, when_node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 108
def reorder_condition(corrector, when_node) when_branches = when_node.parent.when_branches return if when_branches.one? corrector.remove(when_branch_range(when_node)) corrector.insert_after(when_branches.last, reordering_correction(when_node)) end
#reordering_correction(when_node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 117
def reordering_correction(when_node) new_condition = replacement(when_node.conditions) condition = if same_line?(when_node, when_node.body) new_condition_with_then(when_node, new_condition) else new_branch_without_then(when_node, new_condition) end condition_comments = comments_in_range(when_node).map do |comment_node| "#{indent_for(comment_node)}#{comment_node.source}" end.join("\n") "#{condition}#{condition_comments}" end
#replacement(conditions) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 96
def replacement(conditions) reordered = conditions.partition(&:splat_type?).reverse reordered.flatten.map(&:source).join(', ') end
#splat_offenses(when_conditions) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 158
def splat_offenses(when_conditions) found_non_splat = false offenses = when_conditions.reverse.map do |condition| found_non_splat ||= non_splat?(condition) next if non_splat?(condition) condition if found_non_splat end offenses.compact end
#when_branch_range(when_node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/case_when_splat.rb', line 134
def when_branch_range(when_node) next_branch = when_node.parent.when_branches[when_node.branch_index + 1] range_between(when_node.source_range.begin_pos, next_branch.source_range.begin_pos) end