class RuboCop::Cop::Style::ParallelAssignment
Checks for simple usages of parallel assignment. This will only complain when the number of variables being assigned matched the number of assigning variables.
@example
# bad a, b, c = 1, 2, 3 a, b, c = [1, 2, 3] # good one, two = *foo a, b = foo() a, b = b, a a = 1 b = 2 c = 3
Constants
- MSG
Public Instance Methods
autocorrect(node)
click to toggle source
# File lib/rubocop/cop/style/parallel_assignment.rb, line 57 def autocorrect(node) lambda do |corrector| left, right = *node left_elements = *left right_elements = [*right].compact order = find_valid_order(left_elements, right_elements) assignment_corrector = if modifier_statement?(node.parent) ModifierCorrector.new(node, config, order) elsif rescue_modifier?(node.parent) RescueCorrector.new(node, config, order) else GenericCorrector.new(node, config, order) end corrector.replace(assignment_corrector.correction_range, assignment_corrector.correction) end end
on_masgn(node)
click to toggle source
# File lib/rubocop/cop/style/parallel_assignment.rb, line 30 def on_masgn(node) left, right = *node left_elements = *left right_elements = [*right].compact # edge case for one constant # only complain when the number of variables matches return if left_elements.size != right_elements.size # account for edge cases using one variable with a comma return if left_elements.size == 1 # account for edge case of Constant::CONSTANT return unless right.array_type? # allow mass assignment as the return of a method call return if right.block_type? || right.send_type? # allow mass assignment when using splat return if (left_elements + right_elements).any?(&:splat_type?) order = find_valid_order(left_elements, right_elements) # For `a, b = b, a` or similar, there is no valid order return if order.nil? add_offense(node, :expression) end
Private Instance Methods
find_valid_order(left_elements, right_elements)
click to toggle source
# File lib/rubocop/cop/style/parallel_assignment.rb, line 80 def find_valid_order(left_elements, right_elements) # arrange left_elements in an order such that no corresponding right # element refers to a left element earlier in the sequence # this can be done using an algorithm called a "topological sort" # fortunately for us, Ruby's stdlib contains an implementation assignments = left_elements.zip(right_elements) begin AssignmentSorter.new(assignments).tsort rescue TSort::Cyclic nil end end
modifier_statement?(node)
click to toggle source
# File lib/rubocop/cop/style/parallel_assignment.rb, line 140 def modifier_statement?(node) node && ((node.if_type? && modifier_if?(node)) || ((node.while_type? || node.until_type?) && modifier_while?(node))) end
modifier_while?(node)
click to toggle source
# File lib/rubocop/cop/style/parallel_assignment.rb, line 146 def modifier_while?(node) node.loc.respond_to?(:keyword) && %w(while until).include?(node.loc.keyword.source) && node.loc.respond_to?(:end) && node.loc.end.nil? end
rescue_modifier?(node)
click to toggle source
# File lib/rubocop/cop/style/parallel_assignment.rb, line 152 def rescue_modifier?(node) node && node.rescue_type? && (node.parent.nil? || !node.parent.kwbegin_type?) end