@@ -10,21 +10,21 @@ defexception SystemLimitError, message: "a system limit has been reached"
10
10
defexception SyntaxError , [ file: nil , line: nil , description: "syntax error" ] do
11
11
def message ( exception ) do
12
12
Exception . format_file_line ( Path . relative_to_cwd ( exception . file ) , exception . line ) <>
13
- exception . description
13
+ " " <> exception . description
14
14
end
15
15
end
16
16
17
17
defexception TokenMissingError , [ file: nil , line: nil , description: "expression is incomplete" ] do
18
18
def message ( exception ) do
19
19
Exception . format_file_line ( Path . relative_to_cwd ( exception . file ) , exception . line ) <>
20
- exception . description
20
+ " " <> exception . description
21
21
end
22
22
end
23
23
24
24
defexception CompileError , [ file: nil , line: nil , description: "compile error" ] do
25
25
def message ( exception ) do
26
26
Exception . format_file_line ( Path . relative_to_cwd ( exception . file ) , exception . line ) <>
27
- exception . description
27
+ " " <> exception . description
28
28
end
29
29
end
30
30
@@ -149,6 +149,16 @@ defmodule Exception do
149
149
pass the `System.stacktrace` as argument.
150
150
"""
151
151
152
+ @ type stacktrace :: [ stacktrace_entry ]
153
+
154
+ @ type stacktrace_entry ::
155
+ { module , function , arity_or_args , location } |
156
+ { function , arity_or_args , location }
157
+
158
+ @ typep function :: atom
159
+ @ typep arity_or_args :: non_neg_integer | list
160
+ @ typep location :: Keyword . t
161
+
152
162
@ doc """
153
163
Normalizes an exception, converting Erlang exceptions
154
164
to Elixir exceptions.
@@ -221,48 +231,38 @@ defmodule Exception do
221
231
end
222
232
223
233
@ doc """
224
- Receives a tuple representing a stacktrace entry and formats it.
225
- """
226
- def format_stacktrace_entry ( entry ) do
227
- format_stacktrace_entry_into_fields ( entry )
228
- |> tuple_to_list
229
- |> Enum . filter ( fn field -> field && field != "" end )
230
- |> Enum . join ( " " )
231
- end
232
-
233
- @ doc """
234
- Returns the fields from a single frame in a stack trace as a list of
235
- `[ app, location, mfa/module/file ]` where all but location can be nil.
236
- Intended for use inside the Elixir libraries and iex only
234
+ Receives an stacktrace entry and formats it into a string.
237
235
"""
236
+ @ spec format_stacktrace_entry ( stacktrace_entry ) :: String . t
237
+ def format_stacktrace_entry ( entry )
238
238
239
239
# From Macro.Env.stacktrace
240
- def format_stacktrace_entry_into_fields ( { module , :__MODULE__ , 0 , location } ) do
241
- { nil , format_location ( location ) , inspect ( module ) <> " (module)" }
240
+ def format_stacktrace_entry ( { module , :__MODULE__ , 0 , location } ) do
241
+ format_location ( location ) <> inspect ( module ) <> " (module)"
242
242
end
243
243
244
244
# From :elixir_compiler_*
245
- def format_stacktrace_entry_into_fields ( { _module , :__MODULE__ , 1 , location } ) do
246
- { nil , format_location ( location ) , "(module)" }
245
+ def format_stacktrace_entry ( { _module , :__MODULE__ , 1 , location } ) do
246
+ format_location ( location ) <> "(module)"
247
247
end
248
248
249
249
# From :elixir_compiler_*
250
- def format_stacktrace_entry_into_fields ( { _module , :__FILE__ , 1 , location } ) do
251
- { nil , format_location ( location ) , "(file)" }
250
+ def format_stacktrace_entry ( { _module , :__FILE__ , 1 , location } ) do
251
+ format_location ( location ) <> "(file)"
252
252
end
253
253
254
- def format_stacktrace_entry_into_fields ( { module , fun , arity , location } ) do
255
- { format_application ( module ) , format_location ( location ) , format_mfa ( module , fun , arity ) }
254
+ def format_stacktrace_entry ( { module , fun , arity , location } ) do
255
+ format_application ( module ) <> format_location ( location ) <> format_mfa ( module , fun , arity )
256
256
end
257
257
258
- def format_stacktrace_entry_into_fields ( { fun , arity , location } ) do
259
- { nil , format_location ( location ) , format_fa ( fun , arity ) }
258
+ def format_stacktrace_entry ( { fun , arity , location } ) do
259
+ format_location ( location ) <> format_fa ( fun , arity )
260
260
end
261
261
262
262
defp format_application ( module ) do
263
263
case :application . get_application ( module ) do
264
- { :ok , app } -> "(" <> atom_to_binary ( app ) <> ")"
265
- :undefined -> nil
264
+ { :ok , app } -> "(" <> atom_to_binary ( app ) <> ") "
265
+ :undefined -> ""
266
266
end
267
267
end
268
268
@@ -285,29 +285,6 @@ defmodule Exception do
285
285
end
286
286
end
287
287
288
- @ doc """
289
- Formats the caller, i.e. the first entry in the stacktrace.
290
-
291
- A stacktrace must be given as an argument. If not, this function
292
- calculates a new stacktrace based on the caller and formats it. As
293
- a consequence, the value of `System.stacktrace` is changed.
294
-
295
- Notice that due to tail call optimization, the stacktrace
296
- may not report the direct caller of the function.
297
- """
298
- def format_caller ( trace \\ nil ) do
299
- trace = trace || try do
300
- throw ( :stacktrace )
301
- catch
302
- :stacktrace -> Enum . drop ( :erlang . get_stacktrace , 2 )
303
- end
304
-
305
- case trace do
306
- [ entry | _ ] -> format_stacktrace_entry ( entry )
307
- _ -> "nofile:0: "
308
- end
309
- end
310
-
311
288
@ doc """
312
289
Receives an anonymous function and arity and formats it as
313
290
shown in stacktraces. The arity may also be a list of arguments.
@@ -326,8 +303,9 @@ defmodule Exception do
326
303
Receives a module, fun and arity and formats it
327
304
as shown in stacktraces. The arity may also be a list
328
305
of arguments.
329
-
306
+
330
307
## Examples
308
+
331
309
iex> Exception.format_mfa Foo, :bar, 1
332
310
"Foo.bar/1"
333
311
iex> Exception.format_mfa Foo, :bar, []
@@ -337,66 +315,51 @@ defmodule Exception do
337
315
338
316
Anonymous functions are reported as -func/arity-anonfn-count-,
339
317
where func is the name of the enclosing function. Convert to
340
- "nth fn in func/arity"
318
+ "anonymous fn in func/arity"
341
319
"""
320
+ def format_mfa ( module , fun , arity ) when is_atom ( fun ) do
321
+ fun =
322
+ case inspect ( fun ) do
323
+ ":" <> fun -> fun
324
+ fun -> fun
325
+ end
342
326
343
- def format_mfa ( module , nil , arity ) ,
344
- do: do_format_mfa ( module , "nil" , arity )
345
-
346
- def format_mfa ( module , fun , arity ) when is_atom ( fun ) ,
347
- do: do_format_mfa ( module , to_string ( fun ) , arity )
348
-
349
- defp do_format_mfa ( module , fun , arity ) when not ( is_binary ( fun ) ) ,
350
- do: format_mfa ( module , inspect ( fun ) , arity )
351
-
352
- defp do_format_mfa ( module , "-" <> fun , arity ) do
353
- [ outer_fun , "fun" , count , "" ] = String . split ( fun , "-" )
354
- "#{ format_nth ( count ) } anonymous fn#{ format_arity ( arity ) } in #{ inspect module } .#{ outer_fun } "
355
- end
356
-
357
- # Erlang internal
358
- defp do_format_mfa ( module , ":" <> fun , arity ) ,
359
- do: format_mfa ( module , maybe_quote_name ( fun ) , arity )
360
-
361
- defp do_format_mfa ( module , fun , arity ) do
362
- "#{ inspect module } .#{ maybe_quote_name ( fun ) } #{ format_arity ( arity ) } "
327
+ case match? ( "\" -" <> _ , fun ) and String . split ( fun , "-" ) do
328
+ [ "\" " , outer_fun , "fun" , _count , "\" " ] ->
329
+ "anonymous fn#{ format_arity ( arity ) } in #{ inspect module } .#{ outer_fun } "
330
+ _ ->
331
+ "#{ inspect module } .#{ fun } #{ format_arity ( arity ) } "
332
+ end
363
333
end
364
334
365
335
defp format_arity ( arity ) when is_list ( arity ) do
366
336
inspected = lc x inlist arity , do: inspect ( x )
367
337
"(#{ Enum . join ( inspected , ", " ) } )"
368
338
end
369
339
370
- defp format_arity ( arity ) , do: "/#{ arity } "
371
-
372
- defp format_nth ( "0" ) , do: "first"
373
- defp format_nth ( "1" ) , do: "second"
374
- defp format_nth ( "2" ) , do: "third"
375
- defp format_nth ( n ) , do: "#{ binary_to_integer ( n ) + 1 } th"
376
-
340
+ defp format_arity ( arity ) , do: "/#{ arity } "
377
341
378
342
@ doc """
379
343
Formats the given file and line as shown in stacktraces.
380
- If any of the values are nil, they are omitted. If the
381
- optional suffix is omitted, a space is appended to
382
- the result.
344
+ If any of the values are nil, they are omitted.
383
345
384
346
## Examples
385
347
386
348
iex> Exception.format_file_line("foo", 1)
387
- "foo:1: "
388
-
389
- iex> Exception.format_file_line("foo", 1, "")
390
349
"foo:1:"
391
350
392
351
iex> Exception.format_file_line("foo", nil)
393
- "foo: "
352
+ "foo:"
394
353
395
354
iex> Exception.format_file_line(nil, nil)
396
355
""
397
356
398
357
"""
399
- def format_file_line ( file , line , suffix // " " ) do
358
+ def format_file_line ( file , line ) do
359
+ format_file_line ( file , line , "" )
360
+ end
361
+
362
+ defp format_file_line ( file , line , suffix ) do
400
363
if file do
401
364
if line && line != 0 do
402
365
"#{ file } :#{ line } :#{ suffix } "
@@ -409,7 +372,7 @@ defmodule Exception do
409
372
end
410
373
411
374
defp format_location ( opts ) do
412
- format_file_line Keyword . get ( opts , :file ) , Keyword . get ( opts , :line ) , ""
375
+ format_file_line Keyword . get ( opts , :file ) , Keyword . get ( opts , :line ) , " "
413
376
end
414
377
415
378
defp from_stacktrace ( [ { module , function , args , _ } | _ ] ) when is_list ( args ) do
@@ -423,50 +386,4 @@ defmodule Exception do
423
386
defp from_stacktrace ( _ ) do
424
387
{ nil , nil , nil }
425
388
end
426
-
427
-
428
- # have to use :re here because exceptions may be triggered before Regexp
429
- # module is compiled.
430
- @ function_name_re :re . compile (
431
- % S {
432
- \A(
433
- [ \w] + [ ?! ] ?
434
- | ->
435
- | <-
436
- | ::
437
- | \|{ 1 , 3 }
438
- | =
439
- | &&&?
440
- | <=?
441
- | >=?
442
- | === ?
443
- | !==?
444
- | =~
445
- | <<<
446
- | >>>
447
- | \+ \+ ?
448
- | -- ?
449
- | <>
450
- | \+
451
- | -
452
- | \*
453
- | //?
454
- | ^^^
455
- | !
456
- | \^
457
- | &
458
- | ~~~
459
- | @
460
- ) \z} , [ :extended ] )
461
-
462
- defp maybe_quote_name ( fun ) do
463
- name = to_string ( fun )
464
- { :ok , re } = @ function_name_re
465
- case :re . run ( name , re ) do
466
- { :match , _ } -> name
467
- _ -> inspect name
468
- end
469
- end
470
-
471
-
472
389
end
0 commit comments