summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@plataformatec.com.br>2018-05-08 16:28:24 +0200
committerJosé Valim <jose.valim@plataformatec.com.br>2018-07-12 12:12:00 +0200
commit35ac568044aca779d2c000f39cee974cae9cf0c0 (patch)
treed4dba95282e31cc7db0092fc3fdb5ce85c5b575b
parent7b9cb85646355ec0706dd0e0fc165c937d5cbba7 (diff)
downloadelixir-35ac568044aca779d2c000f39cee974cae9cf0c0.tar.gz
Require Erlang/OTP 20+
-rw-r--r--.travis.yml4
-rw-r--r--Makefile4
-rw-r--r--README.md4
-rw-r--r--lib/elixir/lib/application.ex6
-rw-r--r--lib/elixir/lib/code/typespec.ex46
-rw-r--r--lib/elixir/lib/exception.ex2
-rw-r--r--lib/elixir/lib/protocol.ex14
-rw-r--r--lib/elixir/lib/regex.ex7
-rw-r--r--lib/elixir/lib/string.ex6
-rw-r--r--lib/elixir/lib/system.ex4
-rw-r--r--lib/elixir/lib/task/supervised.ex30
-rw-r--r--lib/elixir/pages/Syntax Reference.md8
-rw-r--r--lib/elixir/src/elixir.erl13
-rw-r--r--lib/elixir/src/elixir_erl.erl94
-rw-r--r--lib/elixir/src/elixir_erl_for.erl9
-rw-r--r--lib/elixir/src/elixir_erl_try.erl1
-rw-r--r--lib/elixir/test/elixir/code_formatter/literals_test.exs7
-rw-r--r--lib/elixir/test/elixir/exception_test.exs164
-rw-r--r--lib/elixir/test/elixir/inspect_test.exs22
-rw-r--r--lib/elixir/test/elixir/kernel/binary_test.exs3
-rw-r--r--lib/elixir/test/elixir/kernel/cli_test.exs17
-rw-r--r--lib/elixir/test/elixir/kernel/dialyzer_test.exs8
-rw-r--r--lib/elixir/test/elixir/kernel/errors_test.exs25
-rw-r--r--lib/elixir/test/elixir/kernel/string_tokenizer_test.exs130
-rw-r--r--lib/elixir/test/elixir/kernel/warning_test.exs23
-rw-r--r--lib/elixir/test/elixir/module_test.exs32
-rw-r--r--lib/ex_unit/test/ex_unit/formatter_test.exs51
-rw-r--r--lib/iex/lib/iex.ex21
-rw-r--r--lib/iex/lib/iex/helpers.ex5
-rw-r--r--lib/iex/lib/iex/pry.ex8
-rw-r--r--lib/iex/test/iex/helpers_test.exs164
-rw-r--r--lib/iex/test/iex/interaction_test.exs17
-rw-r--r--lib/iex/test/iex/pry_test.exs302
-rw-r--r--lib/logger/lib/logger/translator.ex5
-rw-r--r--lib/logger/test/logger/translator_test.exs269
-rw-r--r--lib/mix/lib/mix/tasks/escript.build.ex6
36 files changed, 626 insertions, 905 deletions
diff --git a/.travis.yml b/.travis.yml
index c6be9892e..cf9733d02 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,10 +5,6 @@ env:
global:
- ELIXIR_ASSERT_TIMEOUT=2000
matrix:
- - OTP_RELEASE=OTP-19.0
- - OTP_RELEASE=OTP-19.1
- - OTP_RELEASE=OTP-19.2
- - OTP_RELEASE=OTP-19.3
- OTP_RELEASE=OTP-20.0
- OTP_RELEASE=OTP-20.1
- OTP_RELEASE=OTP-20.2
diff --git a/Makefile b/Makefile
index f1df933e1..6ae91a1ae 100644
--- a/Makefile
+++ b/Makefile
@@ -22,9 +22,9 @@ GIT_TAG = $(strip $(shell head="$(call GIT_REVISION)"; git tag --points-at $$hea
#==> Functions
define CHECK_ERLANG_RELEASE
- erl -noshell -eval '{V,_} = string:to_integer(erlang:system_info(otp_release)), io:fwrite("~s", [is_integer(V) and (V >= 19)])' -s erlang halt | grep -q '^true'; \
+ erl -noshell -eval '{V,_} = string:to_integer(erlang:system_info(otp_release)), io:fwrite("~s", [is_integer(V) and (V >= 20)])' -s erlang halt | grep -q '^true'; \
if [ $$? != 0 ]; then \
- echo "At least Erlang/OTP 19.0 is required to build Elixir"; \
+ echo "At least Erlang/OTP 20.0 is required to build Elixir"; \
exit 1; \
fi
endef
diff --git a/README.md b/README.md
index f2513e048..7d876321e 100644
--- a/README.md
+++ b/README.md
@@ -30,10 +30,10 @@ If tests pass, you are ready to move on to the [Getting Started guide][1]
or to try Interactive Elixir by running `bin/iex` in your terminal.
However, if tests fail, it is likely you have an outdated Erlang/OTP version
-(Elixir requires Erlang/OTP 19.0 or later). You can check your Erlang/OTP version
+(Elixir requires Erlang/OTP 20.0 or later). You can check your Erlang/OTP version
by calling `erl` in the command line. You will see some information as follows:
- Erlang/OTP 19 [erts-8.0] [smp:2:2] [async-threads:10] [kernel-poll:false]
+ Erlang/OTP 20 [erts-9.0] [smp:2:2] [async-threads:10] [kernel-poll:false]
If you have properly set up your dependencies and tests still fail,
you may want to open up a bug report, as explained next.
diff --git a/lib/elixir/lib/application.ex b/lib/elixir/lib/application.ex
index 1342d9d08..951986bc8 100644
--- a/lib/elixir/lib/application.ex
+++ b/lib/elixir/lib/application.ex
@@ -197,9 +197,9 @@ defmodule Application do
Shutting down a live system cleanly can be done by calling `System.stop/1`. It
will shut down every application in the opposite order they had been started.
- From Erlang/OTP 19.1, a SIGTERM from the operating system will automatically
- translate to `System.stop/0`. Erlang/OTP 20 gives user more explicit control
- over OS signals via the `:os.set_signal/2` function.
+ By default, a SIGTERM from the operating system will automatically translate to
+ `System.stop/0`. You can also have more explicit control over OS signals via the
+ `:os.set_signal/2` function.
## Tooling
diff --git a/lib/elixir/lib/code/typespec.ex b/lib/elixir/lib/code/typespec.ex
index 581c19d52..af33699e2 100644
--- a/lib/elixir/lib/code/typespec.ex
+++ b/lib/elixir/lib/code/typespec.ex
@@ -152,37 +152,23 @@ defmodule Code.Typespec do
end
end
- # TODO: Do not rely on abstract_code when OTP 20+ support is dropped (v1.8).
- # We should then be able to simplify this code and use `with`.
defp typespecs_abstract_code(module) do
- case get_module_and_beam(module) do
- {module, binary} ->
- case :beam_lib.chunks(binary, [:debug_info]) do
- {:ok, {_, [debug_info: {:debug_info_v1, backend, data}]}} ->
- case data do
- {:elixir_v1, %{}, specs} ->
- # Fast path to avoid translation to Erlang from Elixir.
- {:ok, specs}
-
- _ ->
- case backend.debug_info(:erlang_v1, module, data, []) do
- {:ok, abstract_code} -> {:ok, abstract_code}
- _ -> :error
- end
- end
-
- _ ->
- case :beam_lib.chunks(binary, [:abstract_code]) do
- {:ok, {_, [{:abstract_code, {_raw_abstract_v1, abstract_code}}]}} ->
- {:ok, abstract_code}
-
- _ ->
- :error
- end
- end
-
- :error ->
- :error
+ with {module, binary} <- get_module_and_beam(module),
+ {:ok, {_, [debug_info: {:debug_info_v1, backend, data}]}} <-
+ :beam_lib.chunks(binary, [:debug_info]) do
+ case data do
+ {:elixir_v1, %{}, specs} ->
+ # Fast path to avoid translation to Erlang from Elixir.
+ {:ok, specs}
+
+ _ ->
+ case backend.debug_info(:erlang_v1, module, data, []) do
+ {:ok, abstract_code} -> {:ok, abstract_code}
+ _ -> :error
+ end
+ end
+ else
+ _ -> :error
end
end
diff --git a/lib/elixir/lib/exception.ex b/lib/elixir/lib/exception.ex
index 9e78ef89a..297a5bccc 100644
--- a/lib/elixir/lib/exception.ex
+++ b/lib/elixir/lib/exception.ex
@@ -186,8 +186,6 @@ defmodule Exception do
This function returns either `{:ok, definition, clauses}` or `:error`.
Where `definition` is `:def`, `:defp`, `:defmacro` or `:defmacrop`.
- Note this functionality requires Erlang/OTP 20, otherwise `:error`
- is always returned.
"""
@doc since: "1.5.0"
@spec blame_mfa(module, function, args :: [term]) ::
diff --git a/lib/elixir/lib/protocol.ex b/lib/elixir/lib/protocol.ex
index 59c3261c1..4ecd91613 100644
--- a/lib/elixir/lib/protocol.ex
+++ b/lib/elixir/lib/protocol.ex
@@ -320,10 +320,6 @@ defmodule Protocol do
{:compile_info, compile_info} | extra_chunks
] = entries
- extra_chunks =
- for {name, contents} when is_binary(contents) <- extra_chunks,
- do: {List.to_string(name), contents}
-
case attributes[:protocol] do
[fallback_to_any: any] ->
{:ok, {protocol, any, abstract_code}, {compile_info, extra_chunks}}
@@ -499,7 +495,15 @@ defmodule Protocol do
opts = Keyword.take(compile_info, [:source])
opts = if Code.compiler_options()[:debug_info], do: [:debug_info | opts], else: opts
{:ok, ^protocol, binary, _warnings} = :compile.forms(code, [:return | opts])
- {:ok, :elixir_erl.add_beam_chunks(binary, extra_chunks)}
+ {:ok, add_beam_chunks(binary, extra_chunks)}
+ end
+
+ defp add_beam_chunks(bin, []), do: bin
+
+ defp add_beam_chunks(bin, new_chunks) do
+ {:ok, _, old_chunks} = :beam_lib.all_chunks(bin)
+ {:ok, bin} = :beam_lib.build_module(new_chunks ++ old_chunks)
+ bin
end
## Definition callbacks
diff --git a/lib/elixir/lib/regex.ex b/lib/elixir/lib/regex.ex
index 1183f2ba8..201da459b 100644
--- a/lib/elixir/lib/regex.ex
+++ b/lib/elixir/lib/regex.ex
@@ -211,13 +211,8 @@ defmodule Regex do
"""
@doc since: "1.4.0"
@spec version :: term()
- # TODO: No longer check for function_exported? on OTP 20+.
def version do
- if function_exported?(:re, :version, 0) do
- {:re.version(), :erlang.system_info(:endian)}
- else
- {"8.33 2013-05-29", :erlang.system_info(:endian)}
- end
+ {:re.version(), :erlang.system_info(:endian)}
end
@doc """
diff --git a/lib/elixir/lib/string.ex b/lib/elixir/lib/string.ex
index 6e21ab7d2..ff4718c50 100644
--- a/lib/elixir/lib/string.ex
+++ b/lib/elixir/lib/string.ex
@@ -2130,8 +2130,7 @@ defmodule String do
By default, the maximum number of atoms is `1_048_576`. This limit
can be raised or lowered using the VM option `+t`.
- The maximum atom size is of 255 characters. Prior to Erlang/OTP 20,
- only latin1 characters are allowed.
+ The maximum atom size is of 255 unicode characters.
Inlined by the compiler.
@@ -2149,8 +2148,7 @@ defmodule String do
@doc """
Converts a string to an existing atom.
- The maximum atom size is of 255 characters. Prior to Erlang/OTP 20,
- only latin1 characters are allowed.
+ The maximum atom size is of 255 unicode characters.
Inlined by the compiler.
diff --git a/lib/elixir/lib/system.ex b/lib/elixir/lib/system.ex
index 80ac75ac1..af5038d39 100644
--- a/lib/elixir/lib/system.ex
+++ b/lib/elixir/lib/system.ex
@@ -73,10 +73,6 @@ defmodule System do
parts_per_second` seconds. For example, using the `:millisecond` time unit
is equivalent to using `1000` as the time unit (as the time will be returned
in 1/1000 seconds - milliseconds).
-
- Keep in mind the Erlang API prior to version 19.1 will use `:milli_seconds`,
- `:micro_seconds` and `:nano_seconds` as time units although Elixir normalizes
- their spelling to match the SI convention.
"""
# TODO: Warn all old mappings once Elixir requires Erlang/OTP 19.1+ (on v1.8)
@type time_unit ::
diff --git a/lib/elixir/lib/task/supervised.ex b/lib/elixir/lib/task/supervised.ex
index 1f092d6f0..1d00dba4a 100644
--- a/lib/elixir/lib/task/supervised.ex
+++ b/lib/elixir/lib/task/supervised.ex
@@ -83,43 +83,25 @@ defmodule Task.Supervised do
{mod, fun, length(args)}
end
- # TODO: Remove conditionals once we depend on Erlang/OTP 20+
defp do_apply(info, {module, fun, args} = mfa) do
try do
apply(module, fun, args)
catch
- :error, value ->
- reason = {value, __STACKTRACE__}
- log(info, mfa, reason)
-
- if :erlang.system_info(:otp_release) >= '20' do
- :erlang.raise(:error, value, __STACKTRACE__)
- else
- exit(reason)
- end
-
- :throw, value ->
- reason = {{:nocatch, value}, __STACKTRACE__}
- log(info, mfa, reason)
-
- if :erlang.system_info(:otp_release) >= '20' do
- :erlang.raise(:throw, value, __STACKTRACE__)
- else
- exit(reason)
- end
-
:exit, value
when value == :normal
when value == :shutdown
when tuple_size(value) == 2 and elem(value, 0) == :shutdown ->
:erlang.raise(:exit, value, __STACKTRACE__)
- :exit, value ->
- log(info, mfa, {value, __STACKTRACE__})
- :erlang.raise(:exit, value, __STACKTRACE__)
+ kind, value ->
+ log(info, mfa, {log_value(kind, value), __STACKTRACE__})
+ :erlang.raise(kind, value, __STACKTRACE__)
end
end
+ defp log_value(:throw, value), do: {:nocatch, value}
+ defp log_value(_, value), do: value
+
defp log(info, mfa, reason) do
{fun, args} = get_running(mfa)
diff --git a/lib/elixir/pages/Syntax Reference.md b/lib/elixir/pages/Syntax Reference.md
index 74cbd2502..c009c9a07 100644
--- a/lib/elixir/pages/Syntax Reference.md
+++ b/lib/elixir/pages/Syntax Reference.md
@@ -21,7 +21,7 @@ Integers (`1234`) and floats (`123.4`) in Elixir are represented as a sequence o
### Atoms
-Atoms in Elixir start with a colon (`:`) which must be followed by non-combining Unicode characters and underscore. The atom may continue using a sequence of Unicode characters, including numbers, underscore and `@`. Atoms may end in `!` or `?`. See [Unicode Syntax](unicode-syntax.html) for a formal specification. Unicode characters require Erlang/OTP 20.
+Atoms in Elixir start with a colon (`:`) which must be followed by non-combining Unicode characters and underscore. The atom may continue using a sequence of Unicode characters, including numbers, underscore and `@`. Atoms may end in `!` or `?`. See [Unicode Syntax](unicode-syntax.html) for a formal specification.
All operators in Elixir are also valid atoms. Valid examples are `:foo`, `:FOO`, `:foo_42`, `:foo@bar` and `:++`. Invalid examples are `:@foo` (`@` is not allowed at start), `:123` (numbers are not allowed at start) and `:(*)` (not a valid operator).
@@ -80,13 +80,13 @@ Structs built on the map syntax by passing the struct name between `%` and `{`.
### Variables
-Variables in Elixir must start with underscore or a non-combining Unicode character that is not in uppercase or titlecase. The variable may continue using a sequence of Unicode characters, including numbers and underscore. Variables may end in `?` or `!`. See [Unicode Syntax](unicode-syntax.html) for a formal specification. Unicode characters require Erlang/OTP 20.
+Variables in Elixir must start with underscore or a non-combining Unicode character that is not in uppercase or titlecase. The variable may continue using a sequence of Unicode characters, including numbers and underscore. Variables may end in `?` or `!`. See [Unicode Syntax](unicode-syntax.html) for a formal specification.
[Elixir's naming conventions](naming-conventions.html) recommend variables to be in `snake_case` format.
### Non-qualified calls (local calls)
-Non-qualified calls, such as `add(1, 2)`, must start with underscore or a non-combining Unicode character that is not in uppercase or titlecase. The call may continue using a sequence of Unicode characters, including numbers and underscore. Calls may end in `?` or `!`. See [Unicode Syntax](unicode-syntax.html) for a formal specification. Unicode characters require Erlang/OTP 20.
+Non-qualified calls, such as `add(1, 2)`, must start with underscore or a non-combining Unicode character that is not in uppercase or titlecase. The call may continue using a sequence of Unicode characters, including numbers and underscore. Calls may end in `?` or `!`. See [Unicode Syntax](unicode-syntax.html) for a formal specification.
Parentheses for non-qualified calls are optional, except for zero-arity calls, which would then be ambiguous with variables. If parentheses are used, they must immediately follow the function name *without spaces*. For example, `add (1, 2)` is a syntax error, since `(1, 2)` is treated as an invalid block which is attempted to be given as a single argument to `add`.
@@ -98,7 +98,7 @@ As many programming languages, Elixir also support operators as non-qualified ca
### Qualified calls (remote calls)
-Qualified calls, such as `Math.add(1, 2)`, must start with underscore or a non-combining Unicode character that is not in uppercase or titlecase. The call may continue using a sequence of Unicode characters, including numbers and underscore. Calls may end in `?` or `!`. See [Unicode Syntax](unicode-syntax.html) for a formal specification. Unicode characters require Erlang/OTP 20.
+Qualified calls, such as `Math.add(1, 2)`, must start with underscore or a non-combining Unicode character that is not in uppercase or titlecase. The call may continue using a sequence of Unicode characters, including numbers and underscore. Calls may end in `?` or `!`. See [Unicode Syntax](unicode-syntax.html) for a formal specification.
[Elixir's naming conventions](naming-conventions.html) recommend calls to be in `snake_case` format.
diff --git a/lib/elixir/src/elixir.erl b/lib/elixir/src/elixir.erl
index ce2f4c257..3e9967959 100644
--- a/lib/elixir/src/elixir.erl
+++ b/lib/elixir/src/elixir.erl
@@ -33,9 +33,8 @@ start(_Type, _Args) ->
check_file_encoding(Encoding),
check_endianness(),
- %% TODO: Remove OTPRelease check once we support OTP 20+.
Tokenizer = case code:ensure_loaded('Elixir.String.Tokenizer') of
- {module, Mod} when OTPRelease >= 20 -> Mod;
+ {module, Mod} -> Mod;
_ -> elixir_tokenizer
end,
@@ -103,21 +102,15 @@ preload_common_modules() ->
%% the codebase we can avoid code:ensure_loaded/1 checks.
_ = code:ensure_loaded('Elixir.Kernel'),
_ = code:ensure_loaded('Elixir.Macro.Env'),
-
- %% We need to make sure the re module is preloaded to make
- %% function_exported checks inside Regex.version is fast.
- %% TODO: Remove this once we support OTP 20+.
- _ = code:ensure_loaded(re),
-
ok.
parse_otp_release() ->
%% Whenever we change this check, we should also change escript.build and Makefile.
case string:to_integer(erlang:system_info(otp_release)) of
- {Num, _} when Num >= 19 ->
+ {Num, _} when Num >= 20 ->
Num;
_ ->
- io:format(standard_error, "unsupported Erlang/OTP version, expected Erlang/OTP 19+~n", []),
+ io:format(standard_error, "unsupported Erlang/OTP version, expected Erlang/OTP 20+~n", []),
erlang:halt(1)
end.
diff --git a/lib/elixir/src/elixir_erl.erl b/lib/elixir/src/elixir_erl.erl
index ac45bff87..671c34e69 100644
--- a/lib/elixir/src/elixir_erl.erl
+++ b/lib/elixir/src/elixir_erl.erl
@@ -1,20 +1,9 @@
%% Compiler backend to Erlang.
-module(elixir_erl).
-export([elixir_to_erl/1, definition_to_anonymous/4, compile/1,
- get_ann/1, remote/4, add_beam_chunks/2, debug_info/4,
- scope/1, format_error/1]).
+ get_ann/1, remote/4, debug_info/4, scope/1, format_error/1]).
-include("elixir.hrl").
-%% TODO: Remove extra chunk functionality when OTP 20+.
-
-add_beam_chunks(Bin, []) when is_binary(Bin) ->
- Bin;
-add_beam_chunks(Bin, NewChunks) when is_binary(Bin), is_list(NewChunks) ->
- {ok, _, OldChunks} = beam_lib:all_chunks(Bin),
- Chunks = [{binary_to_list(K), V} || {K, V} <- NewChunks] ++ OldChunks,
- {ok, NewBin} = beam_lib:build_module(Chunks),
- NewBin.
-
%% debug_info callback
debug_info(elixir_v1, _Module, none, _Opts) ->
@@ -268,43 +257,14 @@ add_info_function(Line, Module, Def, Defmacro, Deprecated) ->
AllowedArgs = lists:map(fun(Atom) -> {atom, Line, Atom} end, AllowedAttrs),
Spec =
- %% TODO: Remove this check once we depend only on 20
- case erlang:system_info(otp_release) of
- "19" ->
- {attribute, Line, spec, {{'__info__', 1},
- [{type, Line, 'fun', [
- {type, Line, product, [
- {type, Line, union, AllowedArgs}
- ]},
- {type, Line, union, [
- {type, Line, atom, []},
- {type, Line, list, [
- {type, Line, union, [
- {type, Line, tuple, [
- {type, Line, atom, []},
- {type, Line, any, []}
- ]},
- {type, Line, tuple, [
- {type, Line, atom, []},
- {type, Line, byte, []},
- {type, Line, integer, []}
- ]}
- ]}
- ]}
- ]}
- ]}]
- }};
-
- _ ->
- {attribute, Line, spec, {{'__info__', 1},
- [{type, Line, 'fun', [
- {type, Line, product, [
- {type, Line, union, AllowedArgs}
- ]},
- {type, Line, any, []}
- ]}]
- }}
- end,
+ {attribute, Line, spec, {{'__info__', 1},
+ [{type, Line, 'fun', [
+ {type, Line, product, [
+ {type, Line, union, AllowedArgs}
+ ]},
+ {type, Line, any, []}
+ ]}]
+ }},
Info =
{function, 0, '__info__', 1, [
@@ -470,16 +430,14 @@ attributes_form(Line, Attributes, Forms) ->
% Loading forms
load_form(#{file := File, compile_opts := Opts} = Map, Prefix, Forms, Specs, Chunks) ->
- {ExtraChunks, CompileOpts} = extra_chunks(Chunks, debug_opts(Map, Specs, Opts)),
+ CompileOpts = extra_chunks_opts(Chunks, debug_opts(Map, Specs, Opts)),
{_, Binary} = elixir_erl_compiler:forms(Prefix ++ Specs ++ Forms, File, CompileOpts),
- add_beam_chunks(Binary, ExtraChunks).
+ Binary.
debug_opts(Map, Specs, Opts) ->
- case {supports_debug_tuple(), include_debug_opts(Opts)} of
- {true, true} -> [{debug_info, {?MODULE, {elixir_v1, Map, Specs}}}];
- {true, false} -> [{debug_info, {?MODULE, none}}];
- {false, true} -> [debug_info];
- {false, false} -> []
+ case include_debug_opts(Opts) of
+ true -> [{debug_info, {?MODULE, {elixir_v1, Map, Specs}}}];
+ false -> [{debug_info, {?MODULE, none}}]
end.
include_debug_opts(Opts) ->
@@ -489,28 +447,8 @@ include_debug_opts(Opts) ->
undefined -> elixir_compiler:get_opt(debug_info)
end.
-supports_debug_tuple() ->
- case erlang:system_info(otp_release) of
- "18" -> false;
- "19" -> false;
- _ -> true
- end.
-
-extra_chunks(Chunks, Opts) ->
- Supported = supports_extra_chunks_option(),
-
- case Chunks of
- [] -> {[], Opts};
- _ when Supported -> {[], [{extra_chunks, Chunks} | Opts]};
- _ -> {Chunks, Opts}
- end.
-
-supports_extra_chunks_option() ->
- case erlang:system_info(otp_release) of
- "18" -> false;
- "19" -> false;
- _ -> true
- end.
+extra_chunks_opts([], Opts) -> Opts;
+extra_chunks_opts(Chunks, Opts) -> [{extra_chunks, Chunks} | Opts].
docs_chunk(Set, Module, Line, Def, Defmacro, Types, Callbacks) ->
case elixir_compiler:get_opt(docs) of
diff --git a/lib/elixir/src/elixir_erl_for.erl b/lib/elixir/src/elixir_erl_for.erl
index b8a6dc161..40aec2e62 100644
--- a/lib/elixir/src/elixir_erl_for.erl
+++ b/lib/elixir/src/elixir_erl_for.erl
@@ -182,11 +182,10 @@ build_into(Ann, Clauses, Expr, Into, Uniq, S) ->
{{block, Ann, [MatchExpr, TryExpr]}, SD}.
+%% TODO: Remove this check once we support Erlang/OTP 21+ exclusively.
stacktrace_clause(Ann, Fun, Acc, Kind, Reason, Stack) ->
- Release = erlang:system_info(otp_release),
-
- if
- Release == "19"; Release == "20" ->
+ case erlang:system_info(otp_release) of
+ "20" ->
{clause, Ann,
[{tuple, Ann, [Kind, Reason, {var, Ann, '_'}]}],
[],
@@ -194,7 +193,7 @@ stacktrace_clause(Ann, Fun, Acc, Kind, Reason, Stack) ->
{call, Ann, Fun, [Acc, {atom, Ann, halt}]},
elixir_erl:remote(Ann, erlang, raise, [Kind, Reason, Stack])]};
- true ->
+ _ ->
{clause, Ann,
[{tuple, Ann, [Kind, Reason, Stack]}],
[],
diff --git a/lib/elixir/src/elixir_erl_try.erl b/lib/elixir/src/elixir_erl_try.erl
index 601571b22..b101fc2f6 100644
--- a/lib/elixir/src/elixir_erl_try.erl
+++ b/lib/elixir/src/elixir_erl_try.erl
@@ -151,7 +151,6 @@ maybe_add_stacktrace(Line, Kind, Expr, Guards, Body, _) ->
%% TODO: Remove this check once we support Erlang/OTP 21+ exclusively.
supports_stacktrace() ->
case erlang:system_info(otp_release) of
- "19" -> false;
"20" -> false;
_ -> true
end.
diff --git a/lib/elixir/test/elixir/code_formatter/literals_test.exs b/lib/elixir/test/elixir/code_formatter/literals_test.exs
index f48da2d16..f9c704ec4 100644
--- a/lib/elixir/test/elixir/code_formatter/literals_test.exs
+++ b/lib/elixir/test/elixir/code_formatter/literals_test.exs
@@ -94,11 +94,8 @@ defmodule Code.Formatter.LiteralsTest do
assert_format ~S[:"double \" quote"], ~S[:"double \" quote"]
end
- # TODO: Remove this check once we depend only on 20
- if :erlang.system_info(:otp_release) >= '20' do
- test "with unicode" do
- assert_same ~S[:ólá]
- end
+ test "with unicode" do
+ assert_same ~S[:ólá]
end
test "does not reformat aliases" do
diff --git a/lib/elixir/test/elixir/exception_test.exs b/lib/elixir/test/elixir/exception_test.exs
index 153e1109d..c6fe89258 100644
--- a/lib/elixir/test/elixir/exception_test.exs
+++ b/lib/elixir/test/elixir/exception_test.exs
@@ -179,20 +179,14 @@ defmodule ExceptionTest do
assert Exception.format_mfa(Foo, :..., 1) == "Foo.\"...\"/1"
end
- # TODO: Remove this check once we depend only on 20
- # TODO: Remove String.to_atom/1 when we support 20+
- if :erlang.system_info(:otp_release) >= '20' do
- test "format_mfa/3 with unicode" do
- assert Exception.format_mfa(Foo, String.to_atom("olá"), [1, 2]) == "Foo.olá(1, 2)"
- assert Exception.format_mfa(Foo, String.to_atom("Olá"), [1, 2]) == "Foo.\"Olá\"(1, 2)"
- assert Exception.format_mfa(Foo, String.to_atom("Ólá"), [1, 2]) == "Foo.\"Ólá\"(1, 2)"
-
- hello_world = String.to_atom("こんにちは世界")
- assert Exception.format_mfa(Foo, hello_world, [1, 2]) == "Foo.こんにちは世界(1, 2)"
-
- nfd = :unicode.characters_to_nfd_binary("olá")
- assert Exception.format_mfa(Foo, String.to_atom(nfd), [1, 2]) == "Foo.\"#{nfd}\"(1, 2)"
- end
+ test "format_mfa/3 with unicode" do
+ assert Exception.format_mfa(Foo, :olá, [1, 2]) == "Foo.olá(1, 2)"
+ assert Exception.format_mfa(Foo, :Olá, [1, 2]) == "Foo.\"Olá\"(1, 2)"
+ assert Exception.format_mfa(Foo, :Ólá, [1, 2]) == "Foo.\"Ólá\"(1, 2)"
+ assert Exception.format_mfa(Foo, :こんにちは世界, [1, 2]) == "Foo.こんにちは世界(1, 2)"
+
+ nfd = :unicode.characters_to_nfd_binary("olá")
+ assert Exception.format_mfa(Foo, String.to_atom(nfd), [1, 2]) == "Foo.\"#{nfd}\"(1, 2)"
end
test "format_fa/2" do
@@ -599,83 +593,80 @@ defmodule ExceptionTest do
end
end
- # TODO: Remove this check once we depend only on 20
- if :erlang.system_info(:otp_release) >= '20' do
- test "annotates function clause errors" do
- args = [%{}, :key, nil]
+ test "annotates function clause errors" do
+ args = [%{}, :key, nil]
- {exception, stack} =
- Exception.blame(:error, :function_clause, [{Keyword, :pop, args, [line: 13]}])
+ {exception, stack} =
+ Exception.blame(:error, :function_clause, [{Keyword, :pop, args, [line: 13]}])
- assert %FunctionClauseError{kind: :def, args: ^args, clauses: [_]} = exception
- assert stack == [{Keyword, :pop, 3, [line: 13]}]
- end
+ assert %FunctionClauseError{kind: :def, args: ^args, clauses: [_]} = exception
+ assert stack == [{Keyword, :pop, 3, [line: 13]}]
+ end
- test "annotates args and clauses from mfa" do
- import PathHelpers
+ test "annotates args and clauses from mfa" do
+ import PathHelpers
- write_beam(
- defmodule Blaming do
- def with_elem(x, y) when elem(x, 1) == 0 and elem(x, y) == 1 do
- {x, y}
- end
+ write_beam(
+ defmodule Blaming do
+ def with_elem(x, y) when elem(x, 1) == 0 and elem(x, y) == 1 do
+ {x, y}
+ end
- def fetch(%module{} = container, key), do: {module, container, key}
- def fetch(map, key) when is_map(map), do: {map, key}
- def fetch(list, key) when is_list(list) and is_atom(key), do: {list, key}
- def fetch(nil, _key), do: nil
+ def fetch(%module{} = container, key), do: {module, container, key}
+ def fetch(map, key) when is_map(map), do: {map, key}
+ def fetch(list, key) when is_list(list) and is_atom(key), do: {list, key}
+ def fetch(nil, _key), do: nil
- require Integer
- def even_and_odd(foo, bar) when Integer.is_even(foo) and Integer.is_odd(bar), do: :ok
- end
- )
+ require Integer
+ def even_and_odd(foo, bar) when Integer.is_even(foo) and Integer.is_odd(bar), do: :ok
+ end
+ )
- :code.delete(Blaming)
- :code.purge(Blaming)
+ :code.delete(Blaming)
+ :code.purge(Blaming)
- {:ok, :def, clauses} = Exception.blame_mfa(Blaming, :with_elem, [1, 2])
+ {:ok, :def, clauses} = Exception.blame_mfa(Blaming, :with_elem, [1, 2])
- assert annotated_clauses_to_string(clauses) == [
- "{[+x+, +y+], [-elem(x, 1) == 0- and -elem(x, y) == 1-]}"
- ]
+ assert annotated_clauses_to_string(clauses) == [
+ "{[+x+, +y+], [-elem(x, 1) == 0- and -elem(x, y) == 1-]}"
+ ]
- {:ok, :def, clauses} = Exception.blame_mfa(Blaming, :fetch, [self(), "oops"])
+ {:ok, :def, clauses} = Exception.blame_mfa(Blaming, :fetch, [self(), "oops"])
- assert annotated_clauses_to_string(clauses) == [
- "{[-%module{} = container-, +key+], []}",
- "{[+map+, +key+], [-is_map(map)-]}",
- "{[+list+, +key+], [-is_list(list)- and -is_atom(key)-]}",
- "{[-nil-, +_key+], []}"
- ]
+ assert annotated_clauses_to_string(clauses) == [
+ "{[-%module{} = container-, +key+], []}",
+ "{[+map+, +key+], [-is_map(map)-]}",
+ "{[+list+, +key+], [-is_list(list)- and -is_atom(key)-]}",
+ "{[-nil-, +_key+], []}"
+ ]
- {:ok, :def, clauses} = Exception.blame_mfa(Blaming, :even_and_odd, [1, 1])
+ {:ok, :def, clauses} = Exception.blame_mfa(Blaming, :even_and_odd, [1, 1])
- assert annotated_clauses_to_string(clauses) == [
- "{[+foo+, +bar+], [+is_integer(foo)+ and -Bitwise.band(foo, 1) == 0- and (+is_integer(bar)+ and +Bitwise.band(bar, 1) == 1+)]}"
- ]
+ assert annotated_clauses_to_string(clauses) == [
+ "{[+foo+, +bar+], [+is_integer(foo)+ and -Bitwise.band(foo, 1) == 0- and (+is_integer(bar)+ and +Bitwise.band(bar, 1) == 1+)]}"
+ ]
- {:ok, :defmacro, clauses} = Exception.blame_mfa(Kernel, :!, [true])
+ {:ok, :defmacro, clauses} = Exception.blame_mfa(Kernel, :!, [true])
- assert annotated_clauses_to_string(clauses) == [
- "{[-{:!, _, [value]}-], []}",
- "{[+value+], []}"
- ]
- end
+ assert annotated_clauses_to_string(clauses) == [
+ "{[-{:!, _, [value]}-], []}",
+ "{[+value+], []}"
+ ]
+ end
- defp annotated_clauses_to_string(clauses) do
- Enum.map(clauses, fn args_and_clauses ->
- Macro.to_string(args_and_clauses, fn
- %{match?: true, node: node}, _string ->
- "+" <> Macro.to_string(node) <> "+"
+ defp annotated_clauses_to_string(clauses) do
+ Enum.map(clauses, fn args_and_clauses ->
+ Macro.to_string(args_and_clauses, fn
+ %{match?: true, node: node}, _string ->
+ "+" <> Macro.to_string(node) <> "+"
- %{match?: false, node: node}, _string ->
- "-" <> Macro.to_string(node) <> "-"
+ %{match?: false, node: node}, _string ->
+ "-" <> Macro.to_string(node) <> "-"
- _node, string ->
- string
- end)
+ _node, string ->
+ string
end)
- end
+ end)
end
end
@@ -738,28 +729,25 @@ defmodule ExceptionTest do
|> message == "no function clause matching in Foo.bar/1"
end
- # TODO: Remove this check once we depend only on 20
- if :erlang.system_info(:otp_release) >= '20' do
- test "FunctionClauseError with blame" do
- {exception, _} =
- Exception.blame(:error, :function_clause, [{Access, :fetch, [:foo, :bar], [line: 13]}])
+ test "FunctionClauseError with blame" do
+ {exception, _} =
+ Exception.blame(:error, :function_clause, [{Access, :fetch, [:foo, :bar], [line: 13]}])
- assert message(exception) =~ """
- no function clause matching in Access.fetch/2
+ assert message(exception) =~ """
+ no function clause matching in Access.fetch/2
- The following arguments were given to Access.fetch/2:
+ The following arguments were given to Access.fetch/2:
- # 1
- :foo
+ # 1
+ :foo
- # 2
- :bar
+ # 2
+ :bar
- Attempted function clauses (showing 5 out of 5):
+ Attempted function clauses (showing 5 out of 5):
- def fetch(-%module{} = container-, key)
- """
- end
+ def fetch(-%module{} = container-, key)
+ """
end
test "ErlangError" do
diff --git a/lib/elixir/test/elixir/inspect_test.exs b/lib/elixir/test/elixir/inspect_test.exs
index b4123fc15..f7a4b8e68 100644
--- a/lib/elixir/test/elixir/inspect_test.exs
+++ b/lib/elixir/test/elixir/inspect_test.exs
@@ -86,20 +86,14 @@ defmodule Inspect.AtomTest do
assert inspect(:hello, opts) == ":hello"
end
- # TODO: Remove this check once we depend only on 20
- # TODO: Remove String.to_atom/1 calls when we support 20+
- if :erlang.system_info(:otp_release) >= '20' do
- test "unicode" do
- assert inspect(String.to_atom("olá")) == ":olá"
- assert inspect(String.to_atom("Olá")) == ":Olá"
- assert inspect(String.to_atom("Ólá")) == ":Ólá"
-
- hello_world = String.to_atom("こんにちは世界")
- assert inspect(hello_world) == ":こんにちは世界"
-
- nfd = :unicode.characters_to_nfd_binary("olá")
- assert inspect(String.to_atom(nfd)) == ":\"#{nfd}\""
- end
+ test "unicode" do
+ assert inspect(:olá) == ":olá"
+ assert inspect(:Olá) == ":Olá"
+ assert inspect(:Ólá) == ":Ólá"
+ assert inspect(:こんにちは世界) == ":こんにちは世界"
+
+ nfd = :unicode.characters_to_nfd_binary("olá")
+ assert inspect(String.to_atom(nfd)) == ":\"#{nfd}\""
end
end
diff --git a/lib/elixir/test/elixir/kernel/binary_test.exs b/lib/elixir/test/elixir/kernel/binary_test.exs
index b8dbf14be..8dd1bf2ab 100644
--- a/lib/elixir/test/elixir/kernel/binary_test.exs
+++ b/lib/elixir/test/elixir/kernel/binary_test.exs
@@ -165,9 +165,8 @@ defmodule Kernel.BinaryTest do
end
test "literal" do
- # TODO: Remove String.to_atom/1 when we support 20+
assert <<106, 111, 115, 195, 169>> == <<"josé">>
- assert <<106, 111, 115, 195, 169>> == <<"#{String.to_atom("josé")}">>
+ assert <<106, 111, 115, 195, 169>> == <<"#{:josé}">>
assert <<106, 111, 115, 195, 169>> == <<"josé"::binary>>
assert <<106, 111, 115, 195, 169>> == <<"josé"::bits>>
assert <<106, 111, 115, 195, 169>> == <<"josé"::bitstring>>
diff --git a/lib/elixir/test/elixir/kernel/cli_test.exs b/lib/elixir/test/elixir/kernel/cli_test.exs
index 011a7f9ef..39f7664ca 100644
--- a/lib/elixir/test/elixir/kernel/cli_test.exs
+++ b/lib/elixir/test/elixir/kernel/cli_test.exs
@@ -75,16 +75,13 @@ defmodule Kernel.CLI.ErrorTest do
'false\n'
end
- # TODO: Remove this check once we depend only on 20
- if :erlang.system_info(:otp_release) >= '20' do
- test "blames exceptions" do
- error = to_string(elixir('-e "Access.fetch :foo, :bar"'))
- assert error =~ "** (FunctionClauseError) no function clause matching in Access.fetch/2"
- assert error =~ "The following arguments were given to Access.fetch/2"
- assert error =~ ":foo"
- assert error =~ "def fetch(-%module{} = container-, +key+)"
- assert error =~ ~r"\(elixir\) lib/access\.ex:\d+: Access\.fetch/2"
- end
+ test "blames exceptions" do
+ error = to_string(elixir('-e "Access.fetch :foo, :bar"'))
+ assert error =~ "** (FunctionClauseError) no function clause matching in Access.fetch/2"
+ assert error =~ "The following arguments were given to Access.fetch/2"
+ assert error =~ ":foo"
+ assert error =~ "def fetch(-%module{} = container-, +key+)"
+ assert error =~ ~r"\(elixir\) lib/access\.ex:\d+: Access\.fetch/2"
end
end
diff --git a/lib/elixir/test/elixir/kernel/dialyzer_test.exs b/lib/elixir/test/elixir/kernel/dialyzer_test.exs
index af1428e76..022dd99cc 100644
--- a/lib/elixir/test/elixir/kernel/dialyzer_test.exs
+++ b/lib/elixir/test/elixir/kernel/dialyzer_test.exs
@@ -130,11 +130,9 @@ defmodule Kernel.DialyzerTest do
assert_dialyze_no_warnings!(context)
end
- if :erlang.system_info(:otp_release) >= '20' do
- test "no warnings on with/else", context do
- copy_beam!(context, Dialyzer.With)
- assert_dialyze_no_warnings!(context)
- end
+ test "no warnings on with/else", context do
+ copy_beam!(context, Dialyzer.With)
+ assert_dialyze_no_warnings!(context)
end
test "no warnings on defmacrop", context do
diff --git a/lib/elixir/test/elixir/kernel/errors_test.exs b/lib/elixir/test/elixir/kernel/errors_test.exs
index b21cc4abb..b57a73f29 100644
--- a/lib/elixir/test/elixir/kernel/errors_test.exs
+++ b/lib/elixir/test/elixir/kernel/errors_test.exs
@@ -100,28 +100,25 @@ defmodule Kernel.ErrorsTest do
message = "nofile:1: invalid character \"?\" (codepoint U+003F) in alias: Foo?"
assert_eval_raise SyntaxError, message, 'Foo?'
- # TODO: Remove this check once we depend on OTP 20+
- if :erlang.system_info(:otp_release) >= '20' do
- message =
- "nofile:1: invalid character \"ó\" (codepoint U+00F3) in alias (only ascii characters are allowed): Foó"
+ message =
+ "nofile:1: invalid character \"ó\" (codepoint U+00F3) in alias (only ascii characters are allowed): Foó"
- assert_eval_raise SyntaxError, message, 'Foó'
+ assert_eval_raise SyntaxError, message, 'Foó'
- message = ~r"""
- Elixir expects unquoted Unicode atoms and variables to be in NFC form.
+ message = ~r"""
+ Elixir expects unquoted Unicode atoms and variables to be in NFC form.
- Got:
+ Got:
- "foó" \(codepoints 0066 006F 006F 0301\)
+ "foó" \(codepoints 0066 006F 006F 0301\)
- Expected:
+ Expected:
- "foó" \(codepoints 0066 006F 00F3\)
+ "foó" \(codepoints 0066 006F 00F3\)
- """
+ """
- assert_eval_raise SyntaxError, message, :unicode.characters_to_nfd_list("foó")
- end
+ assert_eval_raise SyntaxError, message, :unicode.characters_to_nfd_list("foó")
end
test "kw missing space" do
diff --git a/lib/elixir/test/elixir/kernel/string_tokenizer_test.exs b/lib/elixir/test/elixir/kernel/string_tokenizer_test.exs
index 2b543071a..9a9b2923e 100644
--- a/lib/elixir/test/elixir/kernel/string_tokenizer_test.exs
+++ b/lib/elixir/test/elixir/kernel/string_tokenizer_test.exs
@@ -1,76 +1,72 @@
Code.require_file("../test_helper.exs", __DIR__)
-# TODO: Remove this check once we depend only on 20
-# TODO: Remove String.to_atom/1 calls when we support 20+
-if :erlang.system_info(:otp_release) >= '20' do
- defmodule Kernel.StringTokenizerTest do
- use ExUnit.Case, async: true
+defmodule Kernel.StringTokenizerTest do
+ use ExUnit.Case, async: true
- defp var({var, _, nil}), do: var
- defp aliases({:__aliases__, _, [alias]}), do: alias
+ defp var({var, _, nil}), do: var
+ defp aliases({:__aliases__, _, [alias]}), do: alias
- test "tokenizes vars" do
- assert Code.string_to_quoted!("_12") |> var() == String.to_atom("_12")
- assert Code.string_to_quoted!("ola") |> var() == String.to_atom("ola")
- assert Code.string_to_quoted!("ólá") |> var() == String.to_atom("ólá")
- assert Code.string_to_quoted!("óLÁ") |> var() == String.to_atom("óLÁ")
- assert Code.string_to_quoted!("ólá?") |> var() == String.to_atom("ólá?")
- assert Code.string_to_quoted!("ólá!") |> var() == String.to_atom("ólá!")
- assert Code.string_to_quoted!("こんにちは世界") |> var() == String.to_atom("こんにちは世界")
- assert {:error, _} = Code.string_to_quoted("v@r")
- assert {:error, _} = Code.string_to_quoted("1var")
- end
+ test "tokenizes vars" do
+ assert Code.string_to_quoted!("_12") |> var() == :_12
+ assert Code.string_to_quoted!("ola") |> var() == :ola
+ assert Code.string_to_quoted!("ólá") |> var() == :ólá
+ assert Code.string_to_quoted!("óLÁ") |> var() == :óLÁ
+ assert Code.string_to_quoted!("ólá?") |> var() == :ólá?
+ assert Code.string_to_quoted!("ólá!") |> var() == :ólá!
+ assert Code.string_to_quoted!("こんにちは世界") |> var() == :こんにちは世界
+ assert {:error, _} = Code.string_to_quoted("v@r")
+ assert {:error, _} = Code.string_to_quoted("1var")
+ end
- test "tokenizes atoms" do
- assert Code.string_to_quoted!(":_12") == String.to_atom("_12")
- assert Code.string_to_quoted!(":ola") == String.to_atom("ola")
- assert Code.string_to_quoted!(":ólá") == String.to_atom("ólá")
- assert Code.string_to_quoted!(":ólá?") == String.to_atom("ólá?")
- assert Code.string_to_quoted!(":ólá!") == String.to_atom("ólá!")
- assert Code.string_to_quoted!(":ól@") == String.to_atom("ól@")
- assert Code.string_to_quoted!(":ól@!") == String.to_atom("ól@!")
- assert Code.string_to_quoted!(":ó@@!") == String.to_atom("ó@@!")
- assert Code.string_to_quoted!(":Ola") == String.to_atom("Ola")
- assert Code.string_to_quoted!(":Ólá") == String.to_atom("Ólá")
- assert Code.string_to_quoted!(":ÓLÁ") == String.to_atom("ÓLÁ")
- assert Code.string_to_quoted!(":ÓLÁ?") == String.to_atom("ÓLÁ?")
- assert Code.string_to_quoted!(":ÓLÁ!") == String.to_atom("ÓLÁ!")
- assert Code.string_to_quoted!(":ÓL@!") == String.to_atom("ÓL@!")
- assert Code.string_to_quoted!(":Ó@@!") == String.to_atom("Ó@@!")
- assert Code.string_to_quoted!(":こんにちは世界") == String.to_atom("こんにちは世界")
- assert {:error, _} = Code.string_to_quoted(":123")
- assert {:error, _} = Code.string_to_quoted(":@123")
- end
+ test "tokenizes atoms" do
+ assert Code.string_to_quoted!(":_12") == :_12
+ assert Code.string_to_quoted!(":ola") == :ola
+ assert Code.string_to_quoted!(":ólá") == :ólá
+ assert Code.string_to_quoted!(":ólá?") == :ólá?
+ assert Code.string_to_quoted!(":ólá!") == :ólá!
+ assert Code.string_to_quoted!(":ól@") == :ól@
+ assert Code.string_to_quoted!(":ól@!") == :ól@!
+ assert Code.string_to_quoted!(":ó@@!") == :ó@@!
+ assert Code.string_to_quoted!(":Ola") == :Ola
+ assert Code.string_to_quoted!(":Ólá") == :Ólá
+ assert Code.string_to_quoted!(":ÓLÁ") == :ÓLÁ
+ assert Code.string_to_quoted!(":ÓLÁ?") == :ÓLÁ?
+ assert Code.string_to_quoted!(":ÓLÁ!") == :ÓLÁ!
+ assert Code.string_to_quoted!(":ÓL@!") == :ÓL@!
+ assert Code.string_to_quoted!(":Ó@@!") == :Ó@@!
+ assert Code.string_to_quoted!(":こんにちは世界") == :こんにちは世界
+ assert {:error, _} = Code.string_to_quoted(":123")
+ assert {:error, _} = Code.string_to_quoted(":@123")
+ end
- test "tokenizes keywords" do
- assert Code.string_to_quoted!("[_12: 0]") == [{String.to_atom("_12"), 0}]
- assert Code.string_to_quoted!("[ola: 0]") == [{String.to_atom("ola"), 0}]
- assert Code.string_to_quoted!("[ólá: 0]") == [{String.to_atom("ólá"), 0}]
- assert Code.string_to_quoted!("[ólá?: 0]") == [{String.to_atom("ólá?"), 0}]
- assert Code.string_to_quoted!("[ólá!: 0]") == [{String.to_atom("ólá!"), 0}]
- assert Code.string_to_quoted!("[ól@: 0]") == [{String.to_atom("ól@"), 0}]
- assert Code.string_to_quoted!("[ól@!: 0]") == [{String.to_atom("ól@!"), 0}]
- assert Code.string_to_quoted!("[ó@@!: 0]") == [{String.to_atom("ó@@!"), 0}]
- assert Code.string_to_quoted!("[Ola: 0]") == [{String.to_atom("Ola"), 0}]
- assert Code.string_to_quoted!("[Ólá: 0]") == [{String.to_atom("Ólá"), 0}]
- assert Code.string_to_quoted!("[ÓLÁ: 0]") == [{String.to_atom("ÓLÁ"), 0}]
- assert Code.string_to_quoted!("[ÓLÁ?: 0]") == [{String.to_atom("ÓLÁ?"), 0}]
- assert Code.string_to_quoted!("[ÓLÁ!: 0]") == [{String.to_atom("ÓLÁ!"), 0}]
- assert Code.string_to_quoted!("[ÓL@!: 0]") == [{String.to_atom("ÓL@!"), 0}]
- assert Code.string_to_quoted!("[Ó@@!: 0]") == [{String.to_atom("Ó@@!"), 0}]
- assert Code.string_to_quoted!("[こんにちは世界: 0]") == [{String.to_atom("こんにちは世界"), 0}]
- assert {:error, _} = Code.string_to_quoted("[123: 0]")
- assert {:error, _} = Code.string_to_quoted("[@123: 0]")
- end
+ test "tokenizes keywords" do
+ assert Code.string_to_quoted!("[_12: 0]") == [_12: 0]
+ assert Code.string_to_quoted!("[ola: 0]") == [ola: 0]
+ assert Code.string_to_quoted!("[ólá: 0]") == [ólá: 0]
+ assert Code.string_to_quoted!("[ólá?: 0]") == [ólá?: 0]
+ assert Code.string_to_quoted!("[ólá!: 0]") == [ólá!: 0]
+ assert Code.string_to_quoted!("[ól@: 0]") == [ól@: 0]
+ assert Code.string_to_quoted!("[ól@!: 0]") == [ól@!: 0]
+ assert Code.string_to_quoted!("[ó@@!: 0]") == [ó@@!: 0]
+ assert Code.string_to_quoted!("[Ola: 0]") == [Ola: 0]
+ assert Code.string_to_quoted!("[Ólá: 0]") == [Ólá: 0]
+ assert Code.string_to_quoted!("[ÓLÁ: 0]") == [ÓLÁ: 0]
+ assert Code.string_to_quoted!("[ÓLÁ?: 0]") == [ÓLÁ?: 0]
+ assert Code.string_to_quoted!("[ÓLÁ!: 0]") == [ÓLÁ!: 0]
+ assert Code.string_to_quoted!("[ÓL@!: 0]") == [ÓL@!: 0]
+ assert Code.string_to_quoted!("[Ó@@!: 0]") == [Ó@@!: 0]
+ assert Code.string_to_quoted!("[こんにちは世界: 0]") == [こんにちは世界: 0]
+ assert {:error, _} = Code.string_to_quoted("[123: 0]")
+ assert {:error, _} = Code.string_to_quoted("[@123: 0]")
+ end
- test "tokenizes aliases" do
- assert Code.string_to_quoted!("Ola") |> aliases() == String.to_atom("Ola")
- assert Code.string_to_quoted!("M_123") |> aliases() == String.to_atom("M_123")
- assert {:error, _} = Code.string_to_quoted("Óla")
- assert {:error, _} = Code.string_to_quoted("Olá")
- assert {:error, _} = Code.string_to_quoted("Ol@")
- assert {:error, _} = Code.string_to_quoted("Ola?")
- assert {:error, _} = Code.string_to_quoted("Ola!")
- end
+ test "tokenizes aliases" do
+ assert Code.string_to_quoted!("Ola") |> aliases() == String.to_atom("Ola")
+ assert Code.string_to_quoted!("M_123") |> aliases() == String.to_atom("M_123")
+ assert {:error, _} = Code.string_to_quoted("Óla")
+ assert {:error, _} = Code.string_to_quoted("Olá")
+ assert {:error, _} = Code.string_to_quoted("Ol@")
+ assert {:error, _} = Code.string_to_quoted("Ola?")
+ assert {:error, _} = Code.string_to_quoted("Ola!")
end
end
diff --git a/lib/elixir/test/elixir/kernel/warning_test.exs b/lib/elixir/test/elixir/kernel/warning_test.exs
index 8546f152c..e39ed8819 100644
--- a/lib/elixir/test/elixir/kernel/warning_test.exs
+++ b/lib/elixir/test/elixir/kernel/warning_test.exs
@@ -535,20 +535,17 @@ defmodule Kernel.WarningTest do
purge(Sample)
end
- # TODO: Remove this check once we depend only on 20
- if :erlang.system_info(:otp_release) >= '20' do
- test "duplicate map keys" do
- output =
- capture_err(fn ->
- defmodule DuplicateMapKeys do
- assert %{a: :b, a: :c} == %{a: :c}
- assert %{1 => 2, 1 => 3} == %{1 => 3}
- end
- end)
+ test "duplicate map keys" do
+ output =
+ capture_err(fn ->
+ defmodule DuplicateMapKeys do
+ assert %{a: :b, a: :c} == %{a: :c}
+ assert %{1 => 2, 1 => 3} == %{1 => 3}
+ end
+ end)
- assert output =~ "key :a will be overridden in map"
- assert output =~ "key 1 will be overridden in map"
- end
+ assert output =~ "key :a will be overridden in map"
+ assert output =~ "key 1 will be overridden in map"
end
test "unused guard" do
diff --git a/lib/elixir/test/elixir/module_test.exs b/lib/elixir/test/elixir/module_test.exs
index 5da0d0cc5..e73f079de 100644
--- a/lib/elixir/test/elixir/module_test.exs
+++ b/lib/elixir/test/elixir/module_test.exs
@@ -310,29 +310,25 @@ defmodule ModuleTest do
assert ModuleCreateGenerated.world()
end
- # TODO: Remove this check once we depend only on 20
- if :erlang.system_info(:otp_release) >= '20' do
- test "uses the new debug_info chunk" do
- {:module, ModuleCreateDebugInfo, binary, _} =
- Module.create(ModuleCreateDebugInfo, :ok, __ENV__)
+ test "uses the debug_info chunk" do
+ {:module, ModuleCreateDebugInfo, binary, _} =
+ Module.create(ModuleCreateDebugInfo, :ok, __ENV__)
- {:ok, {_, [debug_info: {:debug_info_v1, backend, data}]}} =
- :beam_lib.chunks(binary, [:debug_info])
+ {:ok, {_, [debug_info: {:debug_info_v1, backend, data}]}} =
+ :beam_lib.chunks(binary, [:debug_info])
- {:ok, map} = backend.debug_info(:elixir_v1, ModuleCreateDebugInfo, data, [])
- assert map.module == ModuleCreateDebugInfo
- end
+ {:ok, map} = backend.debug_info(:elixir_v1, ModuleCreateDebugInfo, data, [])
+ assert map.module == ModuleCreateDebugInfo
+ end
- test "uses the new debug_info chunk even if debug_info is set to false" do
- {:module, ModuleCreateNoDebugInfo, binary, _} =
- Module.create(ModuleCreateNoDebugInfo, quote(do: @compile({:debug_info, false})), __ENV__)
+ test "uses the debug_info chunk even if debug_info is set to false" do
+ {:module, ModuleCreateNoDebugInfo, binary, _} =
+ Module.create(ModuleCreateNoDebugInfo, quote(do: @compile({:debug_info, false})), __ENV__)
- {:ok, {_, [debug_info: {:debug_info_v1, backend, data}]}} =
- :beam_lib.chunks(binary, [:debug_info])
+ {:ok, {_, [debug_info: {:debug_info_v1, backend, data}]}} =
+ :beam_lib.chunks(binary, [:debug_info])
- assert backend.debug_info(:elixir_v1, ModuleCreateNoDebugInfo, data, []) ==
- {:error, :missing}
- end
+ assert backend.debug_info(:elixir_v1, ModuleCreateNoDebugInfo, data, []) == {:error, :missing}
end
test "no function in module body" do
diff --git a/lib/ex_unit/test/ex_unit/formatter_test.exs b/lib/ex_unit/test/ex_unit/formatter_test.exs
index b243f5e5b..4efe7bc11 100644
--- a/lib/ex_unit/test/ex_unit/formatter_test.exs
+++ b/lib/ex_unit/test/ex_unit/formatter_test.exs
@@ -147,42 +147,39 @@ defmodule ExUnit.FormatterTest do
"""
end
- # TODO: Remove this check once we depend only on 20
- if :erlang.system_info(:otp_release) >= '20' do
- defp trim_multiline_whitespace(string) do
- String.replace(string, ~r"\n\s+\n", "\n\n")
- end
+ defp trim_multiline_whitespace(string) do
+ String.replace(string, ~r"\n\s+\n", "\n\n")
+ end
- test "blames function clause error" do
- {error, stack} =
- try do
- Access.fetch(:foo, :bar)
- rescue
- exception -> {exception, __STACKTRACE__}
- end
+ test "blames function clause error" do
+ {error, stack} =
+ try do
+ Access.fetch(:foo, :bar)
+ rescue
+ exception -> {exception, __STACKTRACE__}
+ end
- failure = format_test_failure(test(), [{:error, error, [hd(stack)]}], 1, 80, &formatter/2)
+ failure = format_test_failure(test(), [{:error, error, [hd(stack)]}], 1, 80, &formatter/2)
- assert trim_multiline_whitespace(failure) =~ """
- 1) world (Hello)
- test/ex_unit/formatter_test.exs:1
- ** (FunctionClauseError) no function clause matching in Access.fetch/2
+ assert trim_multiline_whitespace(failure) =~ """
+ 1) world (Hello)
+ test/ex_unit/formatter_test.exs:1
+ ** (FunctionClauseError) no function clause matching in Access.fetch/2
- The following arguments were given to Access.fetch/2:
+ The following arguments were given to Access.fetch/2:
- # 1
- :foo
+ # 1
+ :foo
- # 2
- :bar
+ # 2
+ :bar
- Attempted function clauses (showing 5 out of 5):
+ Attempted function clauses (showing 5 out of 5):
- def fetch(%module{} = container, key)
- """
+ def fetch(%module{} = container, key)
+ """
- assert failure =~ ~r"\(elixir\) lib/access\.ex:\d+: Access\.fetch/2"
- end
+ assert failure =~ ~r"\(elixir\) lib/access\.ex:\d+: Access\.fetch/2"
end
test "formats setup all errors" do
diff --git a/lib/iex/lib/iex.ex b/lib/iex/lib/iex.ex
index 84bcc20f0..59424757e 100644
--- a/lib/iex/lib/iex.ex
+++ b/lib/iex/lib/iex.ex
@@ -31,9 +31,8 @@ defmodule IEx do
## Shell history
- From Erlang/OTP 20, it is possible to get shell history by passing some
- flags that enable it in the VM. This can be done on a per-need basis
- when starting IEx:
+ It is possible to get shell history by passing some flags that enable it
+ in the VM. This can be done on a per-need basis when starting IEx:
iex --erl "-kernel shell_history enabled"
@@ -117,9 +116,8 @@ defmodule IEx do
Alternatively, you can use `IEx.break!/4` to setup a breakpoint
on a given module, function and arity you have no control of.
- While `IEx.break!/4` is more flexible, it requires Erlang/OTP 20+ and
- it does not contain information about imports and aliases from
- the source code.
+ While `IEx.break!/4` is more flexible, it does not contain
+ information about imports and aliases from the source code.
## The User Switch command
@@ -255,7 +253,7 @@ defmodule IEx do
results in:
$ iex
- Erlang 19 [...]
+ Erlang/OTP 20 [...]
hello world
Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
@@ -279,7 +277,7 @@ defmodule IEx do
Now run the shell:
$ iex
- Erlang 19 [...]
+ Erlang/OTP 20 [...]
Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> [1, 2, 3, 4, 5]
@@ -469,9 +467,8 @@ defmodule IEx do
Alternatively, you can use `IEx.break!/4` to setup a breakpoint
on a given module, function and arity you have no control of.
- While `IEx.break!/4` is more flexible, it requires Erlang/OTP 20+ and
- it does not contain information about imports and aliases from
- the source code.
+ While `IEx.break!/4` is more flexible, it does not contain
+ information about imports and aliases from the source code.
## Examples
@@ -663,8 +660,6 @@ defmodule IEx do
the process terminates, or invoke `respawn()`, which starts a new IEx
shell, freeing up the pried one.
- This functionality only works on Elixir code and requires Erlang/OTP 20+.
-
## Examples
The examples below will use `break!`, assuming that you are setting
diff --git a/lib/iex/lib/iex/helpers.ex b/lib/iex/lib/iex/helpers.ex
index 637496411..2df3c13ad 100644
--- a/lib/iex/lib/iex/helpers.ex
+++ b/lib/iex/lib/iex/helpers.ex
@@ -580,10 +580,7 @@ defmodule IEx.Helpers do
print_uptime()
print_entry("Run queue", :erlang.statistics(:run_queue))
- if :erlang.system_info(:otp_release) >= '20' do
- print_percentage("Atoms", :atom_count, :atom_limit)
- end
-
+ print_percentage("Atoms", :atom_count, :atom_limit)
print_percentage("ETS", :ets_count, :ets_limit)
print_percentage("Ports", :port_count, :port_limit)
print_percentage("Processes", :process_count, :process_limit)
diff --git a/lib/iex/lib/iex/pry.ex b/lib/iex/lib/iex/pry.ex
index 8bfb23097..e7317e19f 100644
--- a/lib/iex/lib/iex/pry.ex
+++ b/lib/iex/lib/iex/pry.ex
@@ -156,7 +156,6 @@ defmodule IEx.Pry do
:recompilation_failed
| :no_beam_file
| :unknown_function_arity
- | :otp_20_is_required
| :missing_debug_info
| :outdated_debug_info
| :non_elixir_module
@@ -188,9 +187,6 @@ defmodule IEx.Pry do
:non_elixir_module ->
"module #{inspect(module)} was not written in Elixir"
- :otp_20_is_required ->
- "you are running on an earlier version than Erlang/OTP 20"
-
:outdated_debug_info ->
"module #{inspect(module)} was not compiled with the latest debug_info"
@@ -383,10 +379,6 @@ defmodule IEx.Pry do
{:ok, {_, [debug_info: {:debug_info_v1, _, _}]}} ->
{:error, :non_elixir_module}
- {:error, :beam_lib, {:unknown_chunk, _, _}} ->
- # TODO: Remove this when we require OTP 20+
- {:error, :otp_20_is_required}
-
{:error, :beam_lib, {:missing_chunk, _, _}} ->
{:error, :missing_debug_info}
diff --git a/lib/iex/test/iex/helpers_test.exs b/lib/iex/test/iex/helpers_test.exs
index a8a1db0df..d15967485 100644
--- a/lib/iex/test/iex/helpers_test.exs
+++ b/lib/iex/test/iex/helpers_test.exs
@@ -27,115 +27,113 @@ defmodule IEx.HelpersTest do
end
end
- if :erlang.system_info(:otp_release) >= '20' do
- describe "breakpoints" do
- setup do
- on_exit(fn -> IEx.Pry.remove_breaks() end)
- end
+ describe "breakpoints" do
+ setup do
+ on_exit(fn -> IEx.Pry.remove_breaks() end)
+ end
- test "sets up a breakpoint with capture syntax" do
- assert break!(URI.decode_query() / 2) == 1
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
- end
+ test "sets up a breakpoint with capture syntax" do
+ assert break!(URI.decode_query() / 2) == 1
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
+ end
- test "sets up a breakpoint with call syntax" do
- assert break!(URI.decode_query(_, %{})) == 1
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
- end
+ test "sets up a breakpoint with call syntax" do
+ assert break!(URI.decode_query(_, %{})) == 1
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
+ end
- test "sets up a breakpoint with guards syntax" do
- assert break!(URI.decode_query(_, map) when is_map(map)) == 1
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
- end
+ test "sets up a breakpoint with guards syntax" do
+ assert break!(URI.decode_query(_, map) when is_map(map)) == 1
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
+ end
- test "sets up a breakpoint on the given module" do
- assert break!(URI, :decode_query, 2) == 1
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
- end
+ test "sets up a breakpoint on the given module" do
+ assert break!(URI, :decode_query, 2) == 1
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
+ end
- test "resets breaks on the given id" do
- assert break!(URI, :decode_query, 2) == 1
- assert reset_break(1) == :ok
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
- end
+ test "resets breaks on the given id" do
+ assert break!(URI, :decode_query, 2) == 1
+ assert reset_break(1) == :ok
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
+ end
- test "resets breaks on the given module" do
- assert break!(URI, :decode_query, 2) == 1
- assert reset_break(URI, :decode_query, 2) == :ok
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
- end
+ test "resets breaks on the given module" do
+ assert break!(URI, :decode_query, 2) == 1
+ assert reset_break(URI, :decode_query, 2) == :ok
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
+ end
- test "removes breaks in the given module" do
- assert break!(URI.decode_query() / 2) == 1
- assert remove_breaks(URI) == :ok
- assert IEx.Pry.breaks() == []
- end
+ test "removes breaks in the given module" do
+ assert break!(URI.decode_query() / 2) == 1
+ assert remove_breaks(URI) == :ok
+ assert IEx.Pry.breaks() == []
+ end
- test "removes breaks on all modules" do
- assert break!(URI.decode_query() / 2) == 1
- assert remove_breaks() == :ok
- assert IEx.Pry.breaks() == []
- end
+ test "removes breaks on all modules" do
+ assert break!(URI.decode_query() / 2) == 1
+ assert remove_breaks() == :ok
+ assert IEx.Pry.breaks() == []
+ end
- test "errors when setting up a breakpoint with invalid guard" do
- assert_raise CompileError, ~r"cannot invoke local is_whatever/1 inside guard", fn ->
- break!(URI.decode_query(_, map) when is_whatever(map))
- end
+ test "errors when setting up a breakpoint with invalid guard" do
+ assert_raise CompileError, ~r"cannot invoke local is_whatever/1 inside guard", fn ->
+ break!(URI.decode_query(_, map) when is_whatever(map))
end
+ end
- test "errors when setting up a break with no beam" do
- assert_raise RuntimeError,
- "could not set breakpoint, could not find .beam file for IEx.HelpersTest",
- fn -> break!(__MODULE__, :setup, 1) end
- end
+ test "errors when setting up a break with no beam" do
+ assert_raise RuntimeError,
+ "could not set breakpoint, could not find .beam file for IEx.HelpersTest",
+ fn -> break!(__MODULE__, :setup, 1) end
+ end
- test "errors when setting up a break for unknown function" do
- assert_raise RuntimeError,
- "could not set breakpoint, unknown function/macro URI.unknown/2",
- fn -> break!(URI, :unknown, 2) end
- end
+ test "errors when setting up a break for unknown function" do
+ assert_raise RuntimeError,
+ "could not set breakpoint, unknown function/macro URI.unknown/2",
+ fn -> break!(URI, :unknown, 2) end
+ end
- test "errors for non-Elixir modules" do
- assert_raise RuntimeError,
- "could not set breakpoint, module :elixir was not written in Elixir",
- fn -> break!(:elixir, :unknown, 2) end
- end
+ test "errors for non-Elixir modules" do
+ assert_raise RuntimeError,
+ "could not set breakpoint, module :elixir was not written in Elixir",
+ fn -> break!(:elixir, :unknown, 2) end
+ end
- test "prints table with breaks" do
- break!(URI, :decode_query, 2)
+ test "prints table with breaks" do
+ break!(URI, :decode_query, 2)
- assert capture_io(fn -> breaks() end) == """
+ assert capture_io(fn -> breaks() end) == """
- ID Module.function/arity Pending stops
- ---- ----------------------- ---------------
- 1 URI.decode_query/2 1
+ ID Module.function/arity Pending stops
+ ---- ----------------------- ---------------
+ 1 URI.decode_query/2 1
- """
+ """
- assert capture_io(fn -> URI.decode_query("foo=bar", %{}) end) != ""
+ assert capture_io(fn -> URI.decode_query("foo=bar", %{}) end) != ""
- assert capture_io(fn -> breaks() end) == """
+ assert capture_io(fn -> breaks() end) == """
- ID Module.function/arity Pending stops
- ---- ----------------------- ---------------
- 1 URI.decode_query/2 0
+ ID Module.function/arity Pending stops
+ ---- ----------------------- ---------------
+ 1 URI.decode_query/2 0
- """
+ """
- assert capture_io(fn -> URI.decode_query("foo=bar", %{}) end) == ""
+ assert capture_io(fn -> URI.decode_query("foo=bar", %{}) end) == ""
- assert capture_io(fn -> breaks() end) == """
+ assert capture_io(fn -> breaks() end) == """
- ID Module.function/arity Pending stops
- ---- ----------------------- ---------------
- 1 URI.decode_query/2 0
+ ID Module.function/arity Pending stops
+ ---- ----------------------- ---------------
+ 1 URI.decode_query/2 0
- """
- end
+ """
+ end
- test "does not print table when there are no breaks" do
- assert capture_io(fn -> breaks() end) == "No breakpoints set\n"
- end
+ test "does not print table when there are no breaks" do
+ assert capture_io(fn -> breaks() end) == "No breakpoints set\n"
end
end
diff --git a/lib/iex/test/iex/interaction_test.exs b/lib/iex/test/iex/interaction_test.exs
index 25e6190bc..591d1f53f 100644
--- a/lib/iex/test/iex/interaction_test.exs
+++ b/lib/iex/test/iex/interaction_test.exs
@@ -144,16 +144,13 @@ defmodule IEx.InteractionTest do
~r"\*\* \(exit\) exited in: :gen_server\.call\(#PID<\d+\.\d+\.\d+>, :hello\)\n\s{4}\*\* \(EXIT\) :bye"
end
- # TODO: Remove this check once we depend only on 20
- if :erlang.system_info(:otp_release) >= '20' do
- test "blames function clause error" do
- content = capture_iex("Access.fetch(:foo, :bar)")
- assert content =~ "** (FunctionClauseError) no function clause matching in Access.fetch/2"
- assert content =~ "The following arguments were given to Access.fetch/2"
- assert content =~ ":foo"
- assert content =~ "def fetch(-%module{} = container-, key)"
- assert content =~ ~r"\(elixir\) lib/access\.ex:\d+: Access\.fetch/2"
- end
+ test "blames function clause error" do
+ content = capture_iex("Access.fetch(:foo, :bar)")
+ assert content =~ "** (FunctionClauseError) no function clause matching in Access.fetch/2"
+ assert content =~ "The following arguments were given to Access.fetch/2"
+ assert content =~ ":foo"
+ assert content =~ "def fetch(-%module{} = container-, key)"
+ assert content =~ ~r"\(elixir\) lib/access\.ex:\d+: Access\.fetch/2"
end
## .iex file loading
diff --git a/lib/iex/test/iex/pry_test.exs b/lib/iex/test/iex/pry_test.exs
index 1532d42a2..b77179850 100644
--- a/lib/iex/test/iex/pry_test.exs
+++ b/lib/iex/test/iex/pry_test.exs
@@ -43,158 +43,156 @@ defmodule IEx.PryTest do
end
end
- if :erlang.system_info(:otp_release) >= '20' do
- describe "break" do
- test "sets up a breakpoint on the given module" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert instrumented?(URI)
- assert [_] = IEx.Pry.breaks()
- end
-
- test "sets up multiple breakpoints in the same module" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert instrumented?(URI)
- assert IEx.Pry.break(URI, :parse, 1, quote(do: _)) == {:ok, 2}
- assert instrumented?(URI)
- assert [_, _] = IEx.Pry.breaks()
- end
-
- test "reinstruments if module has been reloaded" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert instrumented?(URI)
- deinstrument!(URI)
- refute instrumented?(URI)
- assert IEx.Pry.break(URI, :parse, 1, quote(do: _)) == {:ok, 2}
- assert instrumented?(URI)
- assert [_, _] = IEx.Pry.breaks()
- end
-
- test "returns id when breakpoint is already set" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert [_] = IEx.Pry.breaks()
- end
-
- test "returns id even when breakpoint is already set on deinstrument" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- deinstrument!(URI)
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert [_] = IEx.Pry.breaks()
- end
-
- test "errors when setting up a break with no beam" do
- assert IEx.Pry.break(__MODULE__, :setup, 2, quote(do: _)) == {:error, :no_beam_file}
- end
-
- test "errors when setting up a break for unknown function" do
- assert IEx.Pry.break(URI, :unknown, 2, quote(do: _)) == {:error, :unknown_function_arity}
- end
-
- test "errors for non-Elixir modules" do
- assert IEx.Pry.break(:elixir, :unknown, 2, quote(do: _)) == {:error, :non_elixir_module}
- end
- end
-
- describe "breaks" do
- test "returns all breaks" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
-
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _), 10) == {:ok, 1}
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 10}]
-
- assert IEx.Pry.break(URI, :parse, 1, quote(do: _), 1) == {:ok, 2}
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 10}, {2, URI, {:parse, 1}, 1}]
- end
-
- test "sets negative break to 0" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- :ets.insert(IEx.Pry, {1, URI, {:decode_query, 2}, {[], true}, -1})
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
- end
-
- test "do not return break points for deinstrumented modules" do
- assert IEx.Pry.break(URI, :parse, 1, quote(do: _)) == {:ok, 1}
- assert IEx.Pry.breaks() == [{1, URI, {:parse, 1}, 1}]
- deinstrument!(URI)
- assert IEx.Pry.breaks() == []
- end
- end
-
- describe "reset_break" do
- test "resets break for given id" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert IEx.Pry.reset_break(1) == :ok
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
- end
-
- test "resets break for given mfa" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert IEx.Pry.reset_break(URI, :decode_query, 2) == :ok
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
- end
-
- test "returns not_found if module is deinstrumented" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- deinstrument!(URI)
- assert IEx.Pry.reset_break(URI, :decode_query, 2) == :not_found
- assert IEx.Pry.breaks() == []
- end
-
- test "returns not_found if mfa has no break" do
- assert IEx.Pry.reset_break(URI, :decode_query, 2) == :not_found
- end
-
- test "returns not_found if id is deinstrumented" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- deinstrument!(URI)
- assert IEx.Pry.reset_break(1) == :not_found
- assert IEx.Pry.breaks() == []
- end
-
- test "returns not_found if id has no break" do
- assert IEx.Pry.reset_break(1) == :not_found
- end
- end
-
- describe "remove_breaks" do
- test "removes all breaks" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert IEx.Pry.remove_breaks() == :ok
- assert IEx.Pry.breaks() == []
- end
-
- test "removes all breaks even if module is deinstrumented" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- deinstrument!(URI)
- assert IEx.Pry.remove_breaks() == :ok
- assert IEx.Pry.breaks() == []
- end
-
- test "remove breaks in a given module" do
- assert IEx.Pry.remove_breaks(Date.Range) == :ok
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- assert IEx.Pry.break(Date.Range, :__struct__, 1, quote(do: _)) == {:ok, 2}
- assert IEx.Pry.remove_breaks(Date.Range) == :ok
- assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
- end
-
- test "remove breaks in a given module even if deinstrumented" do
- assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
- deinstrument!(URI)
- assert IEx.Pry.breaks() == []
- end
- end
-
- defp instrumented?(module) do
- module.module_info(:attributes)[:iex_pry] == [true]
- end
-
- defp deinstrument!(module) do
- beam = :code.which(module)
- :code.purge(module)
- {:module, _} = :code.load_binary(module, beam, File.read!(beam))
- :ok
+ describe "break" do
+ test "sets up a breakpoint on the given module" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert instrumented?(URI)
+ assert [_] = IEx.Pry.breaks()
end
+
+ test "sets up multiple breakpoints in the same module" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert instrumented?(URI)
+ assert IEx.Pry.break(URI, :parse, 1, quote(do: _)) == {:ok, 2}
+ assert instrumented?(URI)
+ assert [_, _] = IEx.Pry.breaks()
+ end
+
+ test "reinstruments if module has been reloaded" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert instrumented?(URI)
+ deinstrument!(URI)
+ refute instrumented?(URI)
+ assert IEx.Pry.break(URI, :parse, 1, quote(do: _)) == {:ok, 2}
+ assert instrumented?(URI)
+ assert [_, _] = IEx.Pry.breaks()
+ end
+
+ test "returns id when breakpoint is already set" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert [_] = IEx.Pry.breaks()
+ end
+
+ test "returns id even when breakpoint is already set on deinstrument" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ deinstrument!(URI)
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert [_] = IEx.Pry.breaks()
+ end
+
+ test "errors when setting up a break with no beam" do
+ assert IEx.Pry.break(__MODULE__, :setup, 2, quote(do: _)) == {:error, :no_beam_file}
+ end
+
+ test "errors when setting up a break for unknown function" do
+ assert IEx.Pry.break(URI, :unknown, 2, quote(do: _)) == {:error, :unknown_function_arity}
+ end
+
+ test "errors for non-Elixir modules" do
+ assert IEx.Pry.break(:elixir, :unknown, 2, quote(do: _)) == {:error, :non_elixir_module}
+ end
+ end
+
+ describe "breaks" do
+ test "returns all breaks" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
+
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _), 10) == {:ok, 1}
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 10}]
+
+ assert IEx.Pry.break(URI, :parse, 1, quote(do: _), 1) == {:ok, 2}
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 10}, {2, URI, {:parse, 1}, 1}]
+ end
+
+ test "sets negative break to 0" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ :ets.insert(IEx.Pry, {1, URI, {:decode_query, 2}, {[], true}, -1})
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
+ end
+
+ test "do not return break points for deinstrumented modules" do
+ assert IEx.Pry.break(URI, :parse, 1, quote(do: _)) == {:ok, 1}
+ assert IEx.Pry.breaks() == [{1, URI, {:parse, 1}, 1}]
+ deinstrument!(URI)
+ assert IEx.Pry.breaks() == []
+ end
+ end
+
+ describe "reset_break" do
+ test "resets break for given id" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert IEx.Pry.reset_break(1) == :ok
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
+ end
+
+ test "resets break for given mfa" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert IEx.Pry.reset_break(URI, :decode_query, 2) == :ok
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 0}]
+ end
+
+ test "returns not_found if module is deinstrumented" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ deinstrument!(URI)
+ assert IEx.Pry.reset_break(URI, :decode_query, 2) == :not_found
+ assert IEx.Pry.breaks() == []
+ end
+
+ test "returns not_found if mfa has no break" do
+ assert IEx.Pry.reset_break(URI, :decode_query, 2) == :not_found
+ end
+
+ test "returns not_found if id is deinstrumented" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ deinstrument!(URI)
+ assert IEx.Pry.reset_break(1) == :not_found
+ assert IEx.Pry.breaks() == []
+ end
+
+ test "returns not_found if id has no break" do
+ assert IEx.Pry.reset_break(1) == :not_found
+ end
+ end
+
+ describe "remove_breaks" do
+ test "removes all breaks" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert IEx.Pry.remove_breaks() == :ok
+ assert IEx.Pry.breaks() == []
+ end
+
+ test "removes all breaks even if module is deinstrumented" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ deinstrument!(URI)
+ assert IEx.Pry.remove_breaks() == :ok
+ assert IEx.Pry.breaks() == []
+ end
+
+ test "remove breaks in a given module" do
+ assert IEx.Pry.remove_breaks(Date.Range) == :ok
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ assert IEx.Pry.break(Date.Range, :__struct__, 1, quote(do: _)) == {:ok, 2}
+ assert IEx.Pry.remove_breaks(Date.Range) == :ok
+ assert IEx.Pry.breaks() == [{1, URI, {:decode_query, 2}, 1}]
+ end
+
+ test "remove breaks in a given module even if deinstrumented" do
+ assert IEx.Pry.break(URI, :decode_query, 2, quote(do: _)) == {:ok, 1}
+ deinstrument!(URI)
+ assert IEx.Pry.breaks() == []
+ end
+ end
+
+ defp instrumented?(module) do
+ module.module_info(:attributes)[:iex_pry] == [true]
+ end
+
+ defp deinstrument!(module) do
+ beam = :code.which(module)
+ :code.purge(module)
+ {:module, _} = :code.load_binary(module, beam, File.read!(beam))
+ :ok
end
end
diff --git a/lib/logger/lib/logger/translator.ex b/lib/logger/lib/logger/translator.ex
index 592f0d7d7..5a5b11699 100644
--- a/lib/logger/lib/logger/translator.ex
+++ b/lib/logger/lib/logger/translator.ex
@@ -555,10 +555,7 @@ defmodule Logger.Translator do
defp format_mfa(mod, fun, args),
do: Exception.format_mfa(mod, fun, args)
- defp exit_reason(:exit, reason, stack) do
- if :erlang.system_info(:otp_release) >= '20', do: {reason, stack}, else: nil
- end
-
+ defp exit_reason(:exit, reason, stack), do: {reason, stack}
defp exit_reason(:error, reason, stack), do: {reason, stack}
defp exit_reason(:throw, value, stack), do: {{:nocatch, value}, stack}
diff --git a/lib/logger/test/logger/translator_test.exs b/lib/logger/test/logger/translator_test.exs
index 92f7a5fc7..3b9772db9 100644
--- a/lib/logger/test/logger/translator_test.exs
+++ b/lib/logger/test/logger/translator_test.exs
@@ -110,10 +110,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert {%RuntimeError{message: "oops"}, [_ | _]} = gen_server_metadata[:crash_reason]
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
refute Keyword.has_key?(gen_server_metadata, :initial_call)
assert process_metadata[:initial_call] == {Logger.TranslatorTest.MyGenServer, :init, 1}
@@ -157,95 +154,67 @@ defmodule Logger.TranslatorTest do
Application.put_env(:logger, :translator_inspect_opts, [])
end
- # TODO: Remove this check once we depend only on 20
- if :erlang.system_info(:otp_release) >= '20' do
- test "translates GenServer crashes on debug" do
- {:ok, pid} = GenServer.start(MyGenServer, :ok)
+ test "translates GenServer crashes on debug" do
+ {:ok, pid} = GenServer.start(MyGenServer, :ok)
- assert capture_log(:debug, fn ->
- catch_exit(GenServer.call(pid, :error))
- end) =~ ~r"""
- \[error\] GenServer #PID<\d+\.\d+\.\d+> terminating
- \*\* \(RuntimeError\) oops
- .*
- Last message \(from #PID<\d+\.\d+\.\d+>\): :error
- State: :ok
- Client #PID<\d+\.\d+\.\d+> is alive
- .*
- """s
+ assert capture_log(:debug, fn ->
+ catch_exit(GenServer.call(pid, :error))
+ end) =~ ~r"""
+ \[error\] GenServer #PID<\d+\.\d+\.\d+> terminating
+ \*\* \(RuntimeError\) oops
+ .*
+ Last message \(from #PID<\d+\.\d+\.\d+>\): :error
+ State: :ok
+ Client #PID<\d+\.\d+\.\d+> is alive
+ .*
+ """s
- assert_receive {:error, _pid,
- {Logger, [["GenServer " <> _ | _] | _], _ts, gen_server_metadata}}
+ assert_receive {:error, _pid,
+ {Logger, [["GenServer " <> _ | _] | _], _ts, gen_server_metadata}}
- assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
+ assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
- assert {%RuntimeError{message: "oops"}, [_ | _]} = gen_server_metadata[:crash_reason]
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = gen_server_metadata[:crash_reason]
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
+ end
- test "translates GenServer crashes with named client on debug" do
- {:ok, pid} = GenServer.start(MyGenServer, :ok)
-
- assert capture_log(:debug, fn ->
- Process.register(self(), :named_client)
- catch_exit(GenServer.call(pid, :error))
- end) =~ ~r"""
- \[error\] GenServer #PID<\d+\.\d+\.\d+> terminating
- \*\* \(RuntimeError\) oops
- .*
- Last message \(from :named_client\): :error
- State: :ok
- Client :named_client is alive
- .*
- """s
- end
+ test "translates GenServer crashes with named client on debug" do
+ {:ok, pid} = GenServer.start(MyGenServer, :ok)
- test "translates GenServer crashes with dead client on debug" do
- {:ok, pid} = GenServer.start(MyGenServer, :ok)
-
- assert capture_log(:debug, fn ->
- mon = Process.monitor(pid)
-
- spawn_link(fn ->
- catch_exit(GenServer.call(pid, :error_on_down, 0))
- end)
-
- assert_receive {:DOWN, ^mon, _, _, _}
- end) =~ ~r"""
- \[error\] GenServer #PID<\d+\.\d+\.\d+> terminating
- \*\* \(RuntimeError\) oops
- .*
- Last message \(from #PID<\d+\.\d+\.\d+>\): :error_on_down
- State: :ok
- Client #PID<\d+\.\d+\.\d+> is dead
- """s
- end
- else
- test "translates GenServer crashes on debug" do
- {:ok, pid} = GenServer.start(MyGenServer, :ok)
-
- assert capture_log(:debug, fn ->
- catch_exit(GenServer.call(pid, :error))
- end) =~ ~r"""
- \[error\] GenServer #PID<\d+\.\d+\.\d+> terminating
- \*\* \(RuntimeError\) oops
- .*
- Last message: :error
- State: :ok
- """s
-
- assert_receive {:error, _pid,
- {Logger, [["GenServer " <> _ | _] | _], _ts, gen_server_metadata}}
-
- assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
-
- assert {%RuntimeError{message: "oops"}, [_ | _]} = gen_server_metadata[:crash_reason]
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
- end
+ assert capture_log(:debug, fn ->
+ Process.register(self(), :named_client)
+ catch_exit(GenServer.call(pid, :error))
+ end) =~ ~r"""
+ \[error\] GenServer #PID<\d+\.\d+\.\d+> terminating
+ \*\* \(RuntimeError\) oops
+ .*
+ Last message \(from :named_client\): :error
+ State: :ok
+ Client :named_client is alive
+ .*
+ """s
+ end
+
+ test "translates GenServer crashes with dead client on debug" do
+ {:ok, pid} = GenServer.start(MyGenServer, :ok)
+
+ assert capture_log(:debug, fn ->
+ mon = Process.monitor(pid)
+
+ spawn_link(fn ->
+ catch_exit(GenServer.call(pid, :error_on_down, 0))
+ end)
+
+ assert_receive {:DOWN, ^mon, _, _, _}
+ end) =~ ~r"""
+ \[error\] GenServer #PID<\d+\.\d+\.\d+> terminating
+ \*\* \(RuntimeError\) oops
+ .*
+ Last message \(from #PID<\d+\.\d+\.\d+>\): :error_on_down
+ State: :ok
+ Client #PID<\d+\.\d+\.\d+> is dead
+ """s
end
test "translates GenServer crashes with no client" do
@@ -349,11 +318,9 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, task_metadata}}
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
- assert {%RuntimeError{message: "oops"}, [_ | _]} = task_metadata[:crash_reason]
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = task_metadata[:crash_reason]
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
refute Keyword.has_key?(task_metadata, :initial_call)
assert process_metadata[:initial_call] == {Logger.TranslatorTest, :task, 1}
@@ -375,11 +342,9 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, task_metadata}}
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
- assert {:oops, [_ | _]} = task_metadata[:crash_reason]
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%ErlangError{original: :oops}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:oops, [_ | _]} = task_metadata[:crash_reason]
+ assert {%ErlangError{original: :oops}, [_ | _]} = process_metadata[:crash_reason]
end
test "translates Task undef module crash" do
@@ -399,11 +364,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert {%UndefinedFunctionError{function: :undef}, [_ | _]} = task_metadata[:crash_reason]
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%UndefinedFunctionError{function: :undef}, [_ | _]} =
- process_metadata[:crash_reason]
- end
+ assert {%UndefinedFunctionError{function: :undef}, [_ | _]} = process_metadata[:crash_reason]
end
test "translates Task undef function crash" do
@@ -423,11 +384,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert {%UndefinedFunctionError{function: :undef}, [_ | _]} = task_metadata[:crash_reason]
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%UndefinedFunctionError{function: :undef}, [_ | _]} =
- process_metadata[:crash_reason]
- end
+ assert {%UndefinedFunctionError{function: :undef}, [_ | _]} = process_metadata[:crash_reason]
end
test "translates Task raising ErlangError" do
@@ -453,11 +410,9 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, task_metadata}}
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
- assert {%ErlangError{original: :foo}, [_ | _]} = task_metadata[:crash_reason]
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%ErlangError{original: :foo}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%ErlangError{original: :foo}, [_ | _]} = task_metadata[:crash_reason]
+ assert {%ErlangError{original: :foo}, [_ | _]} = process_metadata[:crash_reason]
end
test "translates Task raising Erlang badarg error" do
@@ -477,11 +432,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert {%ArgumentError{message: "argument error"}, [_ | _]} = task_metadata[:crash_reason]
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%ArgumentError{message: "argument error"}, [_ | _]} =
- process_metadata[:crash_reason]
- end
+ assert {%ArgumentError{message: "argument error"}, [_ | _]} = process_metadata[:crash_reason]
end
test "translates Task exiting abnormally" do
@@ -499,11 +450,9 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, task_metadata}}
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
- assert {:abnormal, [_ | _]} = task_metadata[:crash_reason]
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:abnormal, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:abnormal, [_ | _]} = task_metadata[:crash_reason]
+ assert {:abnormal, [_ | _]} = process_metadata[:crash_reason]
end
test "translates application start" do
@@ -537,10 +486,7 @@ defmodule Logger.TranslatorTest do
"""
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
end
test "translates :proc_lib crashes" do
@@ -566,10 +512,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert process_metadata[:foo] == :bar
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
end
test "skips :proc_lib crashes with disabled metadata" do
@@ -609,10 +552,7 @@ defmodule Logger.TranslatorTest do
"""s
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
end
test "translates :proc_lib crashes without initial call" do
@@ -636,10 +576,7 @@ defmodule Logger.TranslatorTest do
"""s
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
end
test "translates :proc_lib crashes with neighbour" do
@@ -692,8 +629,8 @@ defmodule Logger.TranslatorTest do
send(pid, :go)
receive do: ({:DOWN, ^ref, _, _, _} -> :ok)
end) =~ ~r"""
- Ancestors: \[#PID<\d+\.\d+\.\d+>\](?:
- Message Queue Length: 1(?#TODO: Require once depend on Erlang/OTP 20)|)
+ Ancestors: \[#PID<\d+\.\d+\.\d+>\]
+ Message Queue Length: 1
Messages: \[:message\]
Links: \[\]
Dictionary: \[\]
@@ -706,11 +643,9 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, task_metadata}}
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
- assert {%RuntimeError{message: "oops"}, [_ | _]} = task_metadata[:crash_reason]
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = task_metadata[:crash_reason]
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
end
test "translates :proc_lib crashes with neighbour on debug" do
@@ -731,9 +666,9 @@ defmodule Logger.TranslatorTest do
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 Erlang/OTP 20)|)
+ test/logger/translator_test.exs:\d+: Logger.TranslatorTest.sleep/1
"""
end
@@ -854,11 +789,9 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert_receive {:error, _pid, {Logger, ["Child " | _], _ts, _child_metadata}}
assert_receive {:error, _pid, {Logger, ["Child ", "Task" | _], _ts, _child_task_metadata}}
- assert {:stop, [_ | _]} = task_metadata[:crash_reason]
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:stop, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:stop, [_ | _]} = task_metadata[:crash_reason]
+ assert {:stop, [_ | _]} = process_metadata[:crash_reason]
end
test "translates Supervisor reports max restarts shutdown" do
@@ -878,11 +811,9 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert_receive {:error, _pid, {Logger, ["Child " | _], _ts, _child_metadata}}
assert_receive {:error, _pid, {Logger, ["Child ", "Task" | _], _ts, _child_task_metadata}}
- assert {:stop, [_ | _]} = task_metadata[:crash_reason]
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:stop, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:stop, [_ | _]} = task_metadata[:crash_reason]
+ assert {:stop, [_ | _]} = process_metadata[:crash_reason]
end
test "translates Supervisor reports abnormal shutdown" do
@@ -899,10 +830,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert_receive {:error, _pid, {Logger, ["Child " | _], _ts, _child_metadata}}
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:stop, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:stop, [_ | _]} = process_metadata[:crash_reason]
end
test "translates Supervisor reports abnormal shutdown on debug" do
@@ -924,10 +852,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert_receive {:error, _pid, {Logger, ["Child " | _], _ts, _child_metadata}}
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:stop, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:stop, [_ | _]} = process_metadata[:crash_reason]
end
test "translates Supervisor reports abnormal shutdown in simple_one_for_one" do
@@ -948,10 +873,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert_receive {:error, _pid, {Logger, ["Children " | _], _ts, _children_metadata}}
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:stop, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:stop, [_ | _]} = process_metadata[:crash_reason]
end
test "translates DynamicSupervisor reports abnormal shutdown" do
@@ -972,10 +894,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert_receive {:error, _pid, {Logger, ["Child " | _], _ts, child_metadata}}
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:stop, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:stop, [_ | _]} = process_metadata[:crash_reason]
end
test "translates DynamicSupervisor reports abnormal shutdown including extra_arguments" do
@@ -999,10 +918,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert_receive {:error, _pid, {Logger, ["Child " | _], _ts, _child_metadata}}
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:stop, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:stop, [_ | _]} = process_metadata[:crash_reason]
end
test "translates named DynamicSupervisor reports abnormal shutdown" do
@@ -1023,10 +939,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, process_metadata}}
assert_receive {:error, _pid, {Logger, ["Child " | _], _ts, _child_metadata}}
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:stop, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:stop, [_ | _]} = process_metadata[:crash_reason]
end
test "translates :supervisor_bridge progress" do
@@ -1060,10 +973,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Child of Supervisor " | _], _ts, _child_metadata}}
assert {:stop, [_ | _]} = task_metadata[:crash_reason]
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {:stop, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {:stop, [_ | _]} = process_metadata[:crash_reason]
end
test "reports :undefined MFA properly" do
@@ -1092,10 +1002,7 @@ defmodule Logger.TranslatorTest do
assert_receive {:error, _pid, {Logger, ["Child " | _], _ts, child_metadata}}
assert {%RuntimeError{message: "oops"}, [_ | _]} = server_metadata[:crash_reason]
-
- if :erlang.system_info(:otp_release) >= '20' do
- assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
- end
+ assert {%RuntimeError{message: "oops"}, [_ | _]} = process_metadata[:crash_reason]
after
:code.purge(WeirdFunctionNamesGenServer)
:code.delete(WeirdFunctionNamesGenServer)
diff --git a/lib/mix/lib/mix/tasks/escript.build.ex b/lib/mix/lib/mix/tasks/escript.build.ex
index 3b06f09e2..10959a50e 100644
--- a/lib/mix/lib/mix/tasks/escript.build.ex
+++ b/lib/mix/lib/mix/tasks/escript.build.ex
@@ -387,14 +387,14 @@ defmodule Mix.Tasks.Escript.Build do
erl_version = :erlang.system_info(:otp_release)
case :string.to_integer(erl_version) do
- {num, _} when num >= 19 ->
- nil
+ {num, _} when num >= 20 ->
+ :ok
_ ->
error_message = [
"Incompatible Erlang/OTP release: ",
erl_version,
- ".\nThis escript requires at least Erlang/OTP 19.0\n"
+ ".\nThis escript requires at least Erlang/OTP 20.0\n"
]
io_error(error_message)