Class: RuboCop::Cop::Style::ParallelAssignment::AssignmentSorter
- Inherits:
-
Object
- Object
- RuboCop::Cop::Style::ParallelAssignment::AssignmentSorter
- Extended by:
- Macros
- Defined in:
- lib/rubocop/cop/style/parallel_assignment.rb
Overview
Topologically sorts the assignments with Kahn’s algorithm. en.wikipedia.org/wiki/Topological_sorting#Kahn’s_algorithm
Instance Method Summary collapse
-
#accesses?(rhs, lhs) ⇒ Boolean
lhsis an assignment method call likeobj.attr=orary[idx]=. -
#dependencies_for_assignment(assignment) ⇒ Object
Returns all the assignments which must come after
assignment(due to dependencies on the previous value of the assigned var). - #dependency?(lhs, rhs) ⇒ Boolean
-
#initialize(assignments) ⇒ AssignmentSorter
constructor
A new instance of AssignmentSorter.
- #matching_calls(node, receiver, method_name) ⇒ Object
- #tsort ⇒ Object
- #uses_var?(node) ⇒ Object
- #var_name(node) ⇒ Object
Constructor Details
#initialize(assignments) ⇒ AssignmentSorter
Returns a new instance of AssignmentSorter.
126 127 128 |
# 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?
173 174 175 176 177 178 179 180 181 182 183 |
# 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) ⇒ Object
Returns all the assignments which must come after assignment (due to dependencies on the previous value of the assigned var)
152 153 154 155 156 157 158 159 160 161 162 163 164 |
# 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
166 167 168 169 |
# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 166 def dependency?(lhs, rhs) uses_var?(rhs, var_name(lhs)) || (lhs.send_type? && lhs.assignment_method? && accesses?(rhs, lhs)) end |
#matching_calls(node, receiver, method_name) ⇒ Object
124 |
# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 124 def_node_search :matching_calls, '(send %1 %2 $...)' |
#tsort ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# 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) ⇒ Object
121 |
# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 121 def_node_search :uses_var?, '{({lvar ivar cvar gvar} %) (const _ %)}' |
#var_name(node) ⇒ Object
118 |
# File 'lib/rubocop/cop/style/parallel_assignment.rb', line 118 def_node_matcher :var_name, '{(casgn _ $_) (_ $_)}' |