@@ -10,21 +10,21 @@ defexception SystemLimitError, message: "a system limit has been reached"
1010defexception SyntaxError , [ file: nil , line: nil , description: "syntax error" ] do
1111 def message ( exception ) do
1212 Exception . format_file_line ( Path . relative_to_cwd ( exception . file ) , exception . line ) <>
13- exception . description
13+ " " <> exception . description
1414 end
1515end
1616
1717defexception TokenMissingError , [ file: nil , line: nil , description: "expression is incomplete" ] do
1818 def message ( exception ) do
1919 Exception . format_file_line ( Path . relative_to_cwd ( exception . file ) , exception . line ) <>
20- exception . description
20+ " " <> exception . description
2121 end
2222end
2323
2424defexception CompileError , [ file: nil , line: nil , description: "compile error" ] do
2525 def message ( exception ) do
2626 Exception . format_file_line ( Path . relative_to_cwd ( exception . file ) , exception . line ) <>
27- exception . description
27+ " " <> exception . description
2828 end
2929end
3030
@@ -149,6 +149,16 @@ defmodule Exception do
149149 pass the `System.stacktrace` as argument.
150150 """
151151
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+
152162 @ doc """
153163 Normalizes an exception, converting Erlang exceptions
154164 to Elixir exceptions.
@@ -221,48 +231,38 @@ defmodule Exception do
221231 end
222232
223233 @ 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.
237235 """
236+ @ spec format_stacktrace_entry ( stacktrace_entry ) :: String . t
237+ def format_stacktrace_entry ( entry )
238238
239239 # 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)"
242242 end
243243
244244 # 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)"
247247 end
248248
249249 # 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)"
252252 end
253253
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 )
256256 end
257257
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 )
260260 end
261261
262262 defp format_application ( module ) do
263263 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 -> ""
266266 end
267267 end
268268
@@ -285,29 +285,6 @@ defmodule Exception do
285285 end
286286 end
287287
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-
311288 @ doc """
312289 Receives an anonymous function and arity and formats it as
313290 shown in stacktraces. The arity may also be a list of arguments.
@@ -326,8 +303,9 @@ defmodule Exception do
326303 Receives a module, fun and arity and formats it
327304 as shown in stacktraces. The arity may also be a list
328305 of arguments.
329-
306+
330307 ## Examples
308+
331309 iex> Exception.format_mfa Foo, :bar, 1
332310 "Foo.bar/1"
333311 iex> Exception.format_mfa Foo, :bar, []
@@ -337,66 +315,51 @@ defmodule Exception do
337315
338316 Anonymous functions are reported as -func/arity-anonfn-count-,
339317 where func is the name of the enclosing function. Convert to
340- "nth fn in func/arity"
318+ "anonymous fn in func/arity"
341319 """
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
342326
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
363333 end
364334
365335 defp format_arity ( arity ) when is_list ( arity ) do
366336 inspected = lc x inlist arity , do: inspect ( x )
367337 "(#{ Enum . join ( inspected , ", " ) } )"
368338 end
369339
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 } "
377341
378342 @ doc """
379343 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.
383345
384346 ## Examples
385347
386348 iex> Exception.format_file_line("foo", 1)
387- "foo:1: "
388-
389- iex> Exception.format_file_line("foo", 1, "")
390349 "foo:1:"
391350
392351 iex> Exception.format_file_line("foo", nil)
393- "foo: "
352+ "foo:"
394353
395354 iex> Exception.format_file_line(nil, nil)
396355 ""
397356
398357 """
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
400363 if file do
401364 if line && line != 0 do
402365 "#{ file } :#{ line } :#{ suffix } "
@@ -409,7 +372,7 @@ defmodule Exception do
409372 end
410373
411374 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 ) , " "
413376 end
414377
415378 defp from_stacktrace ( [ { module , function , args , _ } | _ ] ) when is_list ( args ) do
@@ -423,50 +386,4 @@ defmodule Exception do
423386 defp from_stacktrace ( _ ) do
424387 { nil , nil , nil }
425388 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-
472389end
0 commit comments