Class: Shirobai::Cop::Layout::TrailingEmptyLines
- Inherits:
-
RuboCop::Cop::Base
- Object
- RuboCop::Cop::Base
- Shirobai::Cop::Layout::TrailingEmptyLines
- Extended by:
- RuboCop::Cop::AutoCorrector
- Includes:
- RuboCop::Cop::ConfigurableEnforcedStyle, RuboCop::Cop::RangeHelp
- Defined in:
- lib/shirobai/cop/layout/trailing_empty_lines.rb
Overview
Drop-in Rust reimplementation of ‘Layout/TrailingEmptyLines`.
The cop touches no AST: stock’s ‘on_new_investigation` looks only at the source buffer’s trailing whitespace. Rust performs the whole byte scan and returns at most one record — the reported caret range, the autocorrect range and its replacement text, and the ‘blank_lines` count that selects the message. Ruby reports the offense and applies the single `corrector.replace`, exactly like stock.
‘EnforcedStyle` (`final_newline` wants 0 trailing blank lines, `final_blank_line` wants 1) is validated through the genuine `ConfigurableEnforcedStyle#style` accessor before the bundle config is derived, so an unrecognized style raises the same error stock would.
Stock reads ‘processed_source.buffer.source`, which the parser normalizes (CRLF `rn` -> `n`, BOM stripping). The bundle, like every cop, runs on `raw_source`; when the parser normalized the source those two differ and the trailing-whitespace byte positions would not line up. So this cop is bundle-eligible only when the buffer source is byte-identical to the raw source (the common case — no CRLF/BOM); otherwise it falls back to a standalone scan of `buffer.source` with offsets converted against the same string. Either way the result is purely config-driven and stateless, so the autocorrect re-passes (fresh `ProcessedSource`) recompute correctly.
Constant Summary collapse
- STYLES =
{ "final_newline" => 0, "final_blank_line" => 1 }.freeze
Class Method Summary collapse
- .badge ⇒ Object
-
.bundle_args(config) ⇒ Object
Packed config nums: ‘[style]`.
- .cop_name ⇒ Object
Instance Method Summary collapse
Class Method Details
.badge ⇒ Object
40 |
# File 'lib/shirobai/cop/layout/trailing_empty_lines.rb', line 40 def self.badge = RuboCop::Cop::Badge.parse("Layout/TrailingEmptyLines") |
.bundle_args(config) ⇒ Object
Packed config nums: ‘[style]`. An unrecognized `EnforcedStyle` defaults to `final_newline` here; the genuine error is raised by the `style` accessor in `on_new_investigation` before this is consulted.
45 46 47 48 |
# File 'lib/shirobai/cop/layout/trailing_empty_lines.rb', line 45 def self.bundle_args(config) cop_config = config.for_badge(badge) [[STYLES.fetch(cop_config["EnforcedStyle"] || "final_newline", 0)]] end |
.cop_name ⇒ Object
39 |
# File 'lib/shirobai/cop/layout/trailing_empty_lines.rb', line 39 def self.cop_name = "Layout/TrailingEmptyLines" |
Instance Method Details
#on_new_investigation ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/shirobai/cop/layout/trailing_empty_lines.rb', line 50 def on_new_investigation # Validate `EnforcedStyle` through the genuine accessor first: stock # raises for an unrecognized style, and this must fire before we derive # the bundle config (which would otherwise mask it). style buffer = processed_source.buffer # Offsets are byte positions into the string the check scanned. On the # bundle path that is `raw_source` (byte-identical to `buffer.source` # there); converting against `raw_source` shares the single-slot # `SourceOffsets` cache with the other bundled cops. On the CRLF/BOM # fallback the check scanned `buffer.source`, so convert against that. off = SourceOffsets.for(bundle_eligible? ? processed_source.raw_source : buffer.source) resolved_result.each do |report_start, report_end, ac_start, ac_end, replacement, blank_lines| report_range = Parser::Source::Range.new(buffer, off[report_start], off[report_end]) autocorrect_range = Parser::Source::Range.new(buffer, off[ac_start], off[ac_end]) add_offense(report_range, message: (blank_lines)) do |corrector| corrector.replace(autocorrect_range, replacement) end end end |