Class: Shirobai::Cop::Layout::ExtraSpacing
- Inherits:
-
RuboCop::Cop::Base
- Object
- RuboCop::Cop::Base
- Shirobai::Cop::Layout::ExtraSpacing
- Extended by:
- RuboCop::Cop::AutoCorrector
- Includes:
- RuboCop::Cop::RangeHelp
- Defined in:
- lib/shirobai/cop/layout/extra_spacing.rb
Overview
Drop-in Rust reimplementation of Layout/ExtraSpacing.
A token-scan cop with an AST side input: Rust walks the parser-gem token
stream as adjacent pairs (tokens.each_cons(2), stock's check_tokens)
and, for the AllowForAlignment / ignored_ranges decisions, consults
the whole token list (the shared alignment helper) and the AST (the
key↔value spans of multi-line hash pairs, left to Layout/HashAlignment).
Both run in the bundle's walk-outer phase; Rust returns one record per
offense: [start, end, message, action, edits].
[start, end) is the offense highlight. action is 0
(corrector.remove(range) — the usual "delete extra spacing" fix) or 1
(ForceEqualSignAlignment: apply each [edit_start, edit_end, text] of
edits with corrector.replace — a zero-width range inserts, an empty
text deletes; Rust has already applied the @corrected dedup so each
token's edit appears under exactly one offense).
Config inputs: AllowForAlignment (default true) /
AllowBeforeTrailingComments (default false) / ForceEqualSignAlignment
(default false). All are purely config-driven, so the cop is always bundle
eligible — except when raw_source != buffer.source (CRLF/BOM
normalization), where the token byte positions would not line up and it
falls back to a standalone lex of buffer.source. (CRLF/buffer.source
trap, aee0e8e.)
Class Method Summary collapse
- .badge ⇒ Object
-
.bundle_args(config) ⇒ Object
Packed config nums:
[enabled, allow_for_alignment, allow_before_trailing_comments, force_equal_sign_alignment]. - .cop_name ⇒ Object
Instance Method Summary collapse
Class Method Details
.badge ⇒ Object
35 |
# File 'lib/shirobai/cop/layout/extra_spacing.rb', line 35 def self.badge = RuboCop::Cop::Badge.parse(cop_name) |
.bundle_args(config) ⇒ Object
Packed config nums: [enabled, allow_for_alignment, allow_before_trailing_comments, force_equal_sign_alignment].
enabled is a token-cop gate the bundle ORs into its decision to
collect the parser-gem token stream. It is a superset of "this cop
runs": a false positive only costs the token pass on a file the cop
never reads, never a wrong offense, so we only turn it off when
Enabled is literally false.
force_equal_sign_alignment is the same config key
(Layout/ExtraSpacing ForceEqualSignAlignment) that
Layout/SpaceAroundOperators reads; the bundle packs it once (num 126)
as the single wire source. It is carried here for the standalone
fallback call below.
51 52 53 54 55 56 57 58 |
# File 'lib/shirobai/cop/layout/extra_spacing.rb', line 51 def self.bundle_args(config) cop_config = config.for_badge(badge) enabled = cop_config["Enabled"] == false ? 0 : 1 allow = cop_config.fetch("AllowForAlignment", true) ? 1 : 0 trailing = cop_config["AllowBeforeTrailingComments"] ? 1 : 0 force = cop_config["ForceEqualSignAlignment"] ? 1 : 0 [[enabled, allow, trailing, force]] end |
.cop_name ⇒ Object
34 |
# File 'lib/shirobai/cop/layout/extra_spacing.rb', line 34 def self.cop_name = "Layout/ExtraSpacing" |
Instance Method Details
#on_new_investigation ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/shirobai/cop/layout/extra_spacing.rb', line 60 def on_new_investigation buffer = processed_source.buffer source_for_offsets = bundle_eligible? ? processed_source.raw_source : buffer.source off = SourceOffsets.for(source_for_offsets) resolved_result.each do |start_pos, end_pos, , action, edits| # `ignored_range?(ast, range.begin_pos)`: applied here (not in Rust) # with the memoized `@ignored_ranges`, reproducing stock's instance # memoization — across an autocorrect re-pass on a reused instance the # ranges go stale exactly as stock's do. Only the "remove extra space" # action (0) is subject to it; the ForceEqualSignAlignment action (1) # is not. Like stock, the ranges are only computed once the first # candidate needs them: most files have no candidate, and the # computation is a second pass over the whole source. next if action == 0 && ignored_ranges(source_for_offsets).any? { |s, e| (s...e).cover?(start_pos) } range = Parser::Source::Range.new(buffer, off[start_pos], off[end_pos]) add_offense(range, message: ) do |corrector| if action == 0 corrector.remove(range) else edits.each do |edit_start, edit_end, text| edit_range = Parser::Source::Range.new(buffer, off[edit_start], off[edit_end]) corrector.replace(edit_range, text) end end end end end |