Class: Shirobai::Cop::Layout::EmptyLineAfterGuardClause

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

Overview

Drop-in Rust reimplementation of Layout/EmptyLineAfterGuardClause.

Rust walks the AST and emits a candidate offense for every if/unless whose if_branch is a guard clause (raise/fail/return/break/ next, with and/or peeled to the rhs) UNLESS one of stock's correct_style? gates fires:

  • node.parent is nil, rescue, or ensure,
  • node.right_sibling is nil or sits under an if with else,
  • the right sibling is itself a guard-bearing if/unless.

Each candidate carries (a) the offense range stock passes to add_offense (the heredoc closer, the end keyword for a multi-line if/unless, or the whole node for the modifier form), and (b) the byte range stock's range_by_whole_lines spans plus the 1-based last_line driving the next_line_empty? check.

The wrapper finishes the directive-comment check (next_line_empty_or_allowed_directive_comment?): a blank line OR a # rubocop:enable / # :nocov: / # simplecov:disable / # simplecov:enable comment whose own next line is blank suppresses the offense. The autocorrect inserts "\n" after the guard's whole-line range, or after the directive comment line when present — byte-for-byte stock corrector behaviour.

Constant Summary collapse

MSG =
"Add empty line after guard clause."
SIMPLECOV_COMMENT_PATTERN =
/\A#\s*(?::nocov:|simplecov\s*:\s*(?:disable|enable)\b)/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.badgeObject



38
# File 'lib/shirobai/cop/layout/empty_line_after_guard_clause.rb', line 38

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

.bundle_args(_config) ⇒ Object



40
41
42
# File 'lib/shirobai/cop/layout/empty_line_after_guard_clause.rb', line 40

def self.bundle_args(_config)
  [] # config-less
end

.cop_nameObject



37
# File 'lib/shirobai/cop/layout/empty_line_after_guard_clause.rb', line 37

def self.cop_name = "Layout/EmptyLineAfterGuardClause"

Instance Method Details

#on_new_investigationObject



44
45
46
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
# File 'lib/shirobai/cop/layout/empty_line_after_guard_clause.rb', line 44

def on_new_investigation
  buffer = processed_source.buffer
  candidates = Dispatch.offenses_for(processed_source, config, :empty_line_after_guard_clause)
  return if candidates.empty?

  off = SourceOffsets.for(processed_source.raw_source)
  candidates.each do |offense_start, offense_end, anchor_first_byte, anchor_last_line|
    # `next_line_empty_or_allowed_directive_comment?(anchor_last_line)`:
    # blank below, OR (directive comment immediately below AND blank
    # below that).
    next_line = anchor_last_line + 1
    next if next_line_blank?(next_line)

    directive_target_line = nil
    if next_line_allowed_directive_comment?(next_line)
      # Comment line is below the guard.  Stock then checks the line
      # below the comment: blank suppresses.
      after_directive = next_line + 1
      next if next_line_blank?(after_directive)
      directive_target_line = next_line
    end

    range = Parser::Source::Range.new(buffer, off[offense_start], off[offense_end])
    add_offense(range, message: MSG) do |corrector|
      autocorrect(corrector, buffer, off, anchor_first_byte, anchor_last_line, directive_target_line)
    end
  end
end