Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71c335ac26 | ||
|
|
02f5d57871 | ||
|
|
6c16486b4a | ||
|
|
bfa5d6d23c | ||
|
|
c30b6d675b | ||
|
|
b59937b80f | ||
|
|
5b0f17130f | ||
|
|
2548965a1e | ||
|
|
09c01da205 | ||
|
|
9ed78dea24 | ||
|
|
e5888e7b93 | ||
|
|
13af842c66 | ||
|
|
a211223810 | ||
|
|
8bc3c826b1 | ||
|
|
7a3d6ec928 | ||
|
|
9b2e7892ca | ||
|
|
04794d5dfd | ||
|
|
36c2787fc6 | ||
|
|
2bafa0b50b | ||
|
|
c953de0036 | ||
|
|
aad7aa4d22 | ||
|
|
ebe23614f7 | ||
|
|
d8d6ab48c8 |
+4
-1
@@ -58,7 +58,7 @@ Another important change related to configuration is that `mix new` will no long
|
||||
|
||||
There are many other enhancements. The Elixir CLI got a handful of new options in order to best support releases. `Logger` now computes its sync/async/discard thresholds in a decentralized fashion, reducing contention. `EEx` templates support more complex expressions than before. Finally, there is a new `~U` sigil for working with UTC DateTimes as well as new functions in the `File`, `Registry`, and `System` modules.
|
||||
|
||||
## v1.9.0-dev
|
||||
## v1.9.0 (2019-06-24)
|
||||
|
||||
### 1. Enhancements
|
||||
|
||||
@@ -110,6 +110,7 @@ There are many other enhancements. The Elixir CLI got a handful of new options i
|
||||
|
||||
* [Mix] Follow XDG base dir specification in Mix for temporary and configuration files
|
||||
* [Mix.Generator] Add `copy_file/3`, `copy_template/4`, and `overwite?/2`
|
||||
* [Mix.Project] Add `preferred_cli_target` that works like `preferred_cli_env`
|
||||
* [mix archive.uninstall] Allow `mix archive.uninstall APP` to uninstall any installed version of APP
|
||||
* [mix new] No longer generate a `config/` directory for mix new
|
||||
* [mix release] Add support for releases
|
||||
@@ -125,6 +126,7 @@ There are many other enhancements. The Elixir CLI got a handful of new options i
|
||||
#### Elixir
|
||||
|
||||
* [Code] Quote `::` in `Code.format_string!/1` to avoid ambiguity
|
||||
* [Code] Do not crash formatter on false positive sigils
|
||||
* [Enum] Ensure the first equal entry is returned by `Enum.min/2` and `Enum.max/2`
|
||||
* [Kernel] Improve error message when string interpolation is used in a guard
|
||||
* [Kernel] Properly merge and handle docs for callbacks with multiple clauses
|
||||
@@ -157,6 +159,7 @@ There are many other enhancements. The Elixir CLI got a handful of new options i
|
||||
* [mix compile] Ensure Erlang-based Mix compilers (erlang, leex, yecc) set valid position on diagnostics
|
||||
* [mix compile] Ensure compilation halts in an umbrella project if one of the siblings fail to compile
|
||||
* [mix deps] Raise an error if the umbrella app's dir name and `mix.exs` app name don't match
|
||||
* [mix deps.compile] Fix subcommand splitting bug in rebar3
|
||||
* [mix test] Do not consider modules that are no longer cover compiled when computing coverage report, which could lead to flawed reports
|
||||
|
||||
### 3. Soft-deprecations (no warnings emitted)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
PREFIX ?= /usr/local
|
||||
SHARE_PREFIX ?= $(PREFIX)/share
|
||||
MAN_PREFIX ?= $(SHARE_PREFIX)/man
|
||||
CANONICAL := master/ # master/ or vMAJOR.MINOR/
|
||||
CANONICAL := v1.9/ # master/ or vMAJOR.MINOR/
|
||||
ELIXIRC := bin/elixirc --verbose --ignore-module-conflict $(ELIXIRC_OPTS)
|
||||
ERLC := erlc -I lib/elixir/include $(ERLC_OPTS)
|
||||
ERL := erl -I lib/elixir/include -noshell -pa lib/elixir/ebin
|
||||
|
||||
+2
-1
@@ -26,7 +26,8 @@
|
||||
Time,
|
||||
Tuple,
|
||||
URI,
|
||||
Version
|
||||
Version,
|
||||
Version.Requirement
|
||||
],
|
||||
"Collections & Enumerables": [
|
||||
Access,
|
||||
|
||||
@@ -963,6 +963,7 @@ defmodule Code do
|
||||
|
||||
For compiling many files concurrently, see `Kernel.ParallelCompiler.compile/2`.
|
||||
"""
|
||||
@doc since: "1.7.0"
|
||||
@spec compile_file(binary, nil | binary) :: [{module, binary}]
|
||||
def compile_file(file, relative_to \\ nil) when is_binary(file) do
|
||||
:elixir_compiler.file(find_file(file, relative_to), fn _, _ -> :ok end)
|
||||
|
||||
@@ -1156,7 +1156,7 @@ defmodule Code.Formatter do
|
||||
{left_doc, _join, state} =
|
||||
args_to_algebra_with_comments(
|
||||
left,
|
||||
Keyword.delete(meta, :end),
|
||||
Keyword.delete(meta, :closing),
|
||||
skip_parens?,
|
||||
:force_comma,
|
||||
join,
|
||||
@@ -1365,26 +1365,26 @@ defmodule Code.Formatter do
|
||||
## Sigils
|
||||
|
||||
defp maybe_sigil_to_algebra(fun, meta, args, state) do
|
||||
case {Atom.to_string(fun), args} do
|
||||
{<<"sigil_", name>>, [{:<<>>, _, entries}, modifiers]} ->
|
||||
opening_terminator = Keyword.fetch!(meta, :terminator)
|
||||
doc = <<?~, name, opening_terminator::binary>>
|
||||
with <<"sigil_", name>> <- Atom.to_string(fun),
|
||||
[{:<<>>, _, entries}, modifiers] when is_list(modifiers) <- args,
|
||||
opening_terminator when not is_nil(opening_terminator) <- Keyword.get(meta, :terminator) do
|
||||
doc = <<?~, name, opening_terminator::binary>>
|
||||
|
||||
if opening_terminator in [@double_heredoc, @single_heredoc] do
|
||||
closing_terminator = concat(opening_terminator, List.to_string(modifiers))
|
||||
if opening_terminator in [@double_heredoc, @single_heredoc] do
|
||||
closing_terminator = concat(opening_terminator, List.to_string(modifiers))
|
||||
|
||||
{doc, state} =
|
||||
entries
|
||||
|> prepend_heredoc_line()
|
||||
|> interpolation_to_algebra(:heredoc, state, doc, closing_terminator)
|
||||
|
||||
{force_unfit(doc), state}
|
||||
else
|
||||
escape = closing_sigil_terminator(opening_terminator)
|
||||
closing_terminator = concat(escape, List.to_string(modifiers))
|
||||
interpolation_to_algebra(entries, escape, state, doc, closing_terminator)
|
||||
end
|
||||
{doc, state} =
|
||||
entries
|
||||
|> prepend_heredoc_line()
|
||||
|> interpolation_to_algebra(:heredoc, state, doc, closing_terminator)
|
||||
|
||||
{force_unfit(doc), state}
|
||||
else
|
||||
escape = closing_sigil_terminator(opening_terminator)
|
||||
closing_terminator = concat(escape, List.to_string(modifiers))
|
||||
interpolation_to_algebra(entries, escape, state, doc, closing_terminator)
|
||||
end
|
||||
else
|
||||
_ ->
|
||||
:error
|
||||
end
|
||||
@@ -1847,7 +1847,7 @@ defmodule Code.Formatter do
|
||||
end
|
||||
|
||||
defp add_max_line_to_last_clause([{op, meta, args}], max_line) do
|
||||
[{op, [end: [line: max_line]] ++ meta, args}]
|
||||
[{op, [closing: [line: max_line]] ++ meta, args}]
|
||||
end
|
||||
|
||||
defp add_max_line_to_last_clause([clause | clauses], max_line) do
|
||||
@@ -2239,7 +2239,7 @@ defmodule Code.Formatter do
|
||||
end
|
||||
|
||||
defp end_line(meta) do
|
||||
meta[:end][:line] || @min_line
|
||||
meta[:closing][:line] || @min_line
|
||||
end
|
||||
|
||||
## Algebra helpers
|
||||
|
||||
+31
-17
@@ -4,8 +4,8 @@ defmodule Config do
|
||||
|
||||
## Example
|
||||
|
||||
This module is most commonly used to define application
|
||||
configuration, typically in `config/config.exs`:
|
||||
This module is most commonly used to define application configuration,
|
||||
typically in `config/config.exs`:
|
||||
|
||||
import Config
|
||||
|
||||
@@ -18,14 +18,20 @@ defmodule Config do
|
||||
`import Config` will import the functions `config/2`, `config/3`
|
||||
and `import_config/1` to help you manage your configuration.
|
||||
|
||||
Once Mix starts, it will automatically evaluate the configuration
|
||||
file and persist it into `:some_app`'s application environment, which
|
||||
can be accessed in as follows:
|
||||
`config/2` and `config/3` are used to define key-value configuration
|
||||
for a given application. Once Mix starts, it will automatically
|
||||
evaluate the configuration file and persist the configuration above
|
||||
into `:some_app`'s application environment, which can be accessed in
|
||||
as follows:
|
||||
|
||||
"value1" = Application.fetch_env!(:some_app, :key1)
|
||||
|
||||
See `Config.Reader` for evaluating and reading configuration
|
||||
files.
|
||||
Finally, the line `import_config "#{Mix.env()}.exs"` will import other
|
||||
config files, based on the current Mix environment, such as
|
||||
`config/dev.exs` and `config/test.exs`.
|
||||
|
||||
`Config` also provides a low-level API for evaluating and reading
|
||||
configuration, under the `Config.Reader` module.
|
||||
|
||||
**Important:** if you are writing a library to be used by other developers,
|
||||
it is generally recommended to avoid the application environment, as the
|
||||
@@ -34,17 +40,16 @@ defmodule Config do
|
||||
|
||||
## Migrating from `use Mix.Config`
|
||||
|
||||
The `Config` module in Elixir was introduced in v1.9 as a
|
||||
replacement to `Mix.Config`, which was specific to Mix and
|
||||
has been deprecated.
|
||||
The `Config` module in Elixir was introduced in v1.9 as a replacement to
|
||||
`Mix.Config`, which was specific to Mix and has been deprecated.
|
||||
|
||||
You can leverage `Config` instead of `Mix.Config` in two steps.
|
||||
The first step is to replace `use Mix.Config` at the top of
|
||||
your config files by `import Config`.
|
||||
You can leverage `Config` instead of `Mix.Config` in two steps. The first
|
||||
step is to replace `use Mix.Config` at the top of your config files by
|
||||
`import Config`.
|
||||
|
||||
The second is to make sure your `import_config/1` calls do
|
||||
not have a wildcard character. If so, you need to perform
|
||||
the wildcard lookup manually. For example, if you did:
|
||||
The second is to make sure your `import_config/1` calls do not have a
|
||||
wildcard character. If so, you need to perform the wildcard lookup
|
||||
manually. For example, if you did:
|
||||
|
||||
import_config "../apps/*/config/config.exs"
|
||||
|
||||
@@ -54,6 +59,15 @@ defmodule Config do
|
||||
import_config config
|
||||
end
|
||||
|
||||
## config/releases.exs
|
||||
|
||||
If you are using releases, see `mix release`, there another configuration
|
||||
file called `config/releases.exs`. While `config/config.exs` and friends
|
||||
mentioned in the previous section are executed whenever you run a Mix
|
||||
command, including when you assemble a release, `config/releases.exs` is
|
||||
execute every time your production system boots. Since Mix is not available
|
||||
in a production system, `config/releases.exs` must not use any of the
|
||||
functions from Mix.
|
||||
"""
|
||||
|
||||
@config_key {__MODULE__, :config}
|
||||
@@ -152,7 +166,7 @@ defmodule Config do
|
||||
|
||||
"""
|
||||
@doc since: "1.9.0"
|
||||
def config(root_key, key, opts) when is_atom(root_key) do
|
||||
def config(root_key, key, opts) when is_atom(root_key) and is_atom(key) do
|
||||
get_config!()
|
||||
|> __merge__([{root_key, [{key, opts}]}])
|
||||
|> put_config()
|
||||
|
||||
@@ -220,9 +220,7 @@ defmodule Config.Provider do
|
||||
end
|
||||
|
||||
defp write_config!(config, path) do
|
||||
{date, time} = :erlang.localtime()
|
||||
args = [date, time, config]
|
||||
contents = :io_lib.format("%% coding: utf-8~n%% config generated at ~p ~p~n~p.~n", args)
|
||||
contents = :io_lib.format("%% coding: utf-8~n~p.~n", [config])
|
||||
|
||||
case File.write(path, contents) do
|
||||
:ok ->
|
||||
|
||||
@@ -33,7 +33,7 @@ defmodule Inspect.Opts do
|
||||
|
||||
* `:printable_limit` - limits the number of characters that are inspected
|
||||
on printable strings and printable charlists. You can use `String.printable?/1`
|
||||
and `List.ascii_printable?/1` to check if a a given string or charlist is
|
||||
and `List.ascii_printable?/1` to check if a given string or charlist is
|
||||
printable. Defaults to 4096. If you don't want to limit the number of
|
||||
characters to a particular number, use `:infinity`.
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ defmodule Kernel.LexicalTracker do
|
||||
|
||||
@doc false
|
||||
def stop(pid) do
|
||||
:gen_server.cast(pid, :stop)
|
||||
:gen_server.call(pid, :stop)
|
||||
end
|
||||
|
||||
@doc false
|
||||
@@ -146,6 +146,10 @@ defmodule Kernel.LexicalTracker do
|
||||
{:reply, :maps.get(key, cache), state}
|
||||
end
|
||||
|
||||
def handle_call(:stop, _from, state) do
|
||||
{:stop, :normal, :ok, state}
|
||||
end
|
||||
|
||||
def handle_cast({:write_cache, key, value}, %{cache: cache} = state) do
|
||||
{:noreply, %{state | cache: :maps.put(key, value, cache)}}
|
||||
end
|
||||
@@ -206,10 +210,6 @@ defmodule Kernel.LexicalTracker do
|
||||
{:noreply, %{state | directives: add_directive(state.directives, module, line, warn, :alias)}}
|
||||
end
|
||||
|
||||
def handle_cast(:stop, state) do
|
||||
{:stop, :normal, state}
|
||||
end
|
||||
|
||||
@doc false
|
||||
def handle_info(_msg, state) do
|
||||
{:noreply, state}
|
||||
|
||||
@@ -557,7 +557,7 @@ defmodule Kernel.Typespec do
|
||||
types =
|
||||
:lists.map(
|
||||
fn {field, _} -> {field, Keyword.get(fields, field, quote(do: term()))} end,
|
||||
struct
|
||||
:lists.sort(struct)
|
||||
)
|
||||
|
||||
fun = fn {field, _} ->
|
||||
|
||||
@@ -85,7 +85,7 @@ defmodule Macro.Env do
|
||||
aliases: aliases,
|
||||
functions: functions,
|
||||
macros: macros,
|
||||
macro_aliases: aliases,
|
||||
macro_aliases: macro_aliases,
|
||||
context_modules: context_modules,
|
||||
vars: vars,
|
||||
unused_vars: unused_vars,
|
||||
|
||||
@@ -158,4 +158,4 @@ Version | Deprecated feature | Replaced by (ava
|
||||
[v1.6]: https://github.com/elixir-lang/elixir/blob/v1.6/CHANGELOG.md#4-deprecations
|
||||
[v1.7]: https://github.com/elixir-lang/elixir/blob/v1.7/CHANGELOG.md#4-hard-deprecations
|
||||
[v1.8]: https://github.com/elixir-lang/elixir/blob/v1.8/CHANGELOG.md#4-hard-deprecations
|
||||
[v1.9]: https://github.com/elixir-lang/elixir/blob/master/CHANGELOG.md#4-hard-deprecations
|
||||
[v1.9]: https://github.com/elixir-lang/elixir/blob/v1.9/CHANGELOG.md#4-hard-deprecations
|
||||
|
||||
@@ -382,10 +382,11 @@ translate_with_else(Meta, [], S) ->
|
||||
Var = {var, Ann, VarName},
|
||||
{{clause, Ann, [Var], [], [Var]}, SC};
|
||||
translate_with_else(Meta, [{else, [{'->', _, [[{Var, VarMeta, Kind}], Clause]}]}], S) when is_atom(Var), is_atom(Kind) ->
|
||||
Ann = ?ann(?generated(Meta)),
|
||||
Ctx = elixir_utils:var_context(VarMeta, Kind),
|
||||
{ElseVarErl, SV} = elixir_erl_var:assign(Meta, Var, Ctx, S),
|
||||
{TranslatedClause, SC} = elixir_erl_pass:translate(Clause, SV),
|
||||
{{clause, Meta, [ElseVarErl], [], [TranslatedClause]}, SC};
|
||||
{{clause, Ann, [ElseVarErl], [], [TranslatedClause]}, SC};
|
||||
translate_with_else(Meta, [{else, Else}], S) ->
|
||||
Generated = ?generated(Meta),
|
||||
ElseVarEx = {else, Generated, ?var_context},
|
||||
|
||||
@@ -653,12 +653,12 @@ line_from_location({Line, _Column, _}) -> Line.
|
||||
is_eol({_, _, Eol}) -> is_integer(Eol) and (Eol > 0).
|
||||
|
||||
end_meta(Token) ->
|
||||
[{format, block}, {'end', meta_from_location(?location(Token))}].
|
||||
[{format, block}, {closing, meta_from_location(?location(Token))}].
|
||||
|
||||
meta_from_token_with_end(Begin, End) ->
|
||||
meta_from_token_with_closing(Begin, End) ->
|
||||
case ?formatter_metadata() of
|
||||
true ->
|
||||
[{'end', meta_from_location(?location(End))} | meta_from_token(Begin)];
|
||||
[{closing, meta_from_location(?location(End))} | meta_from_token(Begin)];
|
||||
false ->
|
||||
meta_from_token(Begin)
|
||||
end.
|
||||
@@ -740,7 +740,7 @@ eol_pair(Left, Right) ->
|
||||
true ->
|
||||
[
|
||||
{eol, is_eol(?location(Left)) and is_eol(?location(Right))},
|
||||
{'end', meta_from_location(?location(Right))}
|
||||
{closing, meta_from_location(?location(Right))}
|
||||
];
|
||||
false ->
|
||||
[]
|
||||
@@ -828,7 +828,7 @@ build_identifier({_, Location, Identifier}, Args) ->
|
||||
build_fn(Fn, Stab, End) ->
|
||||
case check_stab(Stab, none) of
|
||||
stab ->
|
||||
Meta = eol_op(?location(Fn)) ++ meta_from_token_with_end(Fn, End),
|
||||
Meta = eol_op(?location(Fn)) ++ meta_from_token_with_closing(Fn, End),
|
||||
{fn, Meta, collect_stab(Stab, [], [])};
|
||||
block ->
|
||||
return_error(meta_from_token(Fn), "expected anonymous functions to be defined with -> inside: ", "'fn'")
|
||||
@@ -902,7 +902,7 @@ charlist_part({Begin, End, Tokens}) ->
|
||||
Form = string_tokens_parse(Tokens),
|
||||
Meta =
|
||||
case ?formatter_metadata() of
|
||||
true -> [{'end', meta_from_location(End)} | meta_from_location(Begin)];
|
||||
true -> [{closing, meta_from_location(End)} | meta_from_location(Begin)];
|
||||
false -> meta_from_location(Begin)
|
||||
end,
|
||||
{{'.', Meta, ['Elixir.Kernel', to_string]}, Meta, [Form]}.
|
||||
@@ -915,7 +915,7 @@ string_part({Begin, End, Tokens}) ->
|
||||
Form = string_tokens_parse(Tokens),
|
||||
Meta =
|
||||
case ?formatter_metadata() of
|
||||
true -> [{'end', meta_from_location(End)} | meta_from_location(Begin)];
|
||||
true -> [{closing, meta_from_location(End)} | meta_from_location(Begin)];
|
||||
false -> meta_from_location(Begin)
|
||||
end,
|
||||
{'::', Meta, [{{'.', Meta, ['Elixir.Kernel', to_string]}, Meta, [Form]}, {binary, Meta, nil}]}.
|
||||
@@ -943,7 +943,7 @@ build_stab(Stab) ->
|
||||
build_stab(Before, Stab, After) ->
|
||||
case build_stab(Stab) of
|
||||
{'__block__', Meta, Block} ->
|
||||
{'__block__', Meta ++ meta_from_token_with_end(Before, After), Block};
|
||||
{'__block__', Meta ++ meta_from_token_with_closing(Before, After), Block};
|
||||
Other ->
|
||||
Other
|
||||
end.
|
||||
|
||||
@@ -461,6 +461,14 @@ defmodule Code.Formatter.IntegrationTest do
|
||||
"""
|
||||
end
|
||||
|
||||
test "false positive sigil" do
|
||||
assert_same """
|
||||
def sigil_d(<<year::2-bytes, "-", month::2-bytes, "-", day::2-bytes>>, calendar) do
|
||||
ymd(year, month, day, calendar)
|
||||
end
|
||||
"""
|
||||
end
|
||||
|
||||
test "capture with operators" do
|
||||
assert_same """
|
||||
"this works" |> (&String.upcase/1) |> (&String.downcase/1)
|
||||
|
||||
@@ -252,12 +252,14 @@ defmodule CodeTest do
|
||||
assert string_to_quoted.(":one") == {:__block__, [line: 1], [:one]}
|
||||
|
||||
args = [[{:__block__, [original: '1', line: 1], [1]}]]
|
||||
assert string_to_quoted.("[1]") == {:__block__, [eol: false, end: [line: 1], line: 1], args}
|
||||
|
||||
assert string_to_quoted.("[1]") ==
|
||||
{:__block__, [eol: false, closing: [line: 1], line: 1], args}
|
||||
|
||||
args = [{{:__block__, [line: 1], [:ok]}, {:__block__, [line: 1], [:test]}}]
|
||||
|
||||
assert string_to_quoted.("{:ok, :test}") ==
|
||||
{:__block__, [eol: false, end: [line: 1], line: 1], args}
|
||||
{:__block__, [eol: false, closing: [line: 1], line: 1], args}
|
||||
|
||||
assert string_to_quoted.(~s("""\nhello\n""")) ==
|
||||
{:__block__, [format: :bin_heredoc, line: 1], ["hello\n"]}
|
||||
@@ -265,12 +267,12 @@ defmodule CodeTest do
|
||||
assert string_to_quoted.("'''\nhello\n'''") ==
|
||||
{:__block__, [format: :list_heredoc, line: 1], ['hello\n']}
|
||||
|
||||
left = {:__block__, [original: '1', line: 1, end: [line: 1], line: 1], [1]}
|
||||
left = {:__block__, [original: '1', line: 1, closing: [line: 1], line: 1], [1]}
|
||||
right = {:__block__, [format: :string, line: 1], ["hello"]}
|
||||
args = [{:->, [line: 1], [[left], right]}]
|
||||
|
||||
assert string_to_quoted.(~s[fn (1) -> "hello" end]) ==
|
||||
{:fn, [end: [line: 1], line: 1], args}
|
||||
{:fn, [closing: [line: 1], line: 1], args}
|
||||
end
|
||||
|
||||
test "adds newlines information to blocks when :formatter_metadata (private) is given" do
|
||||
@@ -285,11 +287,11 @@ defmodule CodeTest do
|
||||
"""
|
||||
|
||||
args = [
|
||||
{:one, [eol: false, end: [line: 1], line: 1], []},
|
||||
{:two, [newlines: 0, eol: false, end: [line: 1], line: 1], []},
|
||||
{:three, [newlines: 1, eol: false, end: [line: 2], line: 2], []},
|
||||
{:four, [newlines: 2, eol: false, end: [line: 4], line: 4], []},
|
||||
{:five, [newlines: 3, eol: false, end: [line: 7], line: 7], []}
|
||||
{:one, [eol: false, closing: [line: 1], line: 1], []},
|
||||
{:two, [newlines: 0, eol: false, closing: [line: 1], line: 1], []},
|
||||
{:three, [newlines: 1, eol: false, closing: [line: 2], line: 2], []},
|
||||
{:four, [newlines: 2, eol: false, closing: [line: 4], line: 4], []},
|
||||
{:five, [newlines: 3, eol: false, closing: [line: 7], line: 7], []}
|
||||
]
|
||||
|
||||
assert Code.string_to_quoted!(file, formatter_metadata: true) == {:__block__, [], args}
|
||||
|
||||
@@ -480,6 +480,23 @@ defmodule TypespecTest do
|
||||
assert {:type, _, :map_field_exact, [{:atom, _, :other}, {:type, _, :term, []}]} = arg2
|
||||
end
|
||||
|
||||
@fields Enum.map(10..42, &{:"f#{&1}", :ok})
|
||||
|
||||
test "@type with a large struct" do
|
||||
bytecode =
|
||||
test_module do
|
||||
defstruct unquote(@fields)
|
||||
@type my_type :: %TypespecSample{unquote_splicing(@fields)}
|
||||
end
|
||||
|
||||
assert [type: {:my_type, type, []}] = types(bytecode)
|
||||
assert {:type, _, :map, [struct, arg1, arg2 | _]} = type
|
||||
assert {:type, _, :map_field_exact, struct_args} = struct
|
||||
assert [{:atom, _, :__struct__}, {:atom, _, TypespecSample}] = struct_args
|
||||
assert {:type, _, :map_field_exact, [{:atom, _, :f10}, {:atom, _, :ok}]} = arg1
|
||||
assert {:type, _, :map_field_exact, [{:atom, _, :f11}, {:atom, _, :ok}]} = arg2
|
||||
end
|
||||
|
||||
test "@type with struct does not @enforce_keys" do
|
||||
bytecode =
|
||||
test_module do
|
||||
|
||||
@@ -644,7 +644,9 @@ defmodule IEx.Introspection do
|
||||
types_not_found(inspect(module))
|
||||
|
||||
{:ok, types} ->
|
||||
Enum.each(types, &(&1 |> format_type() |> IO.puts()))
|
||||
types
|
||||
|> Enum.sort_by(fn {_, {name, _, args}} -> {name, length(args)} end)
|
||||
|> Enum.each(&(&1 |> format_type() |> IO.puts()))
|
||||
end
|
||||
|
||||
dont_display_result()
|
||||
@@ -656,15 +658,19 @@ defmodule IEx.Introspection do
|
||||
no_beam(module)
|
||||
|
||||
{:ok, types} ->
|
||||
printed =
|
||||
for {kind, {^type, _, args}} = typespec <- types,
|
||||
kind != :typep do
|
||||
type_doc(module, type, length(args), typespec)
|
||||
|> print_typespec()
|
||||
end
|
||||
types
|
||||
|> Enum.filter(&match?({kind, {^type, _, _}} when kind in [:type, :opaque], &1))
|
||||
|> Enum.sort_by(fn {_, {name, _, args}} -> {name, length(args)} end)
|
||||
|> case do
|
||||
[] ->
|
||||
types_not_found_or_private("#{inspect(module)}.#{type}")
|
||||
|
||||
if printed == [] do
|
||||
types_not_found_or_private("#{inspect(module)}.#{type}")
|
||||
types ->
|
||||
Enum.map(types, fn {_, {_, _, args}} = typespec ->
|
||||
module
|
||||
|> type_doc(type, length(args), typespec)
|
||||
|> print_typespec()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -677,16 +683,21 @@ defmodule IEx.Introspection do
|
||||
no_beam(module)
|
||||
|
||||
{:ok, types} ->
|
||||
printed =
|
||||
for {kind, {^type, _, args}} = typespec <- types,
|
||||
kind != :typep,
|
||||
length(args) == arity do
|
||||
type_doc(module, type, arity, typespec)
|
||||
|> print_typespec()
|
||||
end
|
||||
types
|
||||
|> Enum.find(
|
||||
&match?(
|
||||
{kind, {^type, _, args}} when kind in [:type, :opaque] and length(args) == arity,
|
||||
&1
|
||||
)
|
||||
)
|
||||
|> case do
|
||||
nil ->
|
||||
types_not_found_or_private("#{inspect(module)}.#{type}")
|
||||
|
||||
if printed == [] do
|
||||
types_not_found_or_private("#{inspect(module)}.#{type}")
|
||||
typespec ->
|
||||
module
|
||||
|> type_doc(type, arity, typespec)
|
||||
|> print_typespec()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -824,6 +824,10 @@ defmodule IEx.HelpersTest do
|
||||
end) >= 2
|
||||
end
|
||||
|
||||
test "prints private types" do
|
||||
assert capture_io(fn -> t(Date.Range) end) =~ "@typep iso_days"
|
||||
end
|
||||
|
||||
test "prints type information" do
|
||||
assert "@type t() ::" <> _ = capture_io(fn -> t(Enum.t()) end)
|
||||
assert capture_io(fn -> t(Enum.t()) end) == capture_io(fn -> t(Enum.t() / 0) end)
|
||||
@@ -831,6 +835,16 @@ defmodule IEx.HelpersTest do
|
||||
assert capture_io(fn -> t(URI.t()) end) == capture_io(fn -> t(URI.t() / 0) end)
|
||||
end
|
||||
|
||||
test "sorts types alphabetically" do
|
||||
unsorted =
|
||||
capture_io(fn -> t(Enum) end)
|
||||
|> String.split("\n")
|
||||
|> Enum.reject(&(&1 == ""))
|
||||
|> Enum.map(&String.replace(&1, ~r/@(type|opaque) /, ""))
|
||||
|
||||
assert unsorted == Enum.sort(unsorted)
|
||||
end
|
||||
|
||||
test "prints type documentation" do
|
||||
content = """
|
||||
defmodule TypeSample do
|
||||
|
||||
+24
-11
@@ -29,7 +29,7 @@ defmodule Mix.CLI do
|
||||
load_mix_exs()
|
||||
{task, args} = get_task(args)
|
||||
ensure_hex(task)
|
||||
change_env(task)
|
||||
maybe_change_env_and_target(task)
|
||||
run_task(task, args)
|
||||
end
|
||||
|
||||
@@ -104,26 +104,39 @@ defmodule Mix.CLI do
|
||||
end
|
||||
end
|
||||
|
||||
defp change_env(task) do
|
||||
if env = preferred_cli_env(task) do
|
||||
Mix.env(env)
|
||||
defp maybe_change_env_and_target(task) do
|
||||
task = String.to_atom(task)
|
||||
config = Mix.Project.config()
|
||||
|
||||
if project = Mix.Project.pop() do
|
||||
%{name: name, file: file} = project
|
||||
Mix.Project.push(name, file)
|
||||
end
|
||||
env = preferred_cli_env(task, config)
|
||||
target = preferred_cli_target(task, config)
|
||||
env && Mix.env(env)
|
||||
target && Mix.target(target)
|
||||
|
||||
if env || target do
|
||||
reload_project()
|
||||
end
|
||||
end
|
||||
|
||||
defp preferred_cli_env(task) do
|
||||
defp reload_project() do
|
||||
if project = Mix.Project.pop() do
|
||||
%{name: name, file: file} = project
|
||||
Mix.Project.push(name, file)
|
||||
end
|
||||
end
|
||||
|
||||
defp preferred_cli_env(task, config) do
|
||||
if System.get_env("MIX_ENV") do
|
||||
nil
|
||||
else
|
||||
task = String.to_atom(task)
|
||||
Mix.Project.config()[:preferred_cli_env][task] || Mix.Task.preferred_cli_env(task)
|
||||
config[:preferred_cli_env][task] || Mix.Task.preferred_cli_env(task)
|
||||
end
|
||||
end
|
||||
|
||||
defp preferred_cli_target(task, config) do
|
||||
config[:preferred_cli_target][task]
|
||||
end
|
||||
|
||||
defp load_dot_config do
|
||||
path = Path.join(Mix.Utils.mix_config(), "config.exs")
|
||||
|
||||
|
||||
@@ -67,9 +67,13 @@ defmodule Mix.Project do
|
||||
* `:preferred_cli_env` - a keyword list of `{task, env}` tuples where `task`
|
||||
is the task name as an atom (for example, `:"deps.get"`) and `env` is the
|
||||
preferred environment (for example, `:test`). This option overrides what
|
||||
specified by the tasks with the `@preferred_cli_env` attribute (see the
|
||||
is specified by the tasks with the `@preferred_cli_env` attribute (see the
|
||||
docs for `Mix.Task`). Defaults to `[]`.
|
||||
|
||||
* `:preferred_cli_target` - a keyword list of `{task, target}` tuples where
|
||||
`task` is the task name as an atom (for example, `:test`) and `target`
|
||||
is the preferred target (for example, `:host`). Defaults to `[]`.
|
||||
|
||||
For more options, keep an eye on the documentation for single Mix tasks; good
|
||||
examples are the `Mix.Tasks.Compile` task and all the specific compiler tasks
|
||||
(such as `Mix.Tasks.Compile.Elixir` or `Mix.Tasks.Compile.Erlang`).
|
||||
|
||||
@@ -318,9 +318,8 @@ defmodule Mix.Release do
|
||||
{sys_config, runtime?} = merge_provider_config(release, sys_config, config_provider_path)
|
||||
path = Path.join(release.version_path, "sys.config")
|
||||
|
||||
{date, time} = :erlang.localtime()
|
||||
args = [runtime?, date, time, sys_config]
|
||||
format = "%% coding: utf-8~n%% RUNTIME_CONFIG=~s~n%% config generated at ~p ~p~n~p.~n"
|
||||
args = [runtime?, sys_config]
|
||||
format = "%% coding: utf-8~n%% RUNTIME_CONFIG=~s~n~p.~n"
|
||||
File.mkdir_p!(Path.dirname(path))
|
||||
File.write!(path, :io_lib.format(format, args))
|
||||
|
||||
@@ -407,7 +406,7 @@ defmodule Mix.Release do
|
||||
:ok | {:error, String.t()}
|
||||
def make_boot_script(release, path, modes, prepend_paths \\ []) do
|
||||
with {:ok, rel_spec} <- build_release_spec(release, modes) do
|
||||
File.write!(path <> ".rel", consultable("rel", rel_spec))
|
||||
File.write!(path <> ".rel", consultable(rel_spec))
|
||||
|
||||
sys_path = String.to_charlist(path)
|
||||
|
||||
@@ -430,7 +429,7 @@ defmodule Mix.Release do
|
||||
|> prepend_paths_to_script(prepend_paths)
|
||||
|
||||
script = {:script, rel_info, instructions}
|
||||
File.write!(script_path, consultable("script", script))
|
||||
File.write!(script_path, consultable(script))
|
||||
:ok = :systools.script2boot(sys_path)
|
||||
|
||||
{:error, module, info} ->
|
||||
@@ -546,10 +545,8 @@ defmodule Mix.Release do
|
||||
end)
|
||||
end
|
||||
|
||||
defp consultable(kind, term) do
|
||||
{date, time} = :erlang.localtime()
|
||||
args = [kind, date, time, term]
|
||||
:io_lib.format("%% coding: utf-8~n%% ~ts generated at ~p ~p~n~p.~n", args)
|
||||
defp consultable(term) do
|
||||
:io_lib.format("%% coding: utf-8~n~p.~n", [term])
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
||||
@@ -183,7 +183,7 @@ defmodule Mix.Tasks.Deps.Compile do
|
||||
lib_path = Path.join(config[:env_path], "lib/*/ebin")
|
||||
|
||||
env = [{"REBAR_CONFIG", config_path}, {"TERM", "dumb"}]
|
||||
cmd = "#{rebar_cmd(dep)} bare compile --paths #{inspect(lib_path)}"
|
||||
cmd = "#{rebar_cmd(dep)} bare compile --paths=#{inspect(lib_path)}"
|
||||
|
||||
File.mkdir_p!(dep_path)
|
||||
File.write!(config_path, rebar_config(dep))
|
||||
|
||||
@@ -667,6 +667,18 @@ defmodule Mix.Tasks.Release do
|
||||
not running on Erlang/OTP 22 or later, you must set `RELEASE_NODE`
|
||||
to `RELEASE_NAME@127.0.0.1` with an IP or a known host
|
||||
|
||||
* `RELEASE_BOOT_SCRIPT` - the name of the boot script to use when starting
|
||||
the release. This script is used when running commands such as `start` and
|
||||
`daemon`. The boot script is expected to be located at the
|
||||
path `releases/RELEASE_VSN/RELEASE_BOOT_SCRIPT.boot`. Defaults to `start`
|
||||
|
||||
* `RELEASE_BOOT_SCRIPT_CLEAN` - the name of the boot script used when
|
||||
starting the release clean, without your application or its dependencies.
|
||||
This script is used by commands such as `eval`, `rpc`, and `remote`.
|
||||
The boot script is expected to be located at the path
|
||||
`releases/RELEASE_VSN/RELEASE_BOOT_SCRIPT_CLEAN.boot`. Defaults
|
||||
to `start_clean`
|
||||
|
||||
## Umbrellas
|
||||
|
||||
Releases are well integrated with umbrella projects, allowing you to
|
||||
|
||||
@@ -66,7 +66,9 @@ defmodule Mix.Tasks.Release.Init do
|
||||
# export ELIXIR_ERL_OPTIONS="-heart"
|
||||
# fi
|
||||
|
||||
# Set the release to work across nodes
|
||||
# Set the release to work across nodes. If using the long name format like
|
||||
# the one below (my_app@127.0.0.1), you need to also uncomment the
|
||||
# RELEASE_DISTRIBUTION variable below.
|
||||
# export RELEASE_DISTRIBUTION=name
|
||||
# export RELEASE_NODE=<%= @release.name %>@127.0.0.1
|
||||
"""
|
||||
@@ -94,6 +96,8 @@ defmodule Mix.Tasks.Release.Init do
|
||||
export RELEASE_TMP="${RELEASE_TMP:-"$RELEASE_ROOT/tmp"}"
|
||||
export RELEASE_VM_ARGS="${RELEASE_VM_ARGS:-"$REL_VSN_DIR/vm.args"}"
|
||||
export RELEASE_DISTRIBUTION="${RELEASE_DISTRIBUTION:-"sname"}"
|
||||
export RELEASE_BOOT_SCRIPT="${RELEASE_BOOT_SCRIPT:-"start"}"
|
||||
export RELEASE_BOOT_SCRIPT_CLEAN="${RELEASE_BOOT_SCRIPT_CLEAN:-"start_clean"}"
|
||||
|
||||
rand () {
|
||||
od -t xS -N 2 -A n /dev/urandom | tr -d " \n"
|
||||
@@ -103,7 +107,7 @@ defmodule Mix.Tasks.Release.Init do
|
||||
exec "$REL_VSN_DIR/elixir" \
|
||||
--hidden --cookie "$RELEASE_COOKIE" \
|
||||
--$RELEASE_DISTRIBUTION "rpc-$(rand)-$RELEASE_NODE" \
|
||||
--boot "$REL_VSN_DIR/start_clean" \
|
||||
--boot "$REL_VSN_DIR/$RELEASE_BOOT_SCRIPT_CLEAN" \
|
||||
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
|
||||
--rpc-eval "$RELEASE_NODE" "$1"
|
||||
}
|
||||
@@ -117,7 +121,7 @@ defmodule Mix.Tasks.Release.Init do
|
||||
--$RELEASE_DISTRIBUTION "$RELEASE_NODE" \
|
||||
--erl "-mode $RELEASE_MODE" \
|
||||
--erl-config "$RELEASE_SYS_CONFIG" \
|
||||
--boot "$REL_VSN_DIR/start" \
|
||||
--boot "$REL_VSN_DIR/$RELEASE_BOOT_SCRIPT" \
|
||||
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
|
||||
--vm-args "$RELEASE_VM_ARGS" "$@"
|
||||
}
|
||||
@@ -164,7 +168,7 @@ defmodule Mix.Tasks.Release.Init do
|
||||
exec "$REL_VSN_DIR/elixir" \
|
||||
--cookie "$RELEASE_COOKIE" \
|
||||
--erl-config "$RELEASE_SYS_CONFIG" \
|
||||
--boot "$REL_VSN_DIR/start_clean" \
|
||||
--boot "$REL_VSN_DIR/$RELEASE_BOOT_SCRIPT_CLEAN" \
|
||||
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
|
||||
--vm-args "$RELEASE_VM_ARGS" --eval "$2"
|
||||
;;
|
||||
@@ -173,7 +177,7 @@ defmodule Mix.Tasks.Release.Init do
|
||||
exec "$REL_VSN_DIR/iex" \
|
||||
--werl --hidden --cookie "$RELEASE_COOKIE" \
|
||||
--$RELEASE_DISTRIBUTION "rem-$(rand)-$RELEASE_NODE" \
|
||||
--boot "$REL_VSN_DIR/start_clean" \
|
||||
--boot "$REL_VSN_DIR/$RELEASE_BOOT_SCRIPT_CLEAN" \
|
||||
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
|
||||
--remsh "$RELEASE_NODE"
|
||||
;;
|
||||
@@ -228,7 +232,9 @@ defmodule Mix.Tasks.Release.Init do
|
||||
def env_bat_text,
|
||||
do: ~S"""
|
||||
@echo off
|
||||
rem Set the release to work across nodes
|
||||
rem Set the release to work across nodes. If using the long name format like
|
||||
rem the one below (my_app@127.0.0.1), you need to also uncomment the
|
||||
rem RELEASE_DISTRIBUTION variable below.
|
||||
rem set RELEASE_DISTRIBUTION=name
|
||||
rem set RELEASE_NODE=<%= @release.name %>@127.0.0.1
|
||||
"""
|
||||
@@ -256,6 +262,8 @@ defmodule Mix.Tasks.Release.Init do
|
||||
if not defined RELEASE_TMP (set RELEASE_TMP=!RELEASE_ROOT!\tmp)
|
||||
if not defined RELEASE_VM_ARGS (set RELEASE_VM_ARGS=!REL_VSN_DIR!\vm.args)
|
||||
if not defined RELEASE_DISTRIBUTION (set RELEASE_DISTRIBUTION=sname)
|
||||
if not defined RELEASE_BOOT_SCRIPT (set RELEASE_BOOT_SCRIPT=start)
|
||||
if not defined RELEASE_BOOT_SCRIPT_CLEAN (set RELEASE_BOOT_SCRIPT_CLEAN=start_clean)
|
||||
set RELEASE_SYS_CONFIG=!REL_VSN_DIR!\sys
|
||||
|
||||
if "%~1" == "start" (set "REL_EXEC=elixir" && set "REL_EXTRA=--no-halt" && set "REL_GOTO=start")
|
||||
@@ -270,11 +278,11 @@ defmodule Mix.Tasks.Release.Init do
|
||||
)
|
||||
|
||||
if not "!REL_GOTO!" == "" (
|
||||
findstr "RUNTIME_CONFIG=true" "!RELEASE_SYS_CONFIG!.config" >nil 2>&1 && (
|
||||
findstr "RUNTIME_CONFIG=true" "!RELEASE_SYS_CONFIG!.config" >nul 2>&1 && (
|
||||
for /f "skip=1" %%X in ('wmic os get localdatetime') do if not defined TIMESTAMP set TIMESTAMP=%%X
|
||||
set RELEASE_SYS_CONFIG=!RELEASE_TMP!\!RELEASE_NAME!-!RELEASE_VSN!-!TIMESTAMP:~0,11!-!RANDOM!.runtime
|
||||
mkdir "!RELEASE_TMP!" >nil
|
||||
copy /y "!REL_VSN_DIR!\sys.config" "!RELEASE_SYS_CONFIG!.config" >nil || (
|
||||
mkdir "!RELEASE_TMP!" >nul
|
||||
copy /y "!REL_VSN_DIR!\sys.config" "!RELEASE_SYS_CONFIG!.config" >nul || (
|
||||
echo Cannot start release because it could not write to "!RELEASE_SYS_CONFIG!.config"
|
||||
goto end
|
||||
)
|
||||
@@ -321,7 +329,7 @@ defmodule Mix.Tasks.Release.Init do
|
||||
--!RELEASE_DISTRIBUTION! "!RELEASE_NODE!" ^
|
||||
--erl "-mode !RELEASE_MODE!" ^
|
||||
--erl-config "!RELEASE_SYS_CONFIG!" ^
|
||||
--boot "!REL_VSN_DIR!\start" ^
|
||||
--boot "!REL_VSN_DIR!\!RELEASE_BOOT_SCRIPT!" ^
|
||||
--boot-var RELEASE_LIB "!RELEASE_ROOT!\lib" ^
|
||||
--vm-args "!RELEASE_VM_ARGS!"
|
||||
goto end
|
||||
@@ -331,7 +339,7 @@ defmodule Mix.Tasks.Release.Init do
|
||||
--eval "%~2" ^
|
||||
--cookie "!RELEASE_COOKIE!" ^
|
||||
--erl-config "!RELEASE_SYS_CONFIG!" ^
|
||||
--boot "!REL_VSN_DIR!\start_clean" ^
|
||||
--boot "!REL_VSN_DIR!\!RELEASE_BOOT_SCRIPT_CLEAN!" ^
|
||||
--boot-var RELEASE_LIB "!RELEASE_ROOT!\lib" ^
|
||||
--vm-args "!RELEASE_VM_ARGS!"
|
||||
goto end
|
||||
@@ -340,7 +348,7 @@ defmodule Mix.Tasks.Release.Init do
|
||||
"!REL_VSN_DIR!\iex.bat" ^
|
||||
--werl --hidden --cookie "!RELEASE_COOKIE!" ^
|
||||
--!RELEASE_DISTRIBUTION! "rem-!RANDOM!-!RELEASE_NODE!" ^
|
||||
--boot "!REL_VSN_DIR!\start_clean" ^
|
||||
--boot "!REL_VSN_DIR!\!RELEASE_BOOT_SCRIPT_CLEAN!" ^
|
||||
--boot-var RELEASE_LIB "!RELEASE_ROOT!\lib" ^
|
||||
--remsh "!RELEASE_NODE!"
|
||||
goto end
|
||||
@@ -349,7 +357,7 @@ defmodule Mix.Tasks.Release.Init do
|
||||
"!REL_VSN_DIR!\elixir.bat" ^
|
||||
--hidden --cookie "!RELEASE_COOKIE!" ^
|
||||
--!RELEASE_DISTRIBUTION! "rpc-!RANDOM!-!RELEASE_NODE!" ^
|
||||
--boot "!REL_VSN_DIR!\start_clean" ^
|
||||
--boot "!REL_VSN_DIR!\!RELEASE_BOOT_SCRIPT_CLEAN!" ^
|
||||
--boot-var RELEASE_LIB "!RELEASE_ROOT!\lib" ^
|
||||
--rpc-eval "!RELEASE_NODE!" "!REL_RPC!"
|
||||
goto end
|
||||
|
||||
@@ -143,6 +143,32 @@ defmodule Mix.CLITest do
|
||||
System.delete_env("MIX_EXS")
|
||||
end
|
||||
|
||||
test "target config defaults to the user's preferred cli target", context do
|
||||
in_tmp(context.test, fn ->
|
||||
File.write!("custom.exs", """
|
||||
defmodule P do
|
||||
use Mix.Project
|
||||
def project, do: [app: :p, version: "0.1.0", preferred_cli_target: [test_task: :other]]
|
||||
end
|
||||
|
||||
defmodule Mix.Tasks.TestTask do
|
||||
use Mix.Task
|
||||
|
||||
def run(args) do
|
||||
IO.inspect {Mix.target, args}
|
||||
end
|
||||
end
|
||||
""")
|
||||
|
||||
System.put_env("MIX_EXS", "custom.exs")
|
||||
|
||||
output = mix(["test_task", "a", "b", "c"])
|
||||
assert output =~ ~s({:other, ["a", "b", "c"]})
|
||||
end)
|
||||
after
|
||||
System.delete_env("MIX_EXS")
|
||||
end
|
||||
|
||||
test "new with tests and cover" do
|
||||
in_tmp("new_with_tests", fn ->
|
||||
output = mix(~w[new .])
|
||||
|
||||
@@ -19,7 +19,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
end
|
||||
end
|
||||
|
||||
@tag apps: [:app_start_sample]
|
||||
test "compiles and starts the project" do
|
||||
Mix.Project.push(AppStartSample)
|
||||
|
||||
@@ -50,7 +49,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
end)
|
||||
end
|
||||
|
||||
@tag apps: [:app_start_sample, :app_loaded_sample]
|
||||
test "start checks for invalid configuration", context do
|
||||
Mix.Project.push(AppStartSample)
|
||||
|
||||
@@ -77,7 +75,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
end)
|
||||
end
|
||||
|
||||
@tag apps: [:error]
|
||||
test "validates Elixir version requirement", context do
|
||||
Mix.ProjectStack.post_config(elixir: "~> ~> 0.8.1")
|
||||
Mix.Project.push(WrongElixirProject)
|
||||
@@ -89,7 +86,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
end)
|
||||
end
|
||||
|
||||
@tag apps: [:error]
|
||||
test "validates the Elixir version with requirement", context do
|
||||
Mix.Project.push(WrongElixirProject)
|
||||
|
||||
@@ -100,7 +96,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
end)
|
||||
end
|
||||
|
||||
@tag apps: [:error]
|
||||
test "does not validate the Elixir version with requirement when disabled", context do
|
||||
Mix.Project.push(WrongElixirProject)
|
||||
|
||||
@@ -136,7 +131,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
def start(_type, return), do: return
|
||||
end
|
||||
|
||||
@tag apps: [:return_sample]
|
||||
test "start points to report on error", context do
|
||||
Mix.Project.push(ReturnSample)
|
||||
|
||||
@@ -155,7 +149,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
end)
|
||||
end
|
||||
|
||||
@tag apps: [:return_sample]
|
||||
test "start points to report on exception error", context do
|
||||
Mix.Project.push(ReturnSample)
|
||||
|
||||
@@ -177,7 +170,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
end)
|
||||
end
|
||||
|
||||
@tag apps: [:return_sample]
|
||||
test "start points to report on bad return", context do
|
||||
Mix.Project.push(ReturnSample)
|
||||
|
||||
@@ -212,7 +204,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
def start(_type, reason), do: exit(reason)
|
||||
end
|
||||
|
||||
@tag apps: [:exit_sample]
|
||||
test "start points to report on exit", context do
|
||||
Mix.Project.push(ExitSample)
|
||||
|
||||
@@ -230,7 +221,6 @@ defmodule Mix.Tasks.App.StartTest do
|
||||
end)
|
||||
end
|
||||
|
||||
@tag apps: [:exit_sample]
|
||||
test "start points to report on normal exit", context do
|
||||
Mix.Project.push(ExitSample)
|
||||
|
||||
|
||||
@@ -4,10 +4,8 @@ defmodule Mix.Tasks.Profile.CprofTest do
|
||||
use MixTest.Case
|
||||
|
||||
import ExUnit.CaptureIO
|
||||
|
||||
alias Mix.Tasks.Profile.Cprof
|
||||
|
||||
@moduletag apps: [:sample]
|
||||
@expr "Enum.each(1..5, &String.Chars.Integer.to_string/1)"
|
||||
|
||||
test "profiles evaluated expression", context do
|
||||
|
||||
@@ -4,10 +4,8 @@ defmodule Mix.Tasks.Profile.EprofTest do
|
||||
use MixTest.Case
|
||||
|
||||
import ExUnit.CaptureIO
|
||||
|
||||
alias Mix.Tasks.Profile.Eprof
|
||||
|
||||
@moduletag apps: [:sample]
|
||||
@expr "Enum.each(1..5, &String.Chars.Integer.to_string/1)"
|
||||
|
||||
test "profiles evaluated expression", context do
|
||||
|
||||
@@ -4,9 +4,7 @@ defmodule Mix.Tasks.Profile.FprofTest do
|
||||
use MixTest.Case
|
||||
|
||||
import ExUnit.CaptureIO
|
||||
|
||||
alias Mix.Tasks.Profile.Fprof
|
||||
@moduletag apps: [:sample]
|
||||
|
||||
test "profiles evaluated expression", context do
|
||||
in_tmp(context.test, fn ->
|
||||
|
||||
@@ -5,8 +5,6 @@ defmodule Mix.Tasks.RunTest do
|
||||
|
||||
import ExUnit.CaptureIO
|
||||
|
||||
@moduletag apps: [:sample]
|
||||
|
||||
setup do
|
||||
Mix.Project.push(MixTest.Case.Sample)
|
||||
end
|
||||
|
||||
@@ -3,8 +3,6 @@ Code.require_file("../test_helper.exs", __DIR__)
|
||||
defmodule Mix.UmbrellaTest do
|
||||
use MixTest.Case
|
||||
|
||||
@moduletag apps: [:foo, :bar]
|
||||
|
||||
test "apps_paths" do
|
||||
in_fixture("umbrella_dep/deps/umbrella", fn ->
|
||||
assert Mix.Project.apps_paths() == nil
|
||||
|
||||
@@ -2,6 +2,9 @@ Mix.start()
|
||||
Mix.shell(Mix.Shell.Process)
|
||||
Application.put_env(:mix, :colors, enabled: false)
|
||||
|
||||
Logger.remove_backend(:console)
|
||||
Application.put_env(:logger, :backends, [])
|
||||
|
||||
exclude = if match?({:win32, _}, :os.type()), do: [unix: true], else: [windows: true]
|
||||
ExUnit.start(trace: "--trace" in System.argv(), exclude: exclude)
|
||||
|
||||
@@ -32,12 +35,9 @@ defmodule MixTest.Case do
|
||||
end
|
||||
end
|
||||
|
||||
setup config do
|
||||
if apps = config[:apps] do
|
||||
Logger.remove_backend(:console)
|
||||
Application.put_env(:logger, :backends, [])
|
||||
end
|
||||
@apps Enum.map(Application.loaded_applications(), &elem(&1, 0))
|
||||
|
||||
setup do
|
||||
on_exit(fn ->
|
||||
Application.start(:logger)
|
||||
Mix.env(:dev)
|
||||
@@ -48,14 +48,9 @@ defmodule MixTest.Case do
|
||||
Mix.ProjectStack.clear_stack()
|
||||
delete_tmp_paths()
|
||||
|
||||
if apps do
|
||||
for app <- apps do
|
||||
Application.stop(app)
|
||||
Application.unload(app)
|
||||
end
|
||||
|
||||
Logger.add_backend(:console, flush: true)
|
||||
Application.put_env(:logger, :backends, [:console])
|
||||
for {app, _, _} <- Application.loaded_applications(), app not in @apps do
|
||||
Application.stop(app)
|
||||
Application.unload(app)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user