Class: Shirobai::Cop::Layout::LeadingEmptyLines

Inherits:
RuboCop::Cop::Base
  • Object
show all
Extended by:
RuboCop::Cop::AutoCorrector
Includes:
RuboCop::Cop::RangeHelp, BundleEligible
Defined in:
lib/shirobai/cop/layout/leading_empty_lines.rb

Overview

Drop-in Rust reimplementation of Layout/LeadingEmptyLines.

Stock's on_new_investigation:

1. `token = processed_source.tokens[0]`.
2. `return unless token && token.line > 1`.
3. Emit one offense at `token.pos` whose corrector removes the
 range `[0, token.begin_pos)`.

The first token covers code keywords/identifiers, inline # comments, =begin/=end block comments, and (essentially) anything parser-gem's tokenizer reports. Files starting with __END__ carry no tokens at all, so the cop stays silent even when leading blank lines precede the marker.

Rust returns at most one tuple [start, end, ac_start, ac_end] (all byte offsets into the raw source); the wrapper just turns them into Parser::Source::Ranges and attaches the corrector. The byte→char conversion runs through SourceOffsets so BOM / multibyte files line up with parser-gem's character buffer indexing.

Constant Summary collapse

MSG =
"Unnecessary blank line at the beginning of the source."

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.badgeObject



34
# File 'lib/shirobai/cop/layout/leading_empty_lines.rb', line 34

def self.badge = RuboCop::Cop::Badge.parse(cop_name)

.bundle_args(_config) ⇒ Object

The cop is config-less from the Rust side — bundle_args returns an empty pair so it contributes nothing to nums / lists. Kept for the 4+1 single-source-of-config convention.



39
40
41
# File 'lib/shirobai/cop/layout/leading_empty_lines.rb', line 39

def self.bundle_args(_config)
  []
end

.cop_nameObject



33
# File 'lib/shirobai/cop/layout/leading_empty_lines.rb', line 33

def self.cop_name = "Layout/LeadingEmptyLines"

Instance Method Details

#on_new_investigationObject



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/shirobai/cop/layout/leading_empty_lines.rb', line 43

def on_new_investigation
  buffer = processed_source.buffer
  # On the bundle path Rust scanned `raw_source` (byte-identical to
  # `buffer.source`); on the CRLF/BOM fallback the standalone path
  # scans `buffer.source` instead so every offset Rust returns lines
  # up with the parser-gem buffer.
  source = bundle_eligible? ? processed_source.raw_source : buffer.source
  off = SourceOffsets.for(source)
  resolved_offenses.each do |start, fin, ac_start, ac_end|
    range = Parser::Source::Range.new(buffer, off[start], off[fin])
    ac_range = Parser::Source::Range.new(buffer, off[ac_start], off[ac_end])
    add_offense(range, message: MSG) do |corrector|
      corrector.remove(ac_range)
    end
  end
end