Class: Shirobai::Cop::Metrics::BlockLength

Inherits:
RuboCop::Cop::Base
  • Object
show all
Extended by:
RuboCop::ExcludeLimit
Includes:
RuboCop::Cop::AllowedMethods, RuboCop::Cop::AllowedPattern
Defined in:
lib/shirobai/cop/metrics/block_length.rb

Overview

Drop-in Rust reimplementation of ‘Metrics/BlockLength`.

Rust parses the source, walks blocks, counts body lines (with comment and ‘CountAsOne` handling) and excludes class constructors. With no `AllowedPatterns` configured (the default) the `AllowedMethods` exclusion also runs in Rust, only the offending blocks come back, and the offenses are pulled from the per-file bundled run (`Shirobai::Dispatch`); otherwise the legacy standalone call is made and Ruby applies the `AllowedMethods` / `AllowedPatterns` filters as before.

Constant Summary collapse

LABEL =
"Block"
MSG =
"%<label>s has too many lines. [%<length>d/%<max>d]"
FOLDABLE_TYPES =
%w[array hash heredoc method_call].freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.badgeObject



27
# File 'lib/shirobai/cop/metrics/block_length.rb', line 27

def self.badge = RuboCop::Cop::Badge.parse("Metrics/BlockLength")

.bundle_args(config) ⇒ Object

Packed args for the bundled (fast-path) run: ‘[max, count_comments, count_as_one, allowed_method_strings]`. `Max` defaults to 25 (default.yml) so a config that does not mention this cop (vendor specs of the other bundled cops) still packs cleanly; the computed slice is discarded in that case. The String filtering of `AllowedMethods` mirrors the fast path: non-String entries are skipped by stock’s ‘method_receiver_excluded?` (`next unless config.is_a?(String)`) and can never equal a String method name in `allowed_method?`, so dropping them is faithful.



38
39
40
41
42
43
44
45
46
# File 'lib/shirobai/cop/metrics/block_length.rb', line 38

def self.bundle_args(config)
  cop_config = config.for_badge(badge)
  [
    cop_config["Max"] || 25,
    !!cop_config["CountComments"],
    Array(cop_config["CountAsOne"]).map(&:to_s),
    Cop.allowed_methods_config(cop_config).grep(String)
  ]
end

.cop_nameObject



26
# File 'lib/shirobai/cop/metrics/block_length.rb', line 26

def self.cop_name = "Metrics/BlockLength"

Instance Method Details

#on_new_investigationObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/shirobai/cop/metrics/block_length.rb', line 48

def on_new_investigation
  # Fast path: without AllowedPatterns (the default), the AllowedMethods
  # exclusion runs in Rust and only offending blocks come back. The
  # filters are independent per-block predicates, but we still gate on
  # the patterns being empty so any pattern config keeps the exact
  # legacy path.
  fast = bundle_eligible?
  candidates =
    if fast
      Dispatch.offenses_for(processed_source, config, :block_length)
    else
      Shirobai.check_block_length(
        processed_source.raw_source, max_length, count_comments?, count_as_one, [], false
      )
    end
  off = SourceOffsets.for(processed_source.raw_source)
  candidates.each do |start, fin, head_end, length, method_name, receiver|
    unless fast
      next if allowed_method?(method_name) || matches_allowed_pattern?(method_name)
      next if method_receiver_excluded?(receiver, method_name)
    end

    validate_count_as_one!

    stop = RuboCop::LSP.enabled? ? head_end : fin
    range = Parser::Source::Range.new(processed_source.buffer, off[start], off[stop])
    add_offense(range, message: format(MSG, label: LABEL, length: length, max: max_length)) do
      self.max = length
    end
  end
end