Class: Bijou::ErrorFormatter
- Inherits:
-
Object
- Object
- Bijou::ErrorFormatter
- Defined in:
- lib/bijou/errorformatter.rb
Overview
The error formatter is used at runtime to locate the origin of errors with respect to the source Bijou file. During processing, the text in a Bijou file is turned into Ruby code and cached as a separate file. It is the class contained in this file that is the runtime representation of a Bijou component. When a runtime error occurs, the exception refers to a location in the cached file. The ErrorFormatter class is used to find the location in the original Bijou file by referring to #line comments embedded in the cached file and back tracking from there.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#error ⇒ Object
Returns the value of attribute error.
-
#errors ⇒ Object
Returns the value of attribute errors.
-
#stack ⇒ Object
Returns the value of attribute stack.
-
#title ⇒ Object
Returns the value of attribute title.
-
#warnings ⇒ Object
Returns the value of attribute warnings.
Class Method Summary collapse
- .find_eval_line(error) ⇒ Object
- .format_error(format, adjacent_lines, context = nil) ⇒ Object
- .get_file_context(filename, line, adjacent_lines) ⇒ Object
- .get_source_file_line(cachename, eval_line) ⇒ Object
Instance Method Summary collapse
- #format ⇒ Object
-
#initialize ⇒ ErrorFormatter
constructor
A new instance of ErrorFormatter.
- #set_context(filename, lines, context, error_line, error_column) ⇒ Object
Constructor Details
#initialize ⇒ ErrorFormatter
Returns a new instance of ErrorFormatter.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/bijou/errorformatter.rb', line 24 def initialize @title = '' @error = nil @errors = [] @warnings = [] @stack = [] @adjacent_lines = 0 # Context information @filename = '' @context_lines = [] @error_line = 0 @error_column = 0 @context = nil end |
Instance Attribute Details
#error ⇒ Object
Returns the value of attribute error.
22 23 24 |
# File 'lib/bijou/errorformatter.rb', line 22 def error @error end |
#errors ⇒ Object
Returns the value of attribute errors.
22 23 24 |
# File 'lib/bijou/errorformatter.rb', line 22 def errors @errors end |
#stack ⇒ Object
Returns the value of attribute stack.
22 23 24 |
# File 'lib/bijou/errorformatter.rb', line 22 def stack @stack end |
#title ⇒ Object
Returns the value of attribute title.
22 23 24 |
# File 'lib/bijou/errorformatter.rb', line 22 def title @title end |
#warnings ⇒ Object
Returns the value of attribute warnings.
22 23 24 |
# File 'lib/bijou/errorformatter.rb', line 22 def warnings @warnings end |
Class Method Details
.find_eval_line(error) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/bijou/errorformatter.rb', line 186 def self.find_eval_line(error) line = 0 # # This section requires a heuristic to find the most likely line that # is the origin of the error. # if error.to_s =~ /\(eval\)\:(\d+)\: parse error/ return $1.to_i elsif error.to_s =~ /\(eval\)\:(\d+)\:/ # Any eval line return $1.to_i end return 0 end |
.format_error(format, adjacent_lines, context = nil) ⇒ Object
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/bijou/errorformatter.rb', line 52 def self.format_error(format, adjacent_lines, context=nil) if format == :html formatter = ErrorFormatterHTML.new else formatter = ErrorFormatterText.new end @context = context result = '' error_line = 0 error_column = 0 error = $! if $!.kind_of?(Bijou::ParseError) formatter.title = $!.to_s filename = error.filename formatter.errors.replace(error.diagnostics.errors) formatter.warnings.replace(error.diagnostics.warnings) if error.diagnostics.errors # We use the first error as the origin. selected_error = error.diagnostics.errors[0] error_line = selected_error.line error_column = selected_error.column end else if $!.kind_of?(Bijou::EvalError) formatter.error = error.cause filename = error.filename cachename = error.cachename else formatter.error = $! # REVIEW: Are there any cases where the context would override # the EvalError location? if context filename = context.source_filename cachename = context.cache_filename elsif error.respond_to?('filename') filename = error.filename cachename = error.cachename end end # First, look for '(eval):#' in the error itself. eval_line = self.find_eval_line(formatter.error) if eval_line == 0 # If not found, walk the stack. $@.each {|err| eval_line = self.find_eval_line(err) if eval_line > 0 break end } end # Find the location in the original source using the line numbers # in the cache. if eval_line > 0 && cachename error_line = self.get_source_file_line(cachename, eval_line) end end if filename && File.exists?(filename) && error_line > 0 lines = self.get_file_context(filename, error_line, adjacent_lines) formatter.set_context(filename, lines, adjacent_lines, error_line, error_column) else # TODO: Provide a default message using the best available info. end formatter.stack.replace($@) result = formatter.format return result end |
.get_file_context(filename, line, adjacent_lines) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/bijou/errorformatter.rb', line 136 def self.get_file_context(filename, line, adjacent_lines) file = File.new(filename, "r") min = line > adjacent_lines ? line - adjacent_lines : 1 counter = 1; list = [] while line = file.gets line.chomp! if counter >= min list.push({ 'number' => counter, 'text' => line }) if counter >= min + 2 * adjacent_lines break end end counter += 1 end file.close return list end |
.get_source_file_line(cachename, eval_line) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/bijou/errorformatter.rb', line 161 def self.get_source_file_line(cachename, eval_line) file = File.new(cachename, "r") counter = 1 most_recent_line = 0 while line = file.gets line.chomp! if line =~ /\#line\s+(\d+)/ most_recent_line = $1.to_i # Start back by one to account for the comment line. most_recent_line -= 1 else most_recent_line += 1 end if counter >= eval_line return most_recent_line end counter += 1 end file.close return 0 end |
Instance Method Details
#format ⇒ Object
48 49 50 |
# File 'lib/bijou/errorformatter.rb', line 48 def format raise StandardException, "Invalid error formatter" end |
#set_context(filename, lines, context, error_line, error_column) ⇒ Object
40 41 42 43 44 45 46 |
# File 'lib/bijou/errorformatter.rb', line 40 def set_context(filename, lines, context, error_line, error_column) @filename = filename @context_lines = lines @context = context @error_line = error_line @error_column = error_column end |