Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5131c6be9d | ||
|
|
e3f3dce208 | ||
|
|
5ebd0d2b0b | ||
|
|
e25c37108a | ||
|
|
0b30f6495b | ||
|
|
f126e9f6f6 | ||
|
|
ca06fbf6e0 | ||
|
|
20621d41c6 | ||
|
|
600ca02749 | ||
|
|
241e13da98 | ||
|
|
9c8250a092 |
+26
-5
@@ -109,9 +109,26 @@ You can now also install archives from Hex in this way. Since they are fetched a
|
||||
|
||||
It is also possible to install escripts and archives by providing a Git/GitHub repo. See `mix help escript.install` and `mix help archive.install` for more details.
|
||||
|
||||
## v1.4.5 (2017-06-22)
|
||||
|
||||
This version includes changes that make Elixir fully compatible with Erlang/OTP 20.
|
||||
|
||||
### 1. Enhancements
|
||||
|
||||
#### Logger
|
||||
|
||||
* [Logger] Handle changes to crash reports in OTP 20
|
||||
|
||||
### 2. Bug fixes
|
||||
|
||||
#### Elixir
|
||||
|
||||
* [DateTime] Fix `DateTime.from_iso8601/2` when offset has no colon
|
||||
* [Registry] Do not leak EXIT messages on `Registry.dispatch/3`
|
||||
|
||||
## v1.4.4 (2017-05-15)
|
||||
|
||||
This version includes changes that make Elixir fully compatible with Erlang OTP 20-rc.1.
|
||||
This version includes changes that make Elixir fully compatible with Erlang/OTP 20-rc.1.
|
||||
|
||||
### 1. Bug fixes
|
||||
|
||||
@@ -121,7 +138,7 @@ This version includes changes that make Elixir fully compatible with Erlang OTP
|
||||
|
||||
## v1.4.3 (2017-05-15)
|
||||
|
||||
This version includes changes that make Elixir fully compatible with Erlang OTP 20-rc.1.
|
||||
This version includes changes that make Elixir fully compatible with Erlang/OTP 20-rc.1.
|
||||
|
||||
### 1. Enhancements
|
||||
|
||||
@@ -145,6 +162,7 @@ This version includes changes that make Elixir fully compatible with Erlang OTP
|
||||
|
||||
* [Kernel] Fix code generation when non-binary bitstrings are in AST
|
||||
* [Record] Properly escape fields passed to `defrecord`
|
||||
* [Version] Reject leading zeros according to the SemVer spec
|
||||
|
||||
#### ExUnit
|
||||
|
||||
@@ -320,14 +338,17 @@ This version includes changes that make Elixir fully compatible with Erlang OTP
|
||||
|
||||
#### Elixir
|
||||
|
||||
* [Access] `Access.key/1` is deprecated due to erratic behaviour for missing keys, please use `Access.key/2` instead with proper default values
|
||||
* [Access] `Access.key/1` is deprecated due to erratic behaviour for missing keys, please use `Access.key/2` instead with proper default values
|
||||
* [Behaviour] The `Behaviour` module is deprecated. Callbacks may now be defined directly via the `@callback` attribute
|
||||
* [Enum] Deprecate `Enum.uniq/2` in favor of `Enum.uniq_by/2`
|
||||
* [Float] `Float.to_char_list/2` and `Float.to_string/2` are deprecated (use the `:erlang.float_to_list/2` and `:erlang.float_to_binary/2` functions if such conversions are desired)
|
||||
* [Kernel] Deprecate support for making private functions overridable. Overridable functions must always be public as they must be contracts
|
||||
* [HashDict] The `HashDict` module is deprecated, in favour of the `Map`
|
||||
* [HashSet] The `HashDict` module is deprecated, in favour of the `MapSet`
|
||||
* [Kernel] Deprecate support for making private functions overridable. Overridable functions must always be public as they must be contracts
|
||||
* [Kernel] Anonymous functions with no expression after `->`, in favor of using an expression or returning `nil`
|
||||
* [Kernel] Warn if variable is used as a function call
|
||||
* [OptionParser] Deprecate aliases with multiple letters, such as `-abc`
|
||||
* [Set] Deprecate the `Set` module
|
||||
* [Set] Deprecation of the `Set` module in favor of `MapSet`
|
||||
* [Stream] Deprecate `Stream.uniq/2` in favor of `Stream.uniq_by/2`
|
||||
|
||||
#### IEx
|
||||
|
||||
@@ -240,6 +240,14 @@ defmodule Calendar.ISO do
|
||||
do: parse_offset(1, hour, min, rest)
|
||||
def parse_offset(<<?-, hour::2-bytes, ?:, min::2-bytes, rest::binary>>),
|
||||
do: parse_offset(-1, hour, min, rest)
|
||||
def parse_offset(<<?+, hour::2-bytes, min::2-bytes, rest::binary>>),
|
||||
do: parse_offset(1, hour, min, rest)
|
||||
def parse_offset(<<?-, hour::2-bytes, min::2-bytes, rest::binary>>),
|
||||
do: parse_offset(-1, hour, min, rest)
|
||||
def parse_offset(<<?+, hour::2-bytes, rest::binary>>),
|
||||
do: parse_offset(1, hour, "00", rest)
|
||||
def parse_offset(<<?-, hour::2-bytes, rest::binary>>),
|
||||
do: parse_offset(-1, hour, "00", rest)
|
||||
def parse_offset(_),
|
||||
do: :error
|
||||
|
||||
|
||||
@@ -359,11 +359,13 @@ defmodule Registry do
|
||||
end
|
||||
defp dispatch_task(registry, key, mfa_or_fun, partition) do
|
||||
partition = partition - 1
|
||||
parent = self()
|
||||
task = Task.async(fn ->
|
||||
registry
|
||||
|> key_ets!(partition)
|
||||
|> safe_lookup_second(key)
|
||||
|> apply_non_empty_to_mfa_or_fun(mfa_or_fun)
|
||||
Process.unlink(parent)
|
||||
:ok
|
||||
end)
|
||||
[task | dispatch_task(registry, key, mfa_or_fun, partition)]
|
||||
|
||||
@@ -6,8 +6,8 @@ Elixir treats documentation as a first-class citizen. This means documentation s
|
||||
|
||||
Elixir documentation is written using Markdown. There are plenty of guides on Markdown online, we recommend the ones available on GitHub as a getting started point:
|
||||
|
||||
* [https://help.github.com/articles/markdown-basics/](https://help.github.com/articles/markdown-basics/)
|
||||
* [https://help.github.com/articles/markdown-basics/](https://help.github.com/articles/github-flavored-markdown/)
|
||||
* [Basic writing and formatting syntax](https://help.github.com/articles/basic-writing-and-formatting-syntax/)
|
||||
* [Mastering Markdown](https://guides.github.com/features/mastering-markdown/)
|
||||
|
||||
## Module Attributes
|
||||
|
||||
|
||||
@@ -163,4 +163,36 @@ defmodule DateTimeTest do
|
||||
assert DateTime.compare(datetime1, datetime2) == :lt
|
||||
assert DateTime.compare(datetime2, datetime1) == :gt
|
||||
end
|
||||
|
||||
test "from_iso8601/1 with tz offsets" do
|
||||
assert DateTime.from_iso8601("2017-06-02T14:00:00+01:00") |> elem(1) ==
|
||||
%DateTime{year: 2017, month: 6, day: 2, zone_abbr: "UTC",
|
||||
hour: 13, minute: 0, second: 0, microsecond: {0, 0},
|
||||
utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
|
||||
|
||||
assert DateTime.from_iso8601("2017-06-02T14:00:00-04:00") |> elem(1) ==
|
||||
%DateTime{year: 2017, month: 6, day: 2, zone_abbr: "UTC",
|
||||
hour: 18, minute: 0, second: 0, microsecond: {0, 0},
|
||||
utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
|
||||
|
||||
assert DateTime.from_iso8601("2017-06-02T14:00:00+0100") |> elem(1) ==
|
||||
%DateTime{year: 2017, month: 6, day: 2, zone_abbr: "UTC",
|
||||
hour: 13, minute: 0, second: 0, microsecond: {0, 0},
|
||||
utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
|
||||
|
||||
assert DateTime.from_iso8601("2017-06-02T14:00:00-0400") |> elem(1) ==
|
||||
%DateTime{year: 2017, month: 6, day: 2, zone_abbr: "UTC",
|
||||
hour: 18, minute: 0, second: 0, microsecond: {0, 0},
|
||||
utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
|
||||
|
||||
assert DateTime.from_iso8601("2017-06-02T14:00:00+01") |> elem(1) ==
|
||||
%DateTime{year: 2017, month: 6, day: 2, zone_abbr: "UTC",
|
||||
hour: 13, minute: 0, second: 0, microsecond: {0, 0},
|
||||
utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
|
||||
|
||||
assert DateTime.from_iso8601("2017-06-02T14:00:00-04") |> elem(1) ==
|
||||
%DateTime{year: 2017, month: 6, day: 2, zone_abbr: "UTC",
|
||||
hour: 18, minute: 0, second: 0, microsecond: {0, 0},
|
||||
utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -207,6 +207,8 @@ defmodule RegistryTest do
|
||||
end
|
||||
|
||||
test "dispatches to multiple keys", %{registry: registry} do
|
||||
Process.flag(:trap_exit, true)
|
||||
|
||||
assert Registry.dispatch(registry, "hello", fn _ ->
|
||||
raise "will never be invoked"
|
||||
end) == :ok
|
||||
@@ -230,6 +232,8 @@ defmodule RegistryTest do
|
||||
refute_received {:dispatch, :value1}
|
||||
refute_received {:dispatch, :value2}
|
||||
assert_received {:dispatch, :value3}
|
||||
|
||||
refute_received {:EXIT, _, _}
|
||||
end
|
||||
|
||||
test "allows process unregistering", %{registry: registry} do
|
||||
|
||||
@@ -11,7 +11,7 @@ defmodule ExUnit.OnExitHandler do
|
||||
Agent.update(@name, &Map.put(&1, pid, []))
|
||||
end
|
||||
|
||||
@spec add(pid, term, (()-> term)) :: :ok | :error
|
||||
@spec add(pid, term, (() -> term)) :: :ok | :error
|
||||
def add(pid, name_or_ref, callback) when is_pid(pid) and is_function(callback, 0) do
|
||||
Agent.get_and_update(@name, fn map ->
|
||||
if entries = Map.get(map, pid) do
|
||||
|
||||
@@ -102,7 +102,7 @@ defmodule IEx.Autocomplete do
|
||||
if prefix in [0, length] do
|
||||
yes("", Enum.flat_map(entries, &to_entries/1))
|
||||
else
|
||||
yes(:binary.part(first.name, prefix, length-prefix), [])
|
||||
yes(:binary.part(first.name, prefix, length - prefix), [])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -212,7 +212,7 @@ defmodule IEx.Autocomplete do
|
||||
for mod <- match_modules(base, module === Elixir),
|
||||
parts = String.split(mod, "."),
|
||||
depth <= length(parts) do
|
||||
%{kind: :module, type: :elixir, name: Enum.at(parts, depth-1)}
|
||||
%{kind: :module, type: :elixir, name: Enum.at(parts, depth - 1)}
|
||||
end
|
||||
|> Enum.uniq
|
||||
end
|
||||
|
||||
@@ -97,7 +97,7 @@ defmodule Logger.Translator do
|
||||
[supervisor: sup, errorContext: context,
|
||||
reason: reason,
|
||||
offender: [{:pid, pid}, {name_or_id, name} | offender]])
|
||||
when is_pid(pid) and context !== :shutdown and name_or_id in [:name, :id] do
|
||||
when is_pid(pid) and context !== :shutdown and name_or_id in [:name, :id] do
|
||||
{:ok, ["Child ", inspect(name), " of Supervisor ",
|
||||
sup_name(sup), ?\s, sup_context(context),
|
||||
"\n** (exit) ", offender_reason(reason, context),
|
||||
@@ -106,37 +106,37 @@ defmodule Logger.Translator do
|
||||
end
|
||||
|
||||
defp translate_supervisor(min_level,
|
||||
[supervisor: sup, errorContext: context,
|
||||
[supervisor: sup, errorContext: context,
|
||||
reason: reason,
|
||||
offender: [{:pid, _pid},
|
||||
{name_or_id, name} | offender]]) when name_or_id in [:name, :id] do
|
||||
{:ok, ["Child ", inspect(name), " of Supervisor ",
|
||||
sup_name(sup), ?\s, sup_context(context),
|
||||
"\n** (exit) ", offender_reason(reason, context) |
|
||||
child_info(min_level, offender)]}
|
||||
sup_name(sup), ?\s, sup_context(context),
|
||||
"\n** (exit) ", offender_reason(reason, context) |
|
||||
child_info(min_level, offender)]}
|
||||
end
|
||||
|
||||
defp translate_supervisor(min_level,
|
||||
[supervisor: sup, errorContext: context,
|
||||
[supervisor: sup, errorContext: context,
|
||||
reason: reason,
|
||||
offender: [{:pid, pid} | offender]]) do
|
||||
{:ok, ["Child of Supervisor ",
|
||||
sup_name(sup), ?\s, sup_context(context),
|
||||
"\n** (exit) ", offender_reason(reason, context),
|
||||
"\nPid: ", inspect(pid) |
|
||||
child_info(min_level, offender)]}
|
||||
sup_name(sup), ?\s, sup_context(context),
|
||||
"\n** (exit) ", offender_reason(reason, context),
|
||||
"\nPid: ", inspect(pid) |
|
||||
child_info(min_level, offender)]}
|
||||
end
|
||||
|
||||
defp translate_supervisor(min_level,
|
||||
[supervisor: sup, errorContext: context,
|
||||
[supervisor: sup, errorContext: context,
|
||||
reason: reason,
|
||||
offender: [{:nb_children, n},
|
||||
{name_or_id, name} | offender]]) when name_or_id in [:name, :id] do
|
||||
{:ok, ["Children ", inspect(name), " of Supervisor ",
|
||||
sup_name(sup), ?\s, sup_context(context),
|
||||
"\n** (exit) ", offender_reason(reason, context),
|
||||
"\nNumber: ", inspect(n) |
|
||||
child_info(min_level, offender)]}
|
||||
sup_name(sup), ?\s, sup_context(context),
|
||||
"\n** (exit) ", offender_reason(reason, context),
|
||||
"\nNumber: ", inspect(n) |
|
||||
child_info(min_level, offender)]}
|
||||
end
|
||||
|
||||
defp translate_supervisor(_min_level, _other), do: :none
|
||||
@@ -148,19 +148,19 @@ defmodule Logger.Translator do
|
||||
|
||||
defp translate_progress(min_level,
|
||||
[supervisor: sup,
|
||||
started: [{:pid, pid}, {name_or_id, name} | started]]) when name_or_id in [:name, :id] do
|
||||
started: [{:pid, pid}, {name_or_id, name} | started]]) when name_or_id in [:name, :id] do
|
||||
{:ok, ["Child ", inspect(name), " of Supervisor ",
|
||||
sup_name(sup), " started",
|
||||
"\nPid: ", inspect(pid) |
|
||||
child_info(min_level, started)]}
|
||||
sup_name(sup), " started",
|
||||
"\nPid: ", inspect(pid) |
|
||||
child_info(min_level, started)]}
|
||||
end
|
||||
|
||||
defp translate_progress(min_level,
|
||||
[supervisor: sup,
|
||||
started: [{:pid, pid} | started]]) do
|
||||
started: [{:pid, pid} | started]]) do
|
||||
{:ok, ["Child of Supervisor ", sup_name(sup), " started",
|
||||
"\nPid: ", inspect(pid) |
|
||||
child_info(min_level, started)]}
|
||||
"\nPid: ", inspect(pid) |
|
||||
child_info(min_level, started)]}
|
||||
end
|
||||
|
||||
defp translate_progress(_min_level, _other), do: :none
|
||||
@@ -177,17 +177,17 @@ defmodule Logger.Translator do
|
||||
|
||||
defp child_info(min_level, [{:mfargs, {mod, fun, args}} | debug]) do
|
||||
["\nStart Call: ", format_mfa(mod, fun, args) |
|
||||
child_debug(min_level, debug)]
|
||||
child_debug(min_level, debug)]
|
||||
end
|
||||
|
||||
defp child_info(min_level, [{:mfa, {mod, fun, args}} | debug]) do
|
||||
["\nStart Call: ", format_mfa(mod, fun, args) |
|
||||
child_debug(min_level, debug)]
|
||||
child_debug(min_level, debug)]
|
||||
end
|
||||
|
||||
defp child_info(min_level, [{:mod, mod} | debug]) do
|
||||
["\nStart Module: ", inspect(mod) |
|
||||
child_debug(min_level, debug)]
|
||||
child_debug(min_level, debug)]
|
||||
end
|
||||
|
||||
defp child_debug(:debug,
|
||||
@@ -217,9 +217,9 @@ defmodule Logger.Translator do
|
||||
{:error_info, {kind, exception, stack}} | crashed],
|
||||
linked]) do
|
||||
{:ok, ["Process ", crash_name(pid, name), " terminating",
|
||||
format(kind, exception, stack),
|
||||
crash_info(min_level, [initial_call | crashed]) |
|
||||
crash_linked(min_level, linked)]}
|
||||
format(kind, exception, stack),
|
||||
crash_info(min_level, [initial_call | crashed]) |
|
||||
crash_linked(min_level, linked)]}
|
||||
end
|
||||
|
||||
defp translate_crash(min_level,
|
||||
@@ -228,9 +228,9 @@ defmodule Logger.Translator do
|
||||
{:error_info, {kind, exception, stack}} | crashed],
|
||||
linked]) do
|
||||
{:ok, ["Process ", crash_name(pid, name), " terminating",
|
||||
format(kind, exception, stack),
|
||||
crash_info(min_level, crashed),
|
||||
crash_linked(min_level, linked)]}
|
||||
format(kind, exception, stack),
|
||||
crash_info(min_level, crashed),
|
||||
crash_linked(min_level, linked)]}
|
||||
end
|
||||
|
||||
defp crash_name(pid, []), do: inspect(pid)
|
||||
@@ -241,13 +241,13 @@ defmodule Logger.Translator do
|
||||
defp crash_info(min_level,
|
||||
[{:initial_call, {mod, fun, args}} | info], prefix) do
|
||||
[prefix, "Initial Call: ", crash_call(mod, fun, args) |
|
||||
crash_info(min_level, info, prefix)]
|
||||
crash_info(min_level, info, prefix)]
|
||||
end
|
||||
|
||||
defp crash_info(min_level,
|
||||
[{:current_function, {mod, fun, args}} | info], prefix) do
|
||||
[prefix, "Current Call: ", crash_call(mod, fun, args) |
|
||||
crash_info(min_level, info, prefix)]
|
||||
crash_info(min_level, info, prefix)]
|
||||
end
|
||||
|
||||
defp crash_info(min_level, [{:current_function, []} | info], prefix) do
|
||||
@@ -257,7 +257,17 @@ defmodule Logger.Translator do
|
||||
defp crash_info(min_level,
|
||||
[{:ancestors, ancestors} | debug], prefix) do
|
||||
[prefix, "Ancestors: ", inspect(ancestors) |
|
||||
crash_debug(min_level, debug, prefix)]
|
||||
crash_info(min_level, debug, prefix)]
|
||||
end
|
||||
|
||||
defp crash_info(:debug, debug, prefix) do
|
||||
for {key, value} <- debug do
|
||||
crash_debug(key, value, prefix)
|
||||
end
|
||||
end
|
||||
|
||||
defp crash_info(_, _, _) do
|
||||
[]
|
||||
end
|
||||
|
||||
defp crash_call(mod, fun, arity) when is_integer(arity) do
|
||||
@@ -268,22 +278,28 @@ defmodule Logger.Translator do
|
||||
format_mfa(mod, fun, length(args))
|
||||
end
|
||||
|
||||
defp crash_debug(:debug,
|
||||
[messages: msgs, links: links, dictionary: dict,
|
||||
trap_exit: trap, status: status, heap_size: heap_size,
|
||||
stack_size: stack_size, reductions: reductions], prefix) do
|
||||
[prefix, "Messages: ", inspect(msgs),
|
||||
prefix, "Links: ", inspect(links),
|
||||
prefix, "Dictionary: ", inspect(dict),
|
||||
prefix, "Trapping Exits: ", inspect(trap),
|
||||
prefix, "Status: ", inspect(status),
|
||||
prefix, "Heap Size: ", inspect(heap_size),
|
||||
prefix, "Stack Size: ", inspect(stack_size),
|
||||
prefix, "Reductions: ", inspect(reductions)]
|
||||
defp crash_debug(:current_stacktrace, stack, prefix) do
|
||||
stack_prefix = [prefix | " "]
|
||||
[prefix, "Current Stacktrace:" |
|
||||
Enum.map(stack, &[stack_prefix | Exception.format_stacktrace_entry(&1)])]
|
||||
end
|
||||
|
||||
defp crash_debug(_min_level, _info, _prefix) do
|
||||
[]
|
||||
defp crash_debug(key, value, prefix) do
|
||||
[prefix, crash_debug_key(key), ?:, ?\s, inspect(value)]
|
||||
end
|
||||
|
||||
defp crash_debug_key(key) do
|
||||
case key do
|
||||
:message_queue_len -> "Message Queue Length"
|
||||
:messages -> "Messages"
|
||||
:links -> "Links"
|
||||
:dictionary -> "Dictionary"
|
||||
:trap_exit -> "Trapping Exits"
|
||||
:status -> "Status"
|
||||
:heap_size -> "Heap Size"
|
||||
:stack_size -> "Stack Size"
|
||||
:reductions -> "Reductions"
|
||||
end
|
||||
end
|
||||
|
||||
defp crash_linked(_min_level, []), do: []
|
||||
@@ -298,17 +314,17 @@ defmodule Logger.Translator do
|
||||
[{:pid, pid}, {:registered_name, []} | info]) do
|
||||
indent = " "
|
||||
[?\n, indent, inspect(pid) |
|
||||
crash_info(min_level, info, [?\n, indent | indent])]
|
||||
crash_info(min_level, info, [?\n, indent | indent])]
|
||||
end
|
||||
|
||||
defp crash_neighbour(min_level,
|
||||
[{:pid, pid}, {:registered_name, name} | info]) do
|
||||
indent = " "
|
||||
[?\n, indent, inspect(name), " (", inspect(pid), ")" |
|
||||
crash_info(min_level, info, [?\n, indent | indent])]
|
||||
crash_info(min_level, info, [?\n, indent | indent])]
|
||||
end
|
||||
|
||||
defp format_stop({maybe_exception, [_ | _ ] = maybe_stacktrace} = reason) do
|
||||
defp format_stop({maybe_exception, [_ | _] = maybe_stacktrace} = reason) do
|
||||
try do
|
||||
format_stacktrace(maybe_stacktrace)
|
||||
catch
|
||||
@@ -316,8 +332,7 @@ defmodule Logger.Translator do
|
||||
format_stop_banner(reason)
|
||||
else
|
||||
formatted_stacktrace ->
|
||||
[format_stop_banner(maybe_exception, maybe_stacktrace) |
|
||||
formatted_stacktrace]
|
||||
[format_stop_banner(maybe_exception, maybe_stacktrace) | formatted_stacktrace]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -332,8 +347,8 @@ defmodule Logger.Translator do
|
||||
# OTP processes rewrite the :undef error to these reasons when logging
|
||||
@gen_undef [:"module could not be loaded", :"function not exported"]
|
||||
|
||||
defp format_stop_banner(undef, [{mod, fun, args, _info} | _ ] = stacktrace)
|
||||
when undef in @gen_undef and is_atom(mod) and is_atom(fun) do
|
||||
defp format_stop_banner(undef, [{mod, fun, args, _info} | _] = stacktrace)
|
||||
when undef in @gen_undef and is_atom(mod) and is_atom(fun) do
|
||||
cond do
|
||||
is_list(args) ->
|
||||
format_undef(mod, fun, length(args), undef, stacktrace)
|
||||
@@ -345,8 +360,11 @@ defmodule Logger.Translator do
|
||||
end
|
||||
|
||||
defp format_stop_banner(reason, stacktrace) do
|
||||
# If this is already an exception (even an ErlangError), we format it as an
|
||||
# exception. Otherwise, we try to normalize it, and if it's normalized as an
|
||||
# ErlangError we instead format it as an exit.
|
||||
if Exception.exception?(reason) do
|
||||
[?\n | Exception.format_banner(:error, reason, stacktrace)]
|
||||
[?\n | Exception.format_banner(:error, reason, stacktrace)]
|
||||
else
|
||||
case Exception.normalize(:error, reason, stacktrace) do
|
||||
%ErlangError{} ->
|
||||
@@ -369,9 +387,9 @@ defmodule Logger.Translator do
|
||||
end
|
||||
|
||||
defp format_stacktrace(stacktrace) do
|
||||
for entry <- stacktrace do
|
||||
[<<"\n ">> | Exception.format_stacktrace_entry(entry)]
|
||||
end
|
||||
for entry <- stacktrace do
|
||||
[<<"\n ">> | Exception.format_stacktrace_entry(entry)]
|
||||
end
|
||||
end
|
||||
|
||||
defp format_mfa(mod, fun, :undefined), do: [inspect(mod), ?., to_string(fun) | "/?"]
|
||||
|
||||
@@ -32,10 +32,10 @@ defmodule Logger.Utils do
|
||||
end
|
||||
end
|
||||
|
||||
defp truncate_n(int, n) when int in 0..127, do: {int, n-1}
|
||||
defp truncate_n(int, n) when int in 127..0x07FF, do: {int, n-2}
|
||||
defp truncate_n(int, n) when int in 0x800..0xFFFF, do: {int, n-3}
|
||||
defp truncate_n(int, n) when int >= 0x10000 and is_integer(int), do: {int, n-4}
|
||||
defp truncate_n(int, n) when int in 0..127, do: {int, n - 1}
|
||||
defp truncate_n(int, n) when int in 127..0x07FF, do: {int, n - 2}
|
||||
defp truncate_n(int, n) when int in 0x800..0xFFFF, do: {int, n - 3}
|
||||
defp truncate_n(int, n) when int >= 0x10000 and is_integer(int), do: {int, n - 4}
|
||||
|
||||
defp truncate_n(list, n) when is_list(list) do
|
||||
truncate_n_list(list, n, [])
|
||||
|
||||
@@ -472,7 +472,8 @@ defmodule Logger.TranslatorTest do
|
||||
send(pid, :go)
|
||||
receive do: ({:DOWN, ^ref, _, _, _} -> :ok)
|
||||
end) =~ ~r"""
|
||||
Ancestors: \[#PID<\d+\.\d+\.\d+>\]
|
||||
Ancestors: \[#PID<\d+\.\d+\.\d+>\](?:
|
||||
Message Queue Length: 1(?#TODO: Require once depend on 20)|)
|
||||
Messages: \[:message\]
|
||||
Links: \[\]
|
||||
Dictionary: \[\]
|
||||
@@ -493,15 +494,18 @@ defmodule Logger.TranslatorTest do
|
||||
send(pid, :go)
|
||||
receive do: ({:DOWN, ^ref, _, _, _} -> :ok)
|
||||
end) =~ ~r"""
|
||||
Ancestors: \[#PID<\d+\.\d+\.\d+>, #PID<\d+\.\d+\.\d+>\]
|
||||
Messages: \[\]
|
||||
Links: \[#PID<\d+\.\d+\.\d+>\]
|
||||
Dictionary: \[\]
|
||||
Ancestors: \[#PID<\d+\.\d+\.\d+>, #PID<\d+\.\d+\.\d+>\](?:
|
||||
Message Queue Length: 0|
|
||||
Messages: \[\](?# TODO: Remove once depend on 20))
|
||||
Links: \[#PID<\d+\.\d+\.\d+>\](?:|
|
||||
Dictionary: \[\](?# TODO: Remove once depend on 20))
|
||||
Trapping Exits: false
|
||||
Status: :waiting
|
||||
Heap Size: \d+
|
||||
Stack Size: \d+
|
||||
Reductions: \d+
|
||||
Reductions: \d+(?:
|
||||
Current Stacktrace:
|
||||
test/logger/translator_test.exs:\d+: Logger.TranslatorTest.sleep/1(?#TODO: Require once depend on 20)|)
|
||||
"""
|
||||
end
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ defmodule Mix.Generator do
|
||||
@file file
|
||||
File.read!(file)
|
||||
c when is_binary(c) ->
|
||||
@file {__ENV__.file, __ENV__.line+1}
|
||||
@file {__ENV__.file, __ENV__.line + 1}
|
||||
c
|
||||
_ ->
|
||||
raise ArgumentError, "expected string or from_file: file"
|
||||
|
||||
@@ -255,7 +255,7 @@ defmodule Mix.Local.Installer do
|
||||
path = Path.join(root, name)
|
||||
cond do
|
||||
not File.exists?(path) ->
|
||||
Mix.shell.error "Could not find a local #{item_name} named #{inspect name}. "<>
|
||||
Mix.shell.error "Could not find a local #{item_name} named #{inspect name}. " <>
|
||||
"Existing #{item_plural} are:"
|
||||
Mix.Task.run item_name
|
||||
nil
|
||||
|
||||
@@ -119,11 +119,11 @@ defmodule Mix.Tasks.New do
|
||||
defp otp_app(mod, true) do
|
||||
" [extra_applications: [:logger],\n mod: {#{mod}.Application, []}]"
|
||||
end
|
||||
|
||||
|
||||
defp cd_path(".") do
|
||||
""
|
||||
end
|
||||
|
||||
|
||||
defp cd_path(path) do
|
||||
"cd #{path}\n "
|
||||
end
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{application, elixir,
|
||||
[{description, "elixir"},
|
||||
{vsn, "1.4.4"},
|
||||
{vsn, "1.4.5"},
|
||||
{modules, [
|
||||
elixir
|
||||
]},
|
||||
|
||||
Reference in New Issue
Block a user