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
‘lhs` is an assignment method call like `obj.attr=` or `ary=`.
-
#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=`. 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 _ $_) (_ $_)}' |