Class: RSpec::Signal::Backtrace::Reducer

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec/signal/backtrace/reducer.rb

Overview

Reduces a full backtrace to the frames that carry diagnostic value.

Rules, in order:

1. Consecutive repeats of the same file:line collapse into one.
2. Framework frames (test runner, loader, CLI) are always dropped.
3. Every first-party frame is kept.
4. A run of library frames that directly touches first-party code is
 partially kept: the library entry point the project called, the site
 that raised, and (budget permitting) their immediate neighbours.
 This is the "what operation failed" context.
5. Library frames that touch no first-party code at all are dropped.
6. If nothing survives, progressively fall back so that the report is
 never empty: innermost non-framework frames, then innermost frames.

Constant Summary collapse

SCORE_PROJECT =

Relative value of each kind of frame. Anything scoring 0 is dropped.

100
SCORE_LIBRARY_ENTRY =

last library frame before first-party code

70
SCORE_RAISE_SITE =

innermost frame of an adjacent library run

65
SCORE_LIBRARY_NEAR =

neighbours of the two above

40
SCORE_LIBRARY_CALLER =

library frame that called into first-party code

60
ANONYMOUS_LABEL =

Labels that name no method: delegation shims and block frames.

/\A(?:block\s|<(?:top|module|class|main)\b|rescue in\b|ensure in\b)/.freeze

Instance Method Summary collapse

Constructor Details

#initialize(max_frames: 12, max_external_context: 3, max_project_frames: 8, fallback_frames: 6) ⇒ Reducer

Returns a new instance of Reducer.



107
108
109
110
111
112
# File 'lib/rspec/signal/backtrace/reducer.rb', line 107

def initialize(max_frames: 12, max_external_context: 3, max_project_frames: 8, fallback_frames: 6)
  @max_frames = max_frames
  @max_external_context = max_external_context
  @max_project_frames = max_project_frames
  @fallback_frames = fallback_frames
end

Instance Method Details

#call(frames) ⇒ Reduced

Parameters:

  • frames (Array<Frame>)

    innermost first, as Ruby emits them

Returns:



116
117
118
119
120
121
122
123
124
125
# File 'lib/rspec/signal/backtrace/reducer.rb', line 116

def call(frames)
  frames = collapse_repeats(Array(frames))
  return Reduced.new(entries: [], total: 0, omitted: {}) if frames.empty?

  scored = score(frames)
  keep = select_keepers(scored)
  return fallback(frames) if keep.empty?

  build(frames, keep)
end