Class: Shirobai::Cop::Layout::EmptyLineAfterMagicComment
- Inherits:
-
RuboCop::Cop::Base
- Object
- RuboCop::Cop::Base
- Shirobai::Cop::Layout::EmptyLineAfterMagicComment
- Extended by:
- RuboCop::Cop::AutoCorrector
- Includes:
- RuboCop::Cop::RangeHelp, BundleEligible
- Defined in:
- lib/shirobai/cop/layout/empty_line_after_magic_comment.rb
Overview
Drop-in Rust reimplementation of Layout/EmptyLineAfterMagicComment.
Rust pulls every comment that appears before the file's first AST
statement (or every comment when there are no statements) from the
shared parse cache and returns each as (start, end, line). The Ruby
wrapper finishes step 2 of stock's on_new_investigation: filter the
candidates via MagicComment.parse(text).any?, take the LAST match,
and count the blank lines right below it (processed_source[line]
onwards). When code follows and fewer than NumberOfEmptyLines
(default 1) blank lines separate it from the magic comment, emit an
offense at source_range(buffer, line + 1, 0) with
corrector.insert_before(range, "\n" * missing) — byte-identical to
stock.
MagicComment.parse is regex-heavy and supports three formats
(SimpleComment / EmacsComment / VimComment); keeping it on the Ruby
side reuses stock's implementation verbatim and avoids drift.
Constant Summary collapse
- MSG =
"Expected at least %<expected>d empty %<lines>s after magic comments; found " \ "%<actual>d."
Class Method Summary collapse
Instance Method Summary collapse
Class Method Details
.badge ⇒ Object
32 |
# File 'lib/shirobai/cop/layout/empty_line_after_magic_comment.rb', line 32 def self.badge = RuboCop::Cop::Badge.parse(cop_name) |
.bundle_args(_config) ⇒ Object
34 35 36 |
# File 'lib/shirobai/cop/layout/empty_line_after_magic_comment.rb', line 34 def self.bundle_args(_config) [] # config-less on the Rust side; `NumberOfEmptyLines` is read here end |
.cop_name ⇒ Object
31 |
# File 'lib/shirobai/cop/layout/empty_line_after_magic_comment.rb', line 31 def self.cop_name = "Layout/EmptyLineAfterMagicComment" |
Instance Method Details
#on_new_investigation ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/shirobai/cop/layout/empty_line_after_magic_comment.rb', line 47 def on_new_investigation candidates = resolved_candidates return if candidates.empty? # Find the last magic comment in document order (`reverse.find`). # The candidate slices come from the same buffer Rust scans # (raw_source on the bundle path, buffer.source on the fallback); # both are byte-identical to the bytes Rust used to compute the # ranges, so plain byte indexing is safe. source = bundle_eligible? ? processed_source.raw_source : processed_source.buffer.source last = nil candidates.reverse_each do |start, fin, line| text = source.byteslice(start, fin - start) next unless text && RuboCop::MagicComment.parse(text).any? last = [start, fin, line] break end return unless last _start, _fin, magic_line = last # `processed_source[magic_line]` (0-indexed access) is the line just # below the magic comment; count the blank run from there. actual = empty_lines_after(magic_line) # Trailing empty lines are `Layout/TrailingEmptyLines`' responsibility: # stock returns when nothing but blank lines (or EOF) follows. return unless processed_source[magic_line + actual] return if actual >= number_of_empty_lines buffer = processed_source.buffer offending_range = source_range(buffer, magic_line + 1, 0) add_offense(offending_range, message: (actual)) do |corrector| corrector.insert_before(offending_range, "\n" * (number_of_empty_lines - actual)) end end |
#validate_config ⇒ Object
38 39 40 41 42 43 44 45 |
# File 'lib/shirobai/cop/layout/empty_line_after_magic_comment.rb', line 38 def validate_config return if number_of_empty_lines.is_a?(Integer) && number_of_empty_lines.positive? raise RuboCop::ValidationError, "The `Layout/EmptyLineAfterMagicComment` cop only accepts a positive " \ "integer for its `NumberOfEmptyLines` configuration parameter, but " \ "`#{number_of_empty_lines.inspect}` was given." end |