Class: Shirobai::Cop::Layout::SpaceBeforeBlockBraces

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

Overview

Drop-in Rust reimplementation of Layout/SpaceBeforeBlockBraces.

Rust walks the AST once and decides every offense (do ... end and the Style/BlockDelimiters multiline conflict already excluded), sending back only the offense ranges plus a five-flag style-detection summary — an earlier version shipped one record per brace block and decided here, which scaled the wire volume with the number of blocks.

The summary replays stock's config_to_allow_offenses bookkeeping byte-identically (the vendor spec asserts it):

  • non-empty blocks matching the style fire correct_style_detected once (the state machine intersects sets, so repeats are idempotent);
  • each non-empty offense fires opposite_style_detected inside its add_offense block, exactly like stock (so directive-disabled lines suppress it);
  • the empty-braces axis writes one fixed value and can only be cleared by a matching empty block seen while a value is stored, so "match before first offense" / "match after some offense" bits reproduce every ordering (no_acceptable_style! replaces the whole hash and freezes all later events, making the flag replay exact).

The lazy Unknown EnforcedStyleForEmptyBraces selected! raise fires when an empty-brace block was seen under an invalid setting, mirroring stock's raise from check_empty.

Constant Summary collapse

MISSING_MSG =
"Space missing to the left of {."
DETECTED_MSG =
"Space detected to the left of {."
STYLES =
{ "space" => 0, "no_space" => 1 }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.autocorrect_incompatible_withObject

Stock declares the same incompatibility: both cops can rewrite the same brace, so RuboCop's correction loop defers a conflicting pass.



43
44
45
# File 'lib/shirobai/cop/layout/space_before_block_braces.rb', line 43

def self.autocorrect_incompatible_with
  [RuboCop::Cop::Style::SymbolProc]
end

.badgeObject



48
# File 'lib/shirobai/cop/layout/space_before_block_braces.rb', line 48

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

.bundle_args(config) ⇒ Object

Packed args for the bundled run: [nums, lists] with nums = [EnforcedStyle, resolved EnforcedStyleForEmptyBraces (0 space / 1 no_space / 2 invalid; nil follows EnforcedStyle), Style/BlockDelimiters EnforcedStyle == 'line_count_based'].



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/shirobai/cop/layout/space_before_block_braces.rb', line 54

def self.bundle_args(config)
  cop_config = config.for_badge(badge)
  style = STYLES.fetch(cop_config["EnforcedStyle"] || "space")
  empty = case cop_config["EnforcedStyleForEmptyBraces"]
          when "space" then 0
          when "no_space" then 1
          when nil then style
          else 2
          end
  bd = config.for_cop("Style/BlockDelimiters")["EnforcedStyle"] == "line_count_based"
  [[style, empty, bd ? 1 : 0], []]
end

.cop_nameObject



47
# File 'lib/shirobai/cop/layout/space_before_block_braces.rb', line 47

def self.cop_name = "Layout/SpaceBeforeBlockBraces"

Instance Method Details

#on_new_investigationObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/shirobai/cop/layout/space_before_block_braces.rb', line 67

def on_new_investigation
  buffer = processed_source.buffer
  off = SourceOffsets.for(processed_source.raw_source)
  offenses, summary = result_for_source
  a_correct, b_match_first, b_offense, b_match_after, saw_empty = summary

  # Stock raises lazily from check_empty when an empty-brace block is
  # reached under an invalid EnforcedStyleForEmptyBraces.
  raise "Unknown EnforcedStyleForEmptyBraces selected!" if saw_empty && invalid_empty_style?

  replay_empty_braces_axis(b_match_first, b_offense, b_match_after)
  correct_style_detected if a_correct

  offenses.each do |start, fin, detected, from_empty|
    range = Parser::Source::Range.new(buffer, off[start], off[fin])
    add_offense(range, message: detected ? DETECTED_MSG : MISSING_MSG) do |corrector|
      autocorrect(corrector, range)
      opposite_style_detected unless from_empty
    end
  end
end