Class: RuboCop::Cop::Style::ParallelAssignment::AssignmentSorter
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
Macros
|
|
Inherits: | Object |
Defined in: | lib/rubocop/cop/style/parallel_assignment.rb |
Overview
Topologically sorts the assignments with Kahn’s algorithm. https://en.wikipedia.org/wiki/Topological_sorting#Kahn’s_algorithm
Class Method Summary
- .new(assignments) ⇒ AssignmentSorter constructor
Instance Method Summary
-
#accesses?(rhs, lhs) ⇒ Boolean
lhs
is an assignment method call likeobj.attr=
orary[idx]=
. -
#dependencies_for_assignment(assignment)
Returns all the assignments which must come after
assignment
(due to dependencies on the previous value of the assigned var). - #dependency?(lhs, rhs) ⇒ Boolean
- #matching_calls(node, receiver, method_name)
- #tsort
- #uses_var?(node)
- #var_name(node)
Constructor Details
.new(assignments) ⇒ AssignmentSorter
# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 126
def initialize(assignments) @assignments = assignments end
Instance Method Details
#accesses?(rhs, lhs) ⇒ Boolean
lhs
is an assignment method call like obj.attr=
or ary[idx]=
.
Does rhs
access the same value which is assigned by lhs
?
# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 173
def accesses?(rhs, lhs) if lhs.method?(:[]=) # FIXME: Workaround `rubocop:disable` comment for JRuby. # rubocop:disable Performance/RedundantEqualityComparisonBlock matching_calls(rhs, lhs.receiver, :[]).any? { |args| args == lhs.arguments } # rubocop:enable Performance/RedundantEqualityComparisonBlock else access_method = lhs.method_name.to_s.chop.to_sym matching_calls(rhs, lhs.receiver, access_method).any? end end
#dependencies_for_assignment(assignment)
Returns all the assignments which must come after assignment
(due to dependencies on the previous value of the assigned var)
# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 152
def dependencies_for_assignment(assignment) my_lhs, _my_rhs = *assignment @assignments.filter_map do |other| # Exclude self, there are no dependencies in cases such as `a, b = a, b`. next if other == assignment _other_lhs, other_rhs = *other next unless dependency?(my_lhs, other_rhs) other end end
#dependency?(lhs, rhs) ⇒ Boolean
#matching_calls(node, receiver, method_name)
[ GitHub ]# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 124
def_node_search :matching_calls, '(send %1 %2 $...)'
#tsort
[ GitHub ]# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 130
def tsort dependencies = @assignments.to_h do |assignment| [assignment, dependencies_for_assignment(assignment)] end result = [] while (matched_node, = dependencies.find { |_node, edges| edges.empty? }) dependencies.delete(matched_node) result.push(matched_node) dependencies.each do |node, edges| dependencies[node].delete(matched_node) if edges.include?(matched_node) end end # Cyclic dependency return nil if dependencies.any? result end
#uses_var?(node)
[ GitHub ]# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 121
def_node_search :uses_var?, '{({lvar ivar cvar gvar} %) (const _ %)}'
#var_name(node)
[ GitHub ]# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 118
def_node_matcher :var_name, '{(casgn _ $_) (_ $_)}'