SusSourceSusOutputBacktrace

class Backtrace

Represents a backtrace for displaying error locations.

Definitions

def self.first(identity = nil)

Create a backtrace from the first caller location.

Signature

parameter identity Identity, nil

Optional identity to filter by path.

returns Backtrace

A new Backtrace instance.

Implementation

def self.first(identity = nil)
	# This implementation could be a little more efficient.
	self.new(caller_locations(1), identity&.path, 1)
end

def self.for(exception, identity = nil)

Create a backtrace from an exception.

Signature

parameter exception Exception

The exception to extract the backtrace from.

parameter identity Identity, nil

Optional identity to filter by path.

returns Backtrace

A new Backtrace instance.

Implementation

def self.for(exception, identity = nil)
	# I've disabled the root filter here, because partial backtraces are not very useful.
	# We might want to do something to improve presentation of the backtrace based on the root instead.
	self.new(extract_stack(exception), identity&.path)
end

Location = Struct.new(:path, :lineno, :label)

Represents a location in a backtrace.

def self.extract_stack(exception)

Extract the stack trace from an exception.

Signature

parameter exception Exception

The exception to extract from.

returns Array

An array of location objects.

Implementation

def self.extract_stack(exception)
	if stack = exception.backtrace_locations
		return stack
	elsif stack = exception.backtrace
		return stack.map do |line|
			Location.new(*line.split(":", 3))
		end
	else
		[]
	end
end

def initialize(stack, root = nil, limit = nil)

Initialize a new Backtrace.

Signature

parameter stack Array

The stack trace locations.

parameter root String, nil

Optional root path to filter by.

parameter limit Integer, nil

Optional limit on the number of frames.

Implementation

def initialize(stack, root = nil, limit = nil)
	@stack = stack
	@root = root
	@limit = limit
end

attr :stack

Signature

attribute Array

The stack trace locations.

attr :root

Signature

attribute String, nil

The root path to filter by.

attr :limit

Signature

attribute Integer, nil

The limit on the number of frames.

def filter(root: @root, limit: @limit)

Filter the backtrace by root path and limit.

Signature

parameter root String, nil

Optional root path to filter by.

parameter limit Integer, nil

Optional limit on the number of frames.

returns Array, Enumerator

The filtered stack trace.

Implementation

def filter(root: @root, limit: @limit)
	if root
		if limit
			return @stack.lazy.select do |frame|
				frame.path.start_with?(root)
			end.first(limit)
		else
			return up_to_and_matching(@stack) do |frame|
				frame.path.start_with?(root)
			end
		end
	elsif limit
		return @stack.first(limit)
	else
		return @stack
	end
end

def print(output)

Print the backtrace to the output.

Signature

parameter output Output

The output handler.

Implementation

def print(output)
	if @limit == 1
		filter.each do |frame|
			output.write " ", :path, frame.path, :line, ":", frame.lineno
		end
	else
		output.indented do
			filter.each do |frame|
				output.puts :indent, :path, frame.path, :line, ":", frame.lineno, :reset, " ", frame.label
			end
		end
	end
end