Module: Shirobai::Cop::Rails::IndexMethodSupport

Included in:
IndexBy, IndexWith
Defined in:
lib/shirobai/cop/rails/index_method_support.rb

Overview

Shared Architecture-B harness for Rails/IndexBy and Rails/IndexWith.

Both stock cops share the RuboCop::Cop::IndexMethod mixin, whose autocorrect is heavy parser-AST geometry (strip prefix/suffix, rename the method, rewrite block args, replace the body) plus cross-offense ignore_node state. Rather than reproduce any of that, Rust nominates candidate nodes (the four transform-to-hash shapes) once on the shared walk; this module relocates each parser node (Shirobai::NodeLocator) and runs stock's own handle_possible_offense / correction machinery VERBATIM, so detection and -A bytes match stock by construction.

Stock's node callbacks (on_block / on_send / on_csend, plus the on_numblock / on_itblock aliases) are undefined so the Commissioner never dispatches them per node; the same bodies are re-exposed as investigate_block / investigate_send / investigate_csend, driven only from on_new_investigation. The candidate list is a superset — the empty-hash arg, block arity, key/value identity and Ruby-version gate are all re-checked by the stock matchers the cop still owns.

ignore_node is stock's real one (range/heredoc based, per cop instance): candidates arrive in pre-order (an outer node before any it contains), so a nested transform's inner offense is suppressed for autocorrect exactly as stock does. IndexBy and IndexWith are separate cop instances with separate @ignored_nodes, matching stock.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/shirobai/cop/rails/index_method_support.rb', line 31

def self.included(base)
  # Pull in stock's `Captures` / `Autocorrection` structs and the
  # private glue (`handle_possible_offense`, `extract_captures`,
  # `prepare_correction`, `execute_correction`), then drop the public
  # node callbacks so only `on_new_investigation` drives the cop.
  base.include RuboCop::Cop::IndexMethod
  base.include Shirobai::Cop::BundleEligible
  %i[on_block on_numblock on_itblock on_send on_csend].each do |m|
    base.send(:undef_method, m) if base.method_defined?(m)
  end
end

Instance Method Details

#investigate_block(node) ⇒ Object

--- stock IndexMethod#on_block / on_send / on_csend, copied verbatim (rubocop-rails 2.35.5) and renamed so they are not node callbacks. Every on_bad_* matcher and the private glue are the included stock code.



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/shirobai/cop/rails/index_method_support.rb', line 69

def investigate_block(node)
  on_bad_each_with_object(node) do |*match|
    handle_possible_offense(node, match, 'each_with_object')
  end

  return if target_ruby_version < 2.6

  on_bad_to_h(node) do |*match|
    handle_possible_offense(node, match, 'to_h { ... }')
  end
end

#investigate_csend(node) ⇒ Object



91
92
93
94
95
# File 'lib/shirobai/cop/rails/index_method_support.rb', line 91

def investigate_csend(node)
  on_bad_map_to_h(node) do |*match|
    handle_possible_offense(node, match, 'map { ... }.to_h')
  end
end

#investigate_send(node) ⇒ Object



81
82
83
84
85
86
87
88
89
# File 'lib/shirobai/cop/rails/index_method_support.rb', line 81

def investigate_send(node)
  on_bad_map_to_h(node) do |*match|
    handle_possible_offense(node, match, 'map { ... }.to_h')
  end

  on_bad_hash_brackets_map(node) do |*match|
    handle_possible_offense(node, match, 'Hash[map { ... }]')
  end
end

#on_new_investigationObject



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/shirobai/cop/rails/index_method_support.rb', line 43

def on_new_investigation
  ranges = resolved_candidates
  return if ranges.nil? || ranges.empty?

  source = bundle_eligible? ? processed_source.raw_source : processed_source.buffer.source
  off = SourceOffsets.for(source)
  keys = ranges.map { |(start, fin)| [off[start], off[fin]] }
  located = Shirobai::NodeLocator.locate(processed_source, keys)

  keys.each do |key|
    node = located[key]
    next unless node

    case node.type
    when :block, :numblock, :itblock then investigate_block(node)
    when :send then investigate_send(node)
    when :csend then investigate_csend(node)
    end
  end
end