Class: SimpleCov::Sorbet::IgnoredRanges

Inherits:
ASTTransform::AbstractAnalysis
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/simplecov/sorbet/ignored_ranges.rb

Overview

Read-only analysis pass collecting the line ranges of type-level Sorbet constructs coverage should ignore. Detection is purely syntactic — this gem never loads Sorbet's type system. Three constructs are collected:

  • T.type_alias blocks: sorbet-runtime resolves aliases lazily and collection checks are shallow, so a multi-line alias body never executes and reads as a permanent coverage miss.
  • sig blocks (bare or with a receiver, e.g. T::Sig::WithoutRuntime.sig): sigs are type metadata whose correctness srb tc owns; coverage should measure behavior. Only multi-line blocks are collected — a single-line sig { ... } occupies the send's own line, which executes at load.
  • T.absurd sends: unreachable by definition when exhaustiveness holds, so in correct code the line is a permanent coverage miss.

Constant Summary collapse

T_RECEIVERS =

Structural patterns for the T receiver (node equality ignores source locations): T and its explicit top-level form ::T.

T.let(
  [
    s(:const, nil, :T),
    s(:const, s(:cbase), :T),
  ].freeze,
  T::Array[Parser::AST::Node],
)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeIgnoredRanges

Returns a new instance of IgnoredRanges.



34
35
36
37
# File 'lib/simplecov/sorbet/ignored_ranges.rb', line 34

def initialize
  @ranges = T.let([], T::Array[T::Range[Integer]])
  super
end

Instance Attribute Details

#rangesObject (readonly)

Returns the value of attribute ranges.



31
32
33
# File 'lib/simplecov/sorbet/ignored_ranges.rb', line 31

def ranges
  @ranges
end

Instance Method Details

#on_block(node) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/simplecov/sorbet/ignored_ranges.rb', line 58

def on_block(node)
  receiver, method_name = node.children.first.children
  range = line_range(node)

  case method_name
  when :type_alias
    @ranges << range if T_RECEIVERS.include?(receiver)
  when :sig
    # Any receiver qualifies: bare sig blocks and forms like T::Sig::WithoutRuntime.sig are all sigs. A
    # non-Sorbet DSL also named `sig` would be over-matched, an accepted risk documented in the README.
    @ranges << range if range.first < range.last
  end

  super
end

#on_send(node) ⇒ Object



45
46
47
48
49
50
# File 'lib/simplecov/sorbet/ignored_ranges.rb', line 45

def on_send(node)
  receiver, method_name = node.children
  @ranges << line_range(node) if method_name == :absurd && T_RECEIVERS.include?(receiver)

  super
end