Module: RuboCop::Cop::Asjer::RailsClassOrderCorrector
- Included in:
- RailsClassOrder
- Defined in:
- lib/rubocop/cop/asjer/rails_class_order.rb
Overview
Autocorrect helpers for RailsClassOrder cop
Instance Method Summary collapse
- #autocorrect(corrector, body, original, sorted) ⇒ Object
- #build_sorted_source(sorted, reference_targets) ⇒ Object
- #collect_adjacent_comments(node_pos) ⇒ Object
- #comments_before_node(node_pos) ⇒ Object
- #correction_range_for(ordered_targets) ⇒ Object
- #format_grouped_source(grouped, indent) ⇒ Object
- #full_method_range(node) ⇒ Object
- #normalize_interstitial_chunk(chunk) ⇒ Object
- #ordered_target_nodes(original) ⇒ Object
- #preceding_comments(node) ⇒ Object
- #preserved_interstitial_source(ordered_targets) ⇒ Object
- #range_with_comments(node) ⇒ Object
- #rebuilt_source(sorted, ordered_targets, trailing_sibling:) ⇒ Object
- #skip_trailing_blank_lines(source, pos) ⇒ Object
- #source_with_comments(node) ⇒ Object
- #trailing_blank_line?(source) ⇒ Boolean
- #trailing_sibling?(body, last_target) ⇒ Boolean
- #trim_trailing_newlines(source) ⇒ Object
Instance Method Details
#autocorrect(corrector, body, original, sorted) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 95 def autocorrect(corrector, body, original, sorted) ordered_targets = ordered_target_nodes(original) corrector.replace( correction_range_for(ordered_targets), rebuilt_source( sorted, ordered_targets, trailing_sibling: trailing_sibling?(body, ordered_targets.last) ) ) end |
#build_sorted_source(sorted, reference_targets) ⇒ Object
160 161 162 163 164 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 160 def build_sorted_source(sorted, reference_targets) indent = ' ' * reference_targets.first.loc.column grouped = sorted.group_by { |m| method_type(m) } format_grouped_source(grouped, indent) end |
#collect_adjacent_comments(node_pos) ⇒ Object
128 129 130 131 132 133 134 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 128 def collect_adjacent_comments(node_pos) expected_line = node_pos.first_line - 1 comments_before_node(node_pos).take_while do |comment| pos = comment.loc.expression (pos.last_line == expected_line).tap { expected_line = pos.first_line - 1 } end.reverse end |
#comments_before_node(node_pos) ⇒ Object
136 137 138 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 136 def comments_before_node(node_pos) processed_source.comments.select { |c| c.loc.expression.end_pos < node_pos.begin_pos }.reverse end |
#correction_range_for(ordered_targets) ⇒ Object
109 110 111 112 113 114 115 116 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 109 def correction_range_for(ordered_targets) # Stop at the last expression boundary so any newline/blank-line # suffix after the final target stays in the surrounding source. range_between( range_with_comments(ordered_targets.first).begin_pos, range_with_comments(ordered_targets.last).end_pos ) end |
#format_grouped_source(grouped, indent) ⇒ Object
213 214 215 216 217 218 219 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 213 def format_grouped_source(grouped, indent) self.class::TYPE_ORDER.keys.filter_map do |type| next unless grouped[type]&.any? grouped[type].map { |m| source_with_comments(m) }.join("\n#{indent}") end.join("\n\n#{indent}") end |
#full_method_range(node) ⇒ Object
140 141 142 143 144 145 146 147 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 140 def full_method_range(node) range = range_with_comments(node) source = processed_source.buffer.source line_start = source.rindex("\n", range.begin_pos - 1)&.+(1) || 0 end_pos = source[range.end_pos] == "\n" ? range.end_pos + 1 : range.end_pos range_between(line_start, skip_trailing_blank_lines(source, end_pos)) end |
#normalize_interstitial_chunk(chunk) ⇒ Object
205 206 207 208 209 210 211 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 205 def normalize_interstitial_chunk(chunk) return if chunk.nil? || chunk.strip.empty? # Strip leading blank lines only; trailing ones stay attached so later # preserved chunks keep their separator spacing. chunk.sub(/\A(?:[ \t]*\n)+/, '') end |
#ordered_target_nodes(original) ⇒ Object
107 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 107 def ordered_target_nodes(original) = original.sort_by { |method| full_method_range(method).begin_pos } |
#preceding_comments(node) ⇒ Object
126 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 126 def preceding_comments(node) = collect_adjacent_comments(node.loc.expression) |
#preserved_interstitial_source(ordered_targets) ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 193 def preserved_interstitial_source(ordered_targets) source = processed_source.buffer.source ordered_targets .map { |method| full_method_range(method) } .each_cons(2) .filter_map do |left, right| normalize_interstitial_chunk(source[left.end_pos...right.begin_pos]) end .join end |
#range_with_comments(node) ⇒ Object
120 121 122 123 124 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 120 def range_with_comments(node) comments = preceding_comments(node) start_pos = comments.empty? ? node.loc.expression.begin_pos : comments.first.loc.expression.begin_pos range_between(start_pos, node.loc.expression.end_pos) end |
#rebuilt_source(sorted, ordered_targets, trailing_sibling:) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 166 def rebuilt_source(sorted, ordered_targets, trailing_sibling:) preserved = preserved_interstitial_source(ordered_targets) rebuilt = [ build_sorted_source(sorted, ordered_targets).rstrip, preserved ].reject(&:empty?).join("\n\n") trimmed = trim_trailing_newlines(rebuilt) # Keep end-of-class output flush unless the final preserved chunk # already carried a trailing blank line before it was moved. return trimmed if trailing_sibling || !trailing_blank_line?(preserved) "#{trimmed}\n" end |
#skip_trailing_blank_lines(source, pos) ⇒ Object
149 150 151 152 153 154 155 156 157 158 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 149 def skip_trailing_blank_lines(source, pos) while pos < source.length line_end = source.index("\n", pos) break unless line_end break unless source[pos...line_end].strip.empty? pos = line_end + 1 end pos end |
#source_with_comments(node) ⇒ Object
221 222 223 224 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 221 def source_with_comments(node) range = range_with_comments(node) processed_source.buffer.source[range.begin_pos...range.end_pos].lstrip end |
#trailing_blank_line?(source) ⇒ Boolean
187 188 189 190 191 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 187 def trailing_blank_line?(source) return false unless source&.end_with?("\n") source[(source.rindex("\n", source.length - 2)&.+(1) || 0)...-1].strip.empty? end |
#trailing_sibling?(body, last_target) ⇒ Boolean
118 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 118 def trailing_sibling?(body, last_target) = body.children.index(last_target) < body.children.size - 1 |
#trim_trailing_newlines(source) ⇒ Object
181 182 183 184 185 |
# File 'lib/rubocop/cop/asjer/rails_class_order.rb', line 181 def trim_trailing_newlines(source) trimmed = source.dup trimmed.chop! while trimmed.end_with?("\n") trimmed end |