Class: Shirobai::Cop::Layout::EmptyLineAfterMagicComment

Inherits:
RuboCop::Cop::Base
  • Object
show all
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: message(actual)) do |corrector|
    corrector.insert_before(offending_range, "\n" * (number_of_empty_lines - actual))
  end
end

#validate_config ⇒ Object

Raises:

  • (RuboCop::ValidationError)


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