class MetaRuby::GUI::ExceptionRendering
Functionality to render exceptions in an HTML
view
On top of properly formatting the exception, it introduces backtrace filtering and javascript-based buttons to enable backtraces on or off.
It is usually not used directly, but through {HTML::Page}
@see HTML::Page#enable_exception_rendering
@see HTML::Page#push_exception
Constants
- EXCEPTION_TEMPLATE_WITHOUT_BACKTRACE
Template used to render an exception that does not have backtrace
- EXCEPTION_TEMPLATE_WITH_BACKTRACE
Template used to render an exception that does have a backtrace
- HEADER
Necessary header content
- RESSOURCES_DIR
The directory relative to which ressources (such as css or javascript files) are resolved by default
- SCRIPTS
The scripts that are used by the other exception templates
Attributes
@return [#link_to] an object that allows to render a link to an
object
@return [#[]] an object that can be used to determine whether a
file is a user or framework file. It is used in backtrace filtering and rendering. The default returns true for any file.
Public Class Methods
Create an exception rendering object using the given linker object
@param [#link_to] linker
# File lib/metaruby/gui/exception_rendering.rb, line 36 def initialize(linker) @linker = linker self.user_file_filter = nil end
Parse a backtrace into its file, line and method consistuents
@return [Array<(String,Integer,String)>]
# File lib/metaruby/gui/exception_rendering.rb, line 87 def self.parse_backtrace(backtrace) BacktraceParser.new(backtrace).parse end
Public Instance Methods
Automatically generate an exception ID
# File lib/metaruby/gui/exception_rendering.rb, line 176 def allocate_exception_id @@exception_id += 1 end
Method used by {#render} to discover all exception objects that are linked to another exception, in cases where exceptions cause one another
The default implementation only yields 'e', reimplement in subclasses
@yieldparam [Exception] exception an exception
# File lib/metaruby/gui/exception_rendering.rb, line 211 def each_exception_from(e) return enum_for(__method__) if !block_given? yield(e) end
Filters the backtrace to remove framework parts that are not relevant
@param [Array<(String,Integer,Symbol)>] parsed_backtrace the parsed backtrace @param [Array<(String,Integer,Symbol)>] raw_backtrace the raw backtrace
# File lib/metaruby/gui/exception_rendering.rb, line 156 def filter_backtrace(parsed_backtrace, raw_backtrace) head = parsed_backtrace.take_while { |file, _| !user_file?(file) } tail = parsed_backtrace[head.size..-1].find_all { |file, _| user_file?(file) } head + tail end
Contents necessary in the <head> … </head> section
It is used when enabling the renderer on a [Page] by calling {HTML::Page#add_to_setup}
# File lib/metaruby/gui/exception_rendering.rb, line 72 def head HEADER end
@api private
Parses the exception backtrace, and generate a parsed raw and parsed filtered version of it
@return [(Array<(String,Integer,String)>,Array<(String,Integer,String))>
the full and filtered backtraces, as list of tuples (file,line,method)
# File lib/metaruby/gui/exception_rendering.rb, line 224 def parse_and_filter_backtrace(backtrace) full_backtrace = ExceptionRendering.parse_backtrace(backtrace) filtered_backtrace = filter_backtrace(full_backtrace, backtrace) if filtered_backtrace.first.respond_to?(:to_str) filtered_backtrace = ExceptionRendering.parse_backtrace(filtered_backtrace) end return full_backtrace, filtered_backtrace end
Render an exception into HTML
@param [Exception] e the exception to be rendered @param [String] reason additional string that describes the
exception reason
@param [String] id the ID that should be used to identify the
exception. Since a given exception can "contain" more than one (see {#each_exception_from}), a -#counter pattern is added to the ID.
@return [String]
# File lib/metaruby/gui/exception_rendering.rb, line 190 def render(e, reason = nil, id = allocate_exception_id) counter = 0 html = [] seen = Set.new each_exception_from(e) do |exception| if !seen.include?(exception) seen << exception html << render_single_exception(exception, "#{id}-#{counter += 1}") end end html.join("\n") end
@api private
Render a backtrace
It uses {#linker} to generate links, and {#user_file?} to change the style of the backtrace line.
# File lib/metaruby/gui/exception_rendering.rb, line 266 def render_backtrace(backtrace) result = [] backtrace.each do |file, line, method| file_link = linker.link_to(Pathname.new(file), file, lineno: line) if user_file?(file) result << " <span class=\"user_file\">#{file_link}:#{line}:in #{HTML.escape_html(method.to_s)}</span><br/>" else result << " #{file_link}:#{line}:in #{HTML.escape_html(method.to_s)}<br/>" end end result.join("\n") end
@api private
Render a single exception object into a HTML
block
@param [Exception] e the exception @param [String] id the block ID @return [String]
# File lib/metaruby/gui/exception_rendering.rb, line 240 def render_single_exception(e, id) message = PP.pp(e, "").split("\n"). map { |line| HTML.escape_html(line) } full_backtrace, filtered_backtrace = parse_and_filter_backtrace(e.backtrace || Array.new) if !full_backtrace.empty? origin_file, origin_line, origin_method = filtered_backtrace.find { |file, _| user_file?(file) } || filtered_backtrace.first || full_backtrace.first origin_file = linker.link_to(Pathname.new(origin_file), origin_file, lineno: origin_line) ERB.new(EXCEPTION_TEMPLATE_WITH_BACKTRACE).result(binding) else ERB.new(EXCEPTION_TEMPLATE_WITHOUT_BACKTRACE).result(binding) end end
Scripts block to be added to the HTML
document
It is used when enabling the renderer on a [Page] by calling {HTML::Page#add_to_setup}
# File lib/metaruby/gui/exception_rendering.rb, line 80 def scripts SCRIPTS end
Return true if the given file is a user file or a framework file
An object used to determine this can be set with {#user_file_filter=}
This is used by {#render_backtrace} to choose the style of a backtrace line
# File lib/metaruby/gui/exception_rendering.rb, line 169 def user_file?(file) user_file_filter[file] end
Sets {#user_file_filter} or resets it to the default
@param [nil,# filter
# File lib/metaruby/gui/exception_rendering.rb, line 29 def user_file_filter=(filter) @user_file_filter = filter || Hash.new(true) end