@@ -91,26 +91,33 @@ def self.receiver_string(receiver)
91
91
end
92
92
end
93
93
94
+ # default implementation of Exception#detailed_message hook
94
95
def self . detailed_message ( exception , highlight )
95
96
message = StringValue exception . message . to_s
96
97
97
- klass = Primitive . class ( exception ) . to_s
98
+ exception_class = Primitive . class ( exception )
99
+ class_name = exception_class . to_s
100
+
98
101
if Primitive . is_a? ( exception , Polyglot ::ForeignException ) and
99
102
Truffle ::Interop . has_meta_object? ( exception )
100
- klass = "#{ klass } : #{ Truffle ::Interop . meta_qualified_name Truffle ::Interop . meta_object ( exception ) } "
103
+ class_name = "#{ class_name } : #{ Truffle ::Interop . meta_qualified_name Truffle ::Interop . meta_object ( exception ) } "
101
104
end
102
105
103
106
if message . empty?
104
- return highlight ? "\n \e [1m#{ klass } \e [m" : klass
107
+ message = Primitive . equal? ( exception_class , RuntimeError ) ? 'unhandled exception' : class_name
108
+ message = "\n \e [1m#{ message } \e [m" if highlight
109
+ return message
105
110
end
106
111
107
112
anonymous_class = Primitive . module_anonymous? ( Primitive . class ( exception ) )
108
113
109
114
if highlight
110
- highlighted_class_string = !anonymous_class ? " (\e [1;4m#{ klass } \e [m\e [1m)" : ''
115
+ highlighted_class_string = !anonymous_class ? " (\e [1;4m#{ class_name } \e [m\e [1m)" : ''
116
+
111
117
if message . include? ( "\n " )
112
118
first = true
113
119
result = +''
120
+
114
121
message . each_line do |line |
115
122
if first
116
123
first = false
@@ -119,12 +126,13 @@ def self.detailed_message(exception, highlight)
119
126
result << "\n \e [1m#{ line . chomp } \e [m"
120
127
end
121
128
end
129
+
122
130
result
123
131
else
124
132
"\e [1m#{ message } #{ highlighted_class_string } \e [m"
125
133
end
126
134
else
127
- class_string = !anonymous_class ? " (#{ klass } )" : ''
135
+ class_string = !anonymous_class ? " (#{ class_name } )" : ''
128
136
129
137
if i = message . index ( "\n " )
130
138
"#{ message [ 0 ...i ] } #{ class_string } #{ message [ i ..-1 ] } "
@@ -134,6 +142,9 @@ def self.detailed_message(exception, highlight)
134
142
end
135
143
end
136
144
145
+ # User can customise exception and override/undefine Exception#detailed_message method.
146
+ # This way we need to handle corner cases when #detailed_message is undefined or
147
+ # returns something other than String.
137
148
def self . detailed_message_or_fallback ( exception , options )
138
149
unless Primitive . respond_to? ( exception , :detailed_message , false )
139
150
return detailed_message_fallback ( exception , options )
@@ -177,29 +188,35 @@ def self.full_message(exception, **options)
177
188
178
189
result = '' . b
179
190
bt = exception . backtrace || caller ( 2 )
191
+
180
192
if reverse
181
193
traceback_msg = if highlight
182
194
"\e [1mTraceback\e [m (most recent call last):\n "
183
195
else
184
196
"Traceback (most recent call last):\n "
185
197
end
198
+
186
199
result << traceback_msg
187
200
append_causes ( result , exception , { } . compare_by_identity , reverse , highlight , options )
188
201
backtrace_message = backtrace_message ( highlight , reverse , bt , exception , options )
202
+
189
203
if backtrace_message . empty?
190
204
result << detailed_message_or_fallback ( exception , options )
191
205
else
192
206
result << backtrace_message
193
207
end
194
208
else
195
209
backtrace_message = backtrace_message ( highlight , reverse , bt , exception , options )
210
+
196
211
if backtrace_message . empty?
197
212
result << detailed_message_or_fallback ( exception , options )
198
213
else
199
214
result << backtrace_message
200
215
end
216
+
201
217
append_causes ( result , exception , { } . compare_by_identity , reverse , highlight , options )
202
218
end
219
+
203
220
result
204
221
end
205
222
@@ -255,6 +272,8 @@ def self.append_causes(str, err, causes, reverse, highlight, options)
255
272
end
256
273
end
257
274
275
+ # Return user provided message if it was specified.
276
+ # A message might be computed (and assigned) lazily in some cases (e.g. for NoMethodError).
258
277
def self . compute_message ( exception )
259
278
message = Primitive . exception_message ( exception )
260
279
# mimic CRuby behaviour and explicitly convert a user provided message to String
0 commit comments