|
1 |
| -RSpec::Support.require_rspec_support "ruby_features" |
2 |
| - |
3 | 1 | module RSpec
|
4 | 2 | # Consistent implementation for "cleaning" the caller method to strip out
|
5 | 3 | # non-rspec lines. This enables errors to be reported at the call site in
|
@@ -27,56 +25,48 @@ class CallerFilter
|
27 | 25 | # with this complexity in our `RSpec.deprecate` calls, so we ignore it here.
|
28 | 26 | IGNORE_REGEX = Regexp.union(LIB_REGEX, "rubygems/core_ext/kernel_require.rb")
|
29 | 27 |
|
30 |
| - if RSpec::Support::RubyFeatures.caller_locations_supported? |
31 |
| - # This supports args because it's more efficient when the caller specifies |
32 |
| - # these. It allows us to skip frames the caller knows are part of RSpec, |
33 |
| - # and to decrease the increment size if the caller is confident the line will |
34 |
| - # be found in a small number of stack frames from `skip_frames`. |
35 |
| - # |
36 |
| - # Note that there is a risk to passing a `skip_frames` value that is too high: |
37 |
| - # If it skippped the first non-rspec line, then this method would return the |
38 |
| - # 2nd or 3rd (or whatever) non-rspec line. Thus, you generally shouldn't pass |
39 |
| - # values for these parameters, particularly since most places that use this are |
40 |
| - # not hot spots (generally it gets used for deprecation warnings). However, |
41 |
| - # if you do have a hot spot that calls this, passing `skip_frames` can make |
42 |
| - # a significant difference. Just make sure that that particular use is tested |
43 |
| - # so that if the provided `skip_frames` changes to no longer be accurate in |
44 |
| - # such a way that would return the wrong stack frame, a test will fail to tell you. |
45 |
| - # |
46 |
| - # See benchmarks/skip_frames_for_caller_filter.rb for measurements. |
47 |
| - def self.first_non_rspec_line(skip_frames=3, increment=5) |
48 |
| - # Why a default `skip_frames` of 3? |
49 |
| - # By the time `caller_locations` is called below, the first 3 frames are: |
50 |
| - # lib/rspec/support/caller_filter.rb:63:in `block in first_non_rspec_line' |
51 |
| - # lib/rspec/support/caller_filter.rb:62:in `loop' |
52 |
| - # lib/rspec/support/caller_filter.rb:62:in `first_non_rspec_line' |
| 28 | + # This supports args because it's more efficient when the caller specifies |
| 29 | + # these. It allows us to skip frames the caller knows are part of RSpec, |
| 30 | + # and to decrease the increment size if the caller is confident the line will |
| 31 | + # be found in a small number of stack frames from `skip_frames`. |
| 32 | + # |
| 33 | + # Note that there is a risk to passing a `skip_frames` value that is too high: |
| 34 | + # If it skippped the first non-rspec line, then this method would return the |
| 35 | + # 2nd or 3rd (or whatever) non-rspec line. Thus, you generally shouldn't pass |
| 36 | + # values for these parameters, particularly since most places that use this are |
| 37 | + # not hot spots (generally it gets used for deprecation warnings). However, |
| 38 | + # if you do have a hot spot that calls this, passing `skip_frames` can make |
| 39 | + # a significant difference. Just make sure that that particular use is tested |
| 40 | + # so that if the provided `skip_frames` changes to no longer be accurate in |
| 41 | + # such a way that would return the wrong stack frame, a test will fail to tell you. |
| 42 | + # |
| 43 | + # See benchmarks/skip_frames_for_caller_filter.rb for measurements. |
| 44 | + def self.first_non_rspec_line(skip_frames=3, increment=5) |
| 45 | + # Why a default `skip_frames` of 3? |
| 46 | + # By the time `caller_locations` is called below, the first 3 frames are: |
| 47 | + # lib/rspec/support/caller_filter.rb:63:in `block in first_non_rspec_line' |
| 48 | + # lib/rspec/support/caller_filter.rb:62:in `loop' |
| 49 | + # lib/rspec/support/caller_filter.rb:62:in `first_non_rspec_line' |
53 | 50 |
|
54 |
| - # `caller` is an expensive method that scales linearly with the size of |
55 |
| - # the stack. The performance hit for fetching it in chunks is small, |
56 |
| - # and since the target line is probably near the top of the stack, the |
57 |
| - # overall improvement of a chunked search like this is significant. |
58 |
| - # |
59 |
| - # See benchmarks/caller.rb for measurements. |
| 51 | + # `caller` is an expensive method that scales linearly with the size of |
| 52 | + # the stack. The performance hit for fetching it in chunks is small, |
| 53 | + # and since the target line is probably near the top of the stack, the |
| 54 | + # overall improvement of a chunked search like this is significant. |
| 55 | + # |
| 56 | + # See benchmarks/caller.rb for measurements. |
60 | 57 |
|
61 |
| - # The default increment of 5 for this method are mostly arbitrary, but |
62 |
| - # is chosen to give good performance on the common case of creating a double. |
| 58 | + # The default increment of 5 for this method are mostly arbitrary, but |
| 59 | + # is chosen to give good performance on the common case of creating a double. |
63 | 60 |
|
64 |
| - loop do |
65 |
| - stack = caller_locations(skip_frames, increment) |
66 |
| - raise "No non-lib lines in stack" unless stack |
| 61 | + loop do |
| 62 | + stack = caller_locations(skip_frames, increment) |
| 63 | + raise "No non-lib lines in stack" unless stack |
67 | 64 |
|
68 |
| - line = stack.find { |l| l.path !~ IGNORE_REGEX } |
69 |
| - return line.to_s if line |
| 65 | + line = stack.find { |l| l.path !~ IGNORE_REGEX } |
| 66 | + return line.to_s if line |
70 | 67 |
|
71 |
| - skip_frames += increment |
72 |
| - increment *= 2 # The choice of two here is arbitrary. |
73 |
| - end |
74 |
| - end |
75 |
| - else |
76 |
| - # Earlier rubies do not support the two argument form of `caller`. This |
77 |
| - # fallback is logically the same, but slower. |
78 |
| - def self.first_non_rspec_line(*) |
79 |
| - caller.find { |line| line !~ IGNORE_REGEX } |
| 68 | + skip_frames += increment |
| 69 | + increment *= 2 # The choice of two here is arbitrary. |
80 | 70 | end
|
81 | 71 | end
|
82 | 72 | end
|
|
0 commit comments