class RSpec::CallerFilter

internal method that raised an error.
the code using the library, which is far more useful than the particular
non-rspec lines. This enables errors to be reported at the call site in
Consistent implementation for “cleaning” the caller method to strip out

def self.first_non_rspec_line(skip_frames=3, increment=5)

See benchmarks/skip_frames_for_caller_filter.rb for measurements.

such a way that would return the wrong stack frame, a test will fail to tell you.
so that if the provided `skip_frames` changes to no longer be accurate in
a significant difference. Just make sure that that particular use is tested
if you do have a hot spot that calls this, passing `skip_frames` can make
not hot spots (generally it gets used for deprecation warnings). However,
values for these parameters, particularly since most places that use this are
2nd or 3rd (or whatever) non-rspec line. Thus, you generally shouldn't pass
If it skipped the first non-rspec line, then this method would return the
Note that there is a risk to passing a `skip_frames` value that is too high:

be found in a small number of stack frames from `skip_frames`.
and to decrease the increment size if the caller is confident the line will
these. It allows us to skip frames the caller knows are part of RSpec,
This supports args because it's more efficient when the caller specifies
def self.first_non_rspec_line(skip_frames=3, increment=5)
  # Why a default `skip_frames` of 3?
  # By the time `caller_locations` is called below, the first 3 frames are:
  #   lib/rspec/support/caller_filter.rb:63:in `block in first_non_rspec_line'
  #   lib/rspec/support/caller_filter.rb:62:in `loop'
  #   lib/rspec/support/caller_filter.rb:62:in `first_non_rspec_line'
  # `caller` is an expensive method that scales linearly with the size of
  # the stack. The performance hit for fetching it in chunks is small,
  # and since the target line is probably near the top of the stack, the
  # overall improvement of a chunked search like this is significant.
  #
  # See benchmarks/caller.rb for measurements.
  # The default increment of 5 for this method are mostly arbitrary, but
  # is chosen to give good performance on the common case of creating a double.
  loop do
    stack = caller_locations(skip_frames, increment)
    raise "No non-lib lines in stack" unless stack
    line = stack.find { |l| l.path !~ IGNORE_REGEX }
    return line.to_s if line
    skip_frames += increment
    increment *= 2 # The choice of two here is arbitrary.
  end
end

def self.first_non_rspec_line(*)

fallback is logically the same, but slower.
Earlier rubies do not support the two argument form of `caller`. This
def self.first_non_rspec_line(*)
  caller.find { |line| line !~ IGNORE_REGEX }
end