Re-enable spec/library for full CI runs.
[rbx.git] / kernel / core / backtrace.rb
blobd71af11eeaa66044f3e42d110aca9440156cb7ca
1 ##
2 # Contains all logic for gathering and displaying backtraces.
4 class Backtrace
5   include Enumerable
7   attr_accessor :frames
8   attr_accessor :top_context
9   attr_accessor :first_color
10   attr_accessor :kernel_color
11   attr_accessor :eval_color
13   def initialize
14     @frames = []
15     @top_context = nil
16     @first_color = "\033[0;31m"
17     @kernel_color = "\033[0;34m"
18     @eval_color = "\033[0;33m"
19   end
21   def [](index)
22     @frames[index]
23   end
25   def show(sep="\n", colorize = true)
26     first = true
27     color_config = Rubinius::RUBY_CONFIG["rbx.colorize_backtraces"]
28     if color_config == "no" or color_config == "NO"
29       colorize = false
30       color = ""
31       clear = ""
32     else
33       clear = "\033[0m"
34     end
36     formatted = @frames.map do |ctx|
37       recv = ctx.describe
38       loc = ctx.location
39       color = color_from_loc(loc, first) if colorize
40       first = false # special handling for first line
41       times = @max - recv.size
42       times = 0 if times < 0
43       "#{color}    #{' ' * times}#{recv} at #{loc}#{clear}"
44     end
45     return formatted.join(sep)
46   end
48   def join(sep)
49     show
50   end
52   alias_method :to_s, :show
54   def color_from_loc(loc, first)
55     return @first_color if first
56     if loc =~ /kernel/
57       @kernel_color
58     elsif loc =~ /\(eval\)/
59       @eval_color
60     else
61       ""
62     end
63   end
65   MAX_WIDTH = 40
67   def fill_backtrace
68     @max = 0
69     @backtrace = []
70     # Skip the first frame if we are raising an exception from
71     # an eval's BlockContext
72     if @frames.at(0).from_eval?
73       frames = @frames[1, @frames.length - 1]
74     else
75       frames = @frames
76     end
78     frames.each_with_index do |ctx, i|
79       str = ctx.describe
80       @max = str.size if str.size > @max
81       @backtrace << [str, ctx.location]
82     end
83     @max = MAX_WIDTH if @max > MAX_WIDTH
84   end
86   def self.backtrace(ctx=nil)
87     ctx ||= MethodContext.current.sender
88     obj = new()
89     obj.top_context = ctx
90     obj.frames = ctx.context_stack
92     # TODO - Consider not doing this step if we know we want MRI output
93     obj.fill_backtrace
94     return obj
95   end
97   def each
98     @backtrace.each { |f| yield f.last }
99     self
100   end
102   def to_mri
103     return @top_context.stack_trace_starting_at(0)
104   end