/usr/lib/ruby/vendor_ruby/rspec/support/caller_filter.rb is in ruby-rspec-support 3.5.0c3e0m0s0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 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 79 80 81 82 83 | RSpec::Support.require_rspec_support "ruby_features"
module RSpec
# Consistent implementation for "cleaning" the caller method to strip out
# non-rspec lines. This enables errors to be reported at the call site in
# the code using the library, which is far more useful than the particular
# internal method that raised an error.
class CallerFilter
RSPEC_LIBS = %w[
core
mocks
expectations
support
matchers
rails
]
ADDITIONAL_TOP_LEVEL_FILES = %w[ autorun ]
LIB_REGEX = %r{/(lib|vendor_ruby)/rspec/(#{(RSPEC_LIBS + ADDITIONAL_TOP_LEVEL_FILES).join('|')})(\.rb|/)}
# rubygems/core_ext/kernel_require.rb isn't actually part of rspec (obviously) but we want
# it ignored when we are looking for the first meaningful line of the backtrace outside
# of RSpec. It can show up in the backtrace as the immediate first caller
# when `CallerFilter.first_non_rspec_line` is called from the top level of a required
# file, but it depends on if rubygems is loaded or not. We don't want to have to deal
# with this complexity in our `RSpec.deprecate` calls, so we ignore it here.
IGNORE_REGEX = Regexp.union(LIB_REGEX, "rubygems/core_ext/kernel_require.rb")
if RSpec::Support::RubyFeatures.caller_locations_supported?
# This supports args because it's more efficient when the caller specifies
# these. It allows us to skip frames the caller knows are part of RSpec,
# and to decrease the increment size if the caller is confident the line will
# be found in a small number of stack frames from `skip_frames`.
#
# Note that there is a risk to passing a `skip_frames` value that is too high:
# If it skippped the first non-rspec line, then this method would return the
# 2nd or 3rd (or whatever) non-rspec line. Thus, you generally shouldn't pass
# values for these parameters, particularly since most places that use this are
# not hot spots (generally it gets used for deprecation warnings). However,
# if you do have a hot spot that calls this, passing `skip_frames` can make
# a significant difference. Just make sure that that particular use is tested
# so that if the provided `skip_frames` changes to no longer be accurate in
# such a way that would return the wrong stack frame, a test will fail to tell you.
#
# See benchmarks/skip_frames_for_caller_filter.rb for measurements.
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
else
# Earlier rubies do not support the two argument form of `caller`. This
# fallback is logically the same, but slower.
def self.first_non_rspec_line(*)
caller.find { |line| line !~ IGNORE_REGEX }
end
end
end
end
|