rubocop-asjer 0.4.3 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f00a4effbc757a8aee4981d7b2c20608298f8b8a29c7c9399ac3fcdc9444313f
4
- data.tar.gz: d2c05a6ec5e488ffb464b086c59b851563e08ba8b13920bb6caf36bdb20d8d8a
3
+ metadata.gz: e5ca85da8803a2b7cf65f61600adea61a52c32cd8c327b5e42d83b84a312035c
4
+ data.tar.gz: 82c413cfd54796c72251bfb67b53ac369a829e41ea64e91265de42dbebea1810
5
5
  SHA512:
6
- metadata.gz: 2c0d217cb4de61f093339f34a3e667f46c69e3e9f7ca28c33240d9417509cc7d564a058e1f8a37b56a11a64c1c465c62705aa786f5d50bd4a2d714378f625017
7
- data.tar.gz: ac1517e3467076ac9b5ab78d764e06461d908762413ebf09dc961c1bb3d64ba0a0080beea7ac19074b3852b32eab052d82f1881bd57884e94da9f13b9ae8c7fc
6
+ metadata.gz: 78f2ca3c66f118973d282f8e1ce6ad7e79a47a2c8e4e627c7aa25c006bb914d80ff2c0afde079cb47e5ace29b191d4565fc87f028a6fdc362816103e4f271846
7
+ data.tar.gz: fb1910e981dca843eeb1b0425d098b7d4fed04c96d3ee1e6b2bf15dda990b4ff92ea30db3fadfde05d36ef1772ecfe3d255a4f750910af1d0117839f91e9b72a
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.4.3"
2
+ ".": "0.4.5"
3
3
  }
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.5](https://github.com/asjer/rubocop-asjer/compare/v0.4.4...v0.4.5) (2026-03-08)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **rails_class_order:** prevent autocorrect from deleting interleaved non-target lines ([f7f1628](https://github.com/asjer/rubocop-asjer/commit/f7f162842e2188e99b24a53e55650bcaa678253f))
9
+
10
+ ## [0.4.4](https://github.com/asjer/rubocop-asjer/compare/v0.4.3...v0.4.4) (2026-02-10)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * prevent excessive blank lines after autocorrect in `RailsClassOrder` cop ([56f6def](https://github.com/asjer/rubocop-asjer/commit/56f6deff1fab470ea5c7deac175d1d0088cd11f5))
16
+
3
17
  ## [0.4.3](https://github.com/asjer/rubocop-asjer/compare/v0.4.2...v0.4.3) (2026-01-28)
4
18
 
5
19
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Asjer
5
- VERSION = '0.4.3'
5
+ VERSION = '0.4.5'
6
6
  end
7
7
  end
@@ -93,24 +93,37 @@ module RuboCop
93
93
  # Autocorrect helpers for RailsClassOrder cop
94
94
  module RailsClassOrderCorrector
95
95
  def autocorrect(corrector, body, original, sorted)
96
- first_target = original.min_by { |m| body.children.index(m) }
97
- new_source = build_sorted_source(sorted, original)
98
- corrector.replace(range_with_comments(first_target), new_source.rstrip)
96
+ ordered_targets = ordered_target_nodes(original)
97
+ corrector.replace(
98
+ correction_range_for(ordered_targets),
99
+ rebuilt_source(
100
+ sorted,
101
+ ordered_targets,
102
+ trailing_sibling: trailing_sibling?(body, ordered_targets.last)
103
+ )
104
+ )
105
+ end
99
106
 
100
- (original - [first_target]).each do |method|
101
- corrector.remove(full_method_range(method))
102
- end
107
+ def ordered_target_nodes(original) = original.sort_by { |method| full_method_range(method).begin_pos }
108
+
109
+ def correction_range_for(ordered_targets)
110
+ # Stop at the last expression boundary so any newline/blank-line
111
+ # suffix after the final target stays in the surrounding source.
112
+ range_between(
113
+ range_with_comments(ordered_targets.first).begin_pos,
114
+ range_with_comments(ordered_targets.last).end_pos
115
+ )
103
116
  end
104
117
 
118
+ def trailing_sibling?(body, last_target) = body.children.index(last_target) < body.children.size - 1
119
+
105
120
  def range_with_comments(node)
106
121
  comments = preceding_comments(node)
107
122
  start_pos = comments.empty? ? node.loc.expression.begin_pos : comments.first.loc.expression.begin_pos
108
123
  range_between(start_pos, node.loc.expression.end_pos)
109
124
  end
110
125
 
111
- def preceding_comments(node)
112
- collect_adjacent_comments(node.loc.expression)
113
- end
126
+ def preceding_comments(node) = collect_adjacent_comments(node.loc.expression)
114
127
 
115
128
  def collect_adjacent_comments(node_pos)
116
129
  expected_line = node_pos.first_line - 1
@@ -129,15 +142,74 @@ module RuboCop
129
142
  source = processed_source.buffer.source
130
143
  line_start = source.rindex("\n", range.begin_pos - 1)&.+(1) || 0
131
144
  end_pos = source[range.end_pos] == "\n" ? range.end_pos + 1 : range.end_pos
132
- range_between(line_start, end_pos)
145
+
146
+ range_between(line_start, skip_trailing_blank_lines(source, end_pos))
133
147
  end
134
148
 
135
- def build_sorted_source(sorted, original)
136
- indent = ' ' * original.first.loc.column
149
+ def skip_trailing_blank_lines(source, pos)
150
+ while pos < source.length
151
+ line_end = source.index("\n", pos)
152
+ break unless line_end
153
+ break unless source[pos...line_end].strip.empty?
154
+
155
+ pos = line_end + 1
156
+ end
157
+ pos
158
+ end
159
+
160
+ def build_sorted_source(sorted, reference_targets)
161
+ indent = ' ' * reference_targets.first.loc.column
137
162
  grouped = sorted.group_by { |m| method_type(m) }
138
163
  format_grouped_source(grouped, indent)
139
164
  end
140
165
 
166
+ def rebuilt_source(sorted, ordered_targets, trailing_sibling:)
167
+ preserved = preserved_interstitial_source(ordered_targets)
168
+ rebuilt = [
169
+ build_sorted_source(sorted, ordered_targets).rstrip,
170
+ preserved
171
+ ].reject(&:empty?).join("\n\n")
172
+ trimmed = trim_trailing_newlines(rebuilt)
173
+
174
+ # Keep end-of-class output flush unless the final preserved chunk
175
+ # already carried a trailing blank line before it was moved.
176
+ return trimmed if trailing_sibling || !trailing_blank_line?(preserved)
177
+
178
+ "#{trimmed}\n"
179
+ end
180
+
181
+ def trim_trailing_newlines(source)
182
+ trimmed = source.dup
183
+ trimmed.chop! while trimmed.end_with?("\n")
184
+ trimmed
185
+ end
186
+
187
+ def trailing_blank_line?(source)
188
+ return false unless source&.end_with?("\n")
189
+
190
+ source[(source.rindex("\n", source.length - 2)&.+(1) || 0)...-1].strip.empty?
191
+ end
192
+
193
+ def preserved_interstitial_source(ordered_targets)
194
+ source = processed_source.buffer.source
195
+
196
+ ordered_targets
197
+ .map { |method| full_method_range(method) }
198
+ .each_cons(2)
199
+ .filter_map do |left, right|
200
+ normalize_interstitial_chunk(source[left.end_pos...right.begin_pos])
201
+ end
202
+ .join
203
+ end
204
+
205
+ def normalize_interstitial_chunk(chunk)
206
+ return if chunk.nil? || chunk.strip.empty?
207
+
208
+ # Strip leading blank lines only; trailing ones stay attached so later
209
+ # preserved chunks keep their separator spacing.
210
+ chunk.sub(/\A(?:[ \t]*\n)+/, '')
211
+ end
212
+
141
213
  def format_grouped_source(grouped, indent)
142
214
  self.class::TYPE_ORDER.keys.filter_map do |type|
143
215
  next unless grouped[type]&.any?
data/mise.toml ADDED
@@ -0,0 +1,2 @@
1
+ [env]
2
+ _.path = ["{{cwd}}/bin"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-asjer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Asjer Querido
@@ -58,6 +58,7 @@ files:
58
58
  - lib/rubocop/asjer/version.rb
59
59
  - lib/rubocop/cop/asjer/no_default_translation.rb
60
60
  - lib/rubocop/cop/asjer/rails_class_order.rb
61
+ - mise.toml
61
62
  - release-please-config.json
62
63
  - sig/rubocop/i18n.rbs
63
64
  homepage: https://github.com/asjer/rubocop-asjer