Compare commits

...
Author SHA1 Message Date
José Valim b6d7769674 Release v1.7.0-rc.1 2018-07-19 12:09:05 +02:00
José Valim dc3a56c44f Remove leftover spaces
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:40:45 +02:00
Callum Dempsey Leach ea9cb84eb1 Clarify Application.get_env by illustrating a use case (#7929)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:40:41 +02:00
José Valim b7b7282a22 Optimize metadata merging and ensure no nil leakage (#7927)
Closes #7926

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:40:32 +02:00
José Valim d3d1833d47 Properly populate top_level field of deps (#7931)
Closes #7930

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:40:26 +02:00
Gary Rennie 7d427719fe Fix nested use of Mix.Config.eval!/2 (#7925)
Previously, if a config file uses Mix.Config.eval!/2 then it would fail with the
following error:

 > ** (RuntimeError) could not set configuration via Mix.Config. This usually
 >  means you are trying to execute a configuration file directly instead of
 > using the proper command, such as mix loadconfig
 > code: assert Mix.Config.eval!(fixture_path("configs/nested_import.exs")) ==
 > stacktrace:
 >   (mix) lib/mix/config.ex:71: Mix.Config.raise_improper_use!/0
 >   (mix) lib/mix/config.ex:222: Mix.Config.eval!/2
 >   lib/mix/test/mix/config_test.exs:110: (test)

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:40:17 +02:00
Tobiasz Małecki 9812b74a2c Added missing @doc :since metadata (#7922)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:40:01 +02:00
Tobiasz Małecki aebc7e2fe1 Fixed indentation in StringIO.open/3 examples (#7920)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:39:57 +02:00
Fernando Tapia Rico f0aeb7136f Use "time zone" instead of "timezone" everywhere (#7917)
There is a mix of "timezone" and "time zone" in the codebase. For what I read, "time zone" is usually more correct.

In addition, there are some variables and types named `time_zone`, so I think the best option is to go with "time zone".

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:39:50 +02:00
Tobiasz Małecki d92a450637 fixed typo in float moduledoc (#7915)
[ci skip]

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:39:44 +02:00
Andrea Leopardi afb4667cd0 Add an additional example to the docs for String.jaro_distance/1
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:39:39 +02:00
Fernando Tapia Rico eb50a09679 Clarify documentation of @compile :inline flag (#7909)
[ci skip]

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:39:30 +02:00
Henrik Larsson 2f8ecec32c Clarify how to assert on exits from linked processes (#7904)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:39:17 +02:00
Fernando Tapia Rico 4354938168 Remove duplicated sentence from Map's doc (#7907)
[ci skip]

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 19:39:13 +02:00
José Valim b06d82c93e Allow all args on Mix.Dep.loaded
Even though the API was private, developers were abusing it.
So we allow it to work for now until we remove it in future
versions.

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-18 10:36:59 +02:00
Myron Marston 3dbe8a6661 Changelog: explain mix test --failed more accurately. (#7911)
`mix test --failed` runs all tests that failed the last time they ran,
even if they were not included in the last run of the test suite. This
is important, because it means that you can run individual failed tests
to focus on fixing them without worrying about mix losing track of the
other failed tests.
2018-07-16 09:21:54 +02:00
José Valim 6932e25159 Doc fixes 2018-07-15 22:24:56 +02:00
José Valim 22abd6a48e Fix CHANGELOG typo 2018-07-14 14:21:39 +02:00
José Valim 05f5073cd1 Clarify that any metadata is accepted, only some are shown 2018-07-14 11:51:39 +02:00
Tobiasz Małecki 18d96c2fd5 Add Function docs to "Basic Types" group (#7900)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-13 23:45:26 +02:00
Wojtek Mach ea04ec8f81 Clarify how to configure :test_coverage (#7896)
[ci skip]

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-13 23:45:18 +02:00
Wojtek Mach 0a5d633a5e Update --cover docs (#7897)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-13 23:45:05 +02:00
José Valim 7392d736c4 Print checksums headings 2018-07-13 15:17:14 +02:00
José Valim 1164784b8e Release v1.7.0-rc.0 2018-07-13 14:43:27 +02:00
José Valim 6694ddbd2f Properly add parens around when with keywords as argument 2018-07-13 00:07:26 +02:00
José Valim 85a4d55efb Update CHANGELOG 2018-07-12 20:28:19 +02:00
Arkadiusz Gil 9b238e0316 Ignore unknown child info in Logger.Translator (#7892)
This prevents Logger application from crashing when supervisors report
children progress with fields unknown to Logger.Translator.

Closes #7889

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-12 20:15:08 +02:00
László Bácsi ca82388792 Show documentation metadata in IEx (only since and deprecated for now) (#7886) 2018-07-12 20:07:45 +02:00
Lukasz Samson b33dd12d86 Fix error when :trim_bom is used with :encoding
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-12 14:37:14 +02:00
Dimitrios Zorbas c36b2c9070 Fix syntax highlighting of Calendar.ISO docs (#7880)
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2018-07-12 12:44:41 +02:00
José Valim ac75cdbe05 Prepare for v1.7 release 2018-07-12 11:57:29 +02:00
40 changed files with 480 additions and 137 deletions
+33 -2
View File
@@ -2,6 +2,21 @@
Elixir v1.7 is the last release to support Erlang/OTP 19. We recommend everyone to migrate to Erlang/OTP 20+.
## Documentation metadata
Elixir v1.7 implements [EEP 48](http://erlang.org/eep/eeps/eep-0048.html). EEP 48 aims to bring documentation interoperability across all languages running on the Erlang VM. The documentation format proposed by EEP 48 also supports metadata, which is now fully exposed to Elixir developers:
```elixir
@moduledoc "A brand new module"
@moduledoc authors: ["Jane", "Mary"], since: "1.4.0"
```
Passing metadata is supported on `@doc`, `@moduledoc` and `@typedoc`.
To access the new documentation format, developers should use `Code.fetch_docs/1`. The old documentation format is no longer available and the old `Code.get_docs/2` function will return `nil` accordingly.
Tools like IEx and ExDoc have been updated to leverage the new format and show relevant metadata to users. While Elixir allows any metadata to be given, those tools currently exhibit only `:deprecated` and `:since`. Other keys may be shown in the future.
## The `__STACKTRACE__` construct
Erlang/OTP 21.0 introduces a new way to retrieve the stacktrace that is lexically scoped and no longer relies on side-effects like `System.stacktrace/0` does. Before one would write:
@@ -81,7 +96,7 @@ ExUnit has also seen its own share of improvements. Assertions such as `assert s
Furthermore, failures in doctests are now colored and diffed.
On the `mix test` side of things, there is a new `--failed` flag that runs all tests that failed in the previous run. Finally, coverage reports generated with `mix test --cover` include a summary out of the box:
On the `mix test` side of things, there is a new `--failed` flag that runs all tests that failed the last time they ran. Finally, coverage reports generated with `mix test --cover` include a summary out of the box:
```
Generating cover results ...
@@ -101,7 +116,20 @@ Percentage | Module
77.19% | Total
```
## v1.7.0-dev
## v1.7.0-rc.1 (2018-07-19)
### 1. Bug fixes
#### Logger
* [Logger] Ensure nil metadata is always pruned
#### Mix
* [Mix] Properly tag which dependencies are `top_level` when processing child dependencies (regression)
* [Mix] Allow calls to `Mix.Config.eval!/2` to be nested (regression)
## v1.7.0-rc.0 (2018-07-13)
### 1. Enhancements
@@ -119,6 +147,7 @@ Percentage | Module
* [Function] Add `Function` module with `capture/3`, `info/1` and `info/2` functions
* [GenServer] Support the new `handle_continue/2` callback on Erlang/OTP 21+
* [IO.ANSI] Add cursor movement to `IO.ANSI`
* [Kernel] Support adding arbitrary documentation metadata by passing a keyword list to `@doc`, `@moduledoc` and `@typedoc`
* [Kernel] Introduce `__STACKTRACE__` to retrieve the current stacktrace inside `catch`/`rescue` (this will be a requirement for Erlang/OTP 21+)
* [Kernel] Raise on unsafe variables in order to allow us to better track unused variables
* [Kernel] Warn when using `length` to check if a list is not empty on guards
@@ -146,6 +175,7 @@ Percentage | Module
* [IEx.Helpers] Add `use_if_available/2`
* [IEx.Helpers] Allow `force: true` option in `recompile/1`
* [IEx.Helpers] Add `:allocators` pane to `runtime_info/1`
* [IEx.Helpers] Show documentation metadata in `h/1` helpers
#### Logger
@@ -179,6 +209,7 @@ Percentage | Module
* [Code] Ensure `string_to_quoted` returns error tuples instead of raising in certain constructs
* [Code.Formatter] Consistently format keyword lists in function calls with and without parens
* [Code.Formatter] Do not break after `->` when there are only comments and one-line clauses
* [File] Allow the `:trim_bom` option to be used with `:encoding`
* [Kernel] Raise on unsafe variables as some of the code emitted with unsafe variables would not correctly propagate variables or would disable tail call optimization semantics
* [Kernel] Do not crash on dynamic sizes in binary generators with collectable into in comprehensions
* [Kernel] Do not crash on literals with non-unary size in binary generators with collectable into in comprehensions
+9 -1
View File
@@ -1,6 +1,6 @@
PREFIX ?= /usr/local
SHARE_PREFIX ?= $(PREFIX)/share
CANONICAL := master/
CANONICAL := v1.7/
ELIXIRC := bin/elixirc --verbose --ignore-module-conflict
ERLC := erlc -I lib/elixir/include
ERL := erl -I lib/elixir/include -noshell -pa lib/elixir/ebin
@@ -192,6 +192,14 @@ Precompiled.zip: build_man compile
@ echo "Precompiled file created $(CURDIR)/Precompiled-v$(VERSION).zip"
zips: Precompiled.zip Docs.zip
@ echo ""
@ echo "## Checksums"
@ echo ""
@ shasum -a 1 < Precompiled-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA1:"
@ shasum -a 512 < Precompiled-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA512:"
@ shasum -a 1 < Docs-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA1:"
@ shasum -a 512 < Docs-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA512:"
@ echo ""
#==> Test tasks
+1 -1
View File
@@ -1 +1 @@
1.7.0-dev
1.7.0-rc.1
+1
View File
@@ -14,6 +14,7 @@
DateTime,
Exception,
Float,
Function,
Integer,
NaiveDateTime,
Record,
+35
View File
@@ -404,6 +404,41 @@ defmodule Application do
If the configuration parameter does not exist, the function returns the
`default` value.
## Examples
`get_env/3` is commonly used to read the configuration of your OTP applications.
Since Mix configurations are commonly used to configure applications, we will use
this as a point of illustration.
Consider a new application `:my_app`. `:my_app` contains a database engine which
supports a pool of databases. The database engine needs to know the configuration for
each of those databases, and that configuration is supplied by key-value pairs in
environment of `:my_app`.
config :my_app, Databases.RepoOne,
# A database configuration
ip: "localhost"
port: 5433
config :my_app, Databases.RepoTwo,
# Another database configuration (for the same OTP app)
ip: "localhost"
port: 20717
config :my_app, my_app_databases: [Databases.RepoOne, Databases.RepoTwo]
Our database engine used by `:my_app` needs to know what databases exist, and
what the database configurations are. The database engine can make a call to
`get_env(:my_app, :my_app_databases)` to retrieve the list of databases (specified
by module names). Our database engine can then traverse each repository in the
list and then call `get_env(:my_app, Databases.RepoOne)` and so forth to retrieve
the configuration of each one.
**Important:** if you are writing a library to be used by other developers,
it is generally recommended to avoid the application environment, as the
application environment is effectively a global storage. For more information,
read our [library guidelines](/library-guidelines.html).
"""
@spec get_env(app, key, value) :: value
def get_env(app, key, default \\ nil) do
+4 -4
View File
@@ -17,7 +17,7 @@ defmodule DateTime do
Such functions expect `t:Calendar.datetime/0` in their typespecs
(instead of `t:t/0`).
Developers should avoid creating the DateTime struct directly
Developers should avoid creating the `DateTime` struct directly
and instead rely on the functions provided by this module as
well as the ones in 3rd party calendar libraries.
@@ -25,12 +25,12 @@ defmodule DateTime do
You will notice this module only contains conversion
functions as well as functions that work on UTC. This
is because a proper DateTime implementation requires a
TimeZone database which currently is not provided as part
is because a proper `DateTime` implementation requires a
time zone database which currently is not provided as part
of Elixir.
Such may be addressed in upcoming versions, meanwhile,
use 3rd party packages to provide DateTime building and
use 3rd party packages to provide `DateTime` building and
similar functionality with time zone backing.
"""
+32 -32
View File
@@ -351,12 +351,12 @@ defmodule Calendar.ISO do
## Examples
iex> Calendar.ISO.date_to_string(2015, 2, 28)
"2015-02-28"
iex> Calendar.ISO.date_to_string(2017, 8, 1)
"2017-08-01"
iex> Calendar.ISO.date_to_string(-99, 1, 31)
"-0099-01-31"
iex> Calendar.ISO.date_to_string(2015, 2, 28)
"2015-02-28"
iex> Calendar.ISO.date_to_string(2017, 8, 1)
"2017-08-01"
iex> Calendar.ISO.date_to_string(-99, 1, 31)
"-0099-01-31"
"""
@spec date_to_string(year, month, day) :: String.t()
@@ -378,10 +378,10 @@ defmodule Calendar.ISO do
## Examples
iex> Calendar.ISO.naive_datetime_to_string(2015, 2, 28, 1, 2, 3, {4, 6})
"2015-02-28 01:02:03.000004"
iex> Calendar.ISO.naive_datetime_to_string(2017, 8, 1, 1, 2, 3, {4, 5})
"2017-08-01 01:02:03.00000"
iex> Calendar.ISO.naive_datetime_to_string(2015, 2, 28, 1, 2, 3, {4, 6})
"2015-02-28 01:02:03.000004"
iex> Calendar.ISO.naive_datetime_to_string(2017, 8, 1, 1, 2, 3, {4, 5})
"2017-08-01 01:02:03.00000"
"""
@impl true
@@ -403,14 +403,14 @@ defmodule Calendar.ISO do
## Examples
iex> Calendar.ISO.datetime_to_string(2017, 8, 1, 1, 2, 3, {4, 5}, "Europe/Berlin", "CET", 3600, 0)
"2017-08-01 01:02:03.00000+01:00 CET Europe/Berlin"
iex> Calendar.ISO.datetime_to_string(2017, 8, 1, 1, 2, 3, {4, 5}, "Europe/Berlin", "CDT", 3600, 3600)
"2017-08-01 01:02:03.00000+02:00 CDT Europe/Berlin"
iex> Calendar.ISO.datetime_to_string(2015, 2, 28, 1, 2, 3, {4, 5}, "America/Los_Angeles", "PST", -28800, 0)
"2015-02-28 01:02:03.00000-08:00 PST America/Los_Angeles"
iex> Calendar.ISO.datetime_to_string(2015, 2, 28, 1, 2, 3, {4, 5}, "America/Los_Angeles", "PDT", -28800, 3600)
"2015-02-28 01:02:03.00000-07:00 PDT America/Los_Angeles"
iex> Calendar.ISO.datetime_to_string(2017, 8, 1, 1, 2, 3, {4, 5}, "Europe/Berlin", "CET", 3600, 0)
"2017-08-01 01:02:03.00000+01:00 CET Europe/Berlin"
iex> Calendar.ISO.datetime_to_string(2017, 8, 1, 1, 2, 3, {4, 5}, "Europe/Berlin", "CDT", 3600, 3600)
"2017-08-01 01:02:03.00000+02:00 CDT Europe/Berlin"
iex> Calendar.ISO.datetime_to_string(2015, 2, 28, 1, 2, 3, {4, 5}, "America/Los_Angeles", "PST", -28800, 0)
"2015-02-28 01:02:03.00000-08:00 PST America/Los_Angeles"
iex> Calendar.ISO.datetime_to_string(2015, 2, 28, 1, 2, 3, {4, 5}, "America/Los_Angeles", "PDT", -28800, 3600)
"2015-02-28 01:02:03.00000-07:00 PDT America/Los_Angeles"
"""
@impl true
@@ -452,14 +452,14 @@ defmodule Calendar.ISO do
## Examples
iex> Calendar.ISO.valid_date?(2015, 2, 28)
true
iex> Calendar.ISO.valid_date?(2015, 2, 30)
false
iex> Calendar.ISO.valid_date?(-1, 12, 31)
true
iex> Calendar.ISO.valid_date?(-1, 12, 32)
false
iex> Calendar.ISO.valid_date?(2015, 2, 28)
true
iex> Calendar.ISO.valid_date?(2015, 2, 30)
false
iex> Calendar.ISO.valid_date?(-1, 12, 31)
true
iex> Calendar.ISO.valid_date?(-1, 12, 32)
false
"""
@doc since: "1.5.0"
@@ -476,12 +476,12 @@ defmodule Calendar.ISO do
## Examples
iex> Calendar.ISO.valid_time?(10, 50, 25, {3006, 6})
true
iex> Calendar.ISO.valid_time?(23, 59, 60, {0, 0})
true
iex> Calendar.ISO.valid_time?(24, 0, 0, {0, 0})
false
iex> Calendar.ISO.valid_time?(10, 50, 25, {3006, 6})
true
iex> Calendar.ISO.valid_time?(23, 59, 60, {0, 0})
true
iex> Calendar.ISO.valid_time?(24, 0, 0, {0, 0})
false
"""
@doc since: "1.5.0"
+1 -1
View File
@@ -412,7 +412,7 @@ defmodule NaiveDateTime do
Parses the extended "Date and time of day" format described by
[ISO 8601:2004](https://en.wikipedia.org/wiki/ISO_8601).
Timezone offset may be included in the string but they will be
Time zone offset may be included in the string but they will be
simply discarded as such information is not included in naive date
times.
+1 -1
View File
@@ -177,7 +177,7 @@ defmodule Time do
Parses the extended "Local time" format described by
[ISO 8601:2004](https://en.wikipedia.org/wiki/ISO_8601).
Timezone offset may be included in the string but they will be
Time zone offset may be included in the string but they will be
simply discarded as such information is not included in times.
As specified in the standard, the separator "T" may be omitted if
+15 -8
View File
@@ -716,14 +716,21 @@ defmodule Code.Formatter do
{concat(op_string, doc), @empty, newlines, state}
end
operand_to_algebra_with_comments(
operands,
meta,
min_line,
max_line,
state,
operand_to_algebra
)
{doc, state} =
operand_to_algebra_with_comments(
operands,
meta,
min_line,
max_line,
state,
operand_to_algebra
)
if keyword?(right_arg) and context in [:parens_arg, :no_parens_arg] do
{wrap_in_parens(doc), state}
else
{doc, state}
end
end
defp binary_op_to_algebra(op, _, meta, left_arg, right_arg, context, state, _nesting)
+5 -1
View File
@@ -1512,7 +1512,8 @@ defmodule File do
in raw mode for performance reasons. Therefore, Elixir **will** open
streams in `:raw` mode with the `:read_ahead` option unless an encoding
is specified. This means any data streamed into the file must be
converted to `t:iodata/0` type. If you pass `[:utf8]` in the modes parameter,
converted to `t:iodata/0` type. If you pass e.g. `[encoding: :utf8]`
or `[encoding: {:utf16, :little}]` in the modes parameter,
the underlying stream will use `IO.write/2` and the `String.Chars` protocol
to convert the data. See `IO.binwrite/2` and `IO.write/2` .
@@ -1524,6 +1525,9 @@ defmodule File do
If you pass `:trim_bom` in the modes parameter, the stream will
trim UTF-8, UTF-16 and UTF-32 byte order marks when reading from file.
Note that this function does not try to discover the file encoding basing
on BOM.
## Examples
# Read in 2048 byte chunks rather than lines
+15 -3
View File
@@ -140,12 +140,24 @@ defmodule File.Stream do
end
end
defp trim_bom(device, raw) do
header = if raw, do: IO.binread(device, 4), else: IO.read(device, 1)
{:ok, new_pos} = :file.position(device, bom_length(header))
defp trim_bom(device, true) do
bom_length = device |> IO.binread(4) |> bom_length()
{:ok, new_pos} = :file.position(device, bom_length)
{device, new_pos}
end
defp trim_bom(device, false) do
# Or we read the bom in the correct amount or it isn't there
case bom_length(IO.read(device, 1)) do
0 ->
{:ok, _} = :file.position(device, 0)
{device, 0}
_ ->
{device, 1}
end
end
defp bom_length(<<239, 187, 191, _rest::binary>>), do: 3
defp bom_length(<<254, 255, _rest::binary>>), do: 2
defp bom_length(<<255, 254, _rest::binary>>), do: 2
+1 -1
View File
@@ -33,7 +33,7 @@ defmodule Float do
There are also other known problems like flooring or rounding numbers. See
`round/2` and `floor/2` for more details about them.
To learn more about floting-point arithmetic visit:
To learn more about floating-point arithmetic visit:
* [0.30000000000000004.com](http://0.30000000000000004.com/)
* [What Every Programmer Should Know About Floating-Point Arithmetic](http://floating-point-gui.de/)
+36 -1
View File
@@ -7,12 +7,13 @@ defmodule IO.ANSI.Docs do
@doc """
The default options used by this module.
The supported values are:
The supported keys are:
* `:enabled` - toggles coloring on and off (true)
* `:doc_bold` - bold text (bright)
* `:doc_code` - code blocks (cyan)
* `:doc_headings` - h1, h2, h3, h4, h5, h6 headings (yellow)
* `:doc_metadata` - documentation metadata keys (yellow)
* `:doc_inline_code` - inline code (cyan)
* `:doc_table_heading` - the style for table headings
* `:doc_title` - top level heading (reverse, yellow)
@@ -29,6 +30,7 @@ defmodule IO.ANSI.Docs do
doc_bold: [:bright],
doc_code: [:cyan],
doc_headings: [:yellow],
doc_metadata: [:yellow],
doc_inline_code: [:cyan],
doc_table_heading: [:reverse],
doc_title: [:reverse, :yellow],
@@ -53,6 +55,39 @@ defmodule IO.ANSI.Docs do
newline_after_block()
end
@doc """
Prints documentation metadata (only `since` and `deprecated` for now).
See `default_options/0` for docs on the supported options.
"""
@spec print_metadata(map, keyword) :: :ok
def print_metadata(metadata, options \\ []) when is_map(metadata) do
options = Keyword.merge(default_options(), options)
print_each_metadata(metadata, options) && IO.write("\n")
end
@metadata_filter [:deprecated, :since]
defp print_each_metadata(metadata, options) do
Enum.reduce(metadata, false, fn
{key, value}, _printed when is_binary(value) and key in @metadata_filter ->
label = metadata_label(key, options)
indent = String.duplicate(" ", length_without_escape(label, 0) + 1)
write_with_wrap([label | String.split(value, @spaces)], options[:width], indent, true)
_metadata, printed ->
printed
end)
end
defp metadata_label(key, options) do
if options[:enabled] do
"#{color(:doc_metadata, options)}#{key}:#{IO.ANSI.reset()}"
else
"#{key}:"
end
end
@doc """
Prints the documentation body.
+3 -3
View File
@@ -27,7 +27,7 @@ defmodule Kernel do
If you don't want to import a function or macro from `Kernel`, use the `:except`
option and then list the function/macro by arity:
import Kernel, except: [if: 2, unless: 2]
import Kernel, except: [if: 2, unless: 2]
See `Kernel.SpecialForms.import/2` for more information on importing.
@@ -70,10 +70,10 @@ defmodule Kernel do
listed above. Some of them are:
* `Date` - `year-month-day` structs in a given calendar
* `DateTime` - date and time with timezone in a given calendar
* `DateTime` - date and time with time zone in a given calendar
* `Exception` - data raised from errors and unexpected scenarios
* `MapSet` - unordered collections of unique elements
* `NaiveDateTime` - date and time without timezone in a given calendar
* `NaiveDateTime` - date and time without time zone in a given calendar
* `Keyword` - lists of two-element tuples, often representing optional values
* `Range` - inclusive ranges between two integers
* `Regex` - regular expressions
-1
View File
@@ -506,7 +506,6 @@ defmodule Map do
iex> Map.delete(%{b: 2}, :a)
%{b: 2}
Inlined by the compiler.
"""
@spec delete(map, key) :: map
def delete(map, key), do: :maps.remove(key, map)
+2 -1
View File
@@ -466,7 +466,8 @@ defmodule Module do
of the corresponding setting in `Code.compiler_options/1`
* `@compile {:inline, some_fun: 2, other_fun: 3}` - inlines the given
name/arity pairs
name/arity pairs. Inlining is applied locally, calls from another
module are not affected by this option
* `@compile {:autoload, false}` - disables automatic loading of
modules after compilation. Instead, the module will be loaded after
+2
View File
@@ -2240,6 +2240,8 @@ defmodule String do
0.8222222222222223
iex> String.jaro_distance("even", "odd")
0.0
iex> String.jaro_distance("same", "same")
1.0
"""
@spec jaro_distance(t, t) :: float
+13 -12
View File
@@ -31,21 +31,22 @@ defmodule StringIO do
## Examples
iex> StringIO.open("foo", [], fn(pid) ->
...> input = IO.gets(pid, ">")
...> IO.write(pid, "The input was #{input}")
...> StringIO.contents(pid)
...> end)
{:ok, {"", "The input was foo"}}
iex> StringIO.open("foo", [], fn(pid) ->
...> input = IO.gets(pid, ">")
...> IO.write(pid, "The input was #{input}")
...> StringIO.contents(pid)
...> end)
{:ok, {"", "The input was foo"}}
iex> StringIO.open("foo", [capture_prompt: true], fn(pid) ->
...> input = IO.gets(pid, ">")
...> IO.write(pid, "The input was #{input}")
...> StringIO.contents(pid)
...> end)
{:ok, {"", ">The input was foo"}}
iex> StringIO.open("foo", [capture_prompt: true], fn(pid) ->
...> input = IO.gets(pid, ">")
...> IO.write(pid, "The input was #{input}")
...> StringIO.contents(pid)
...> end)
{:ok, {"", ">The input was foo"}}
"""
@doc since: "1.7.0"
@spec open(binary, keyword, (pid -> res)) :: {:ok, res} when res: var
def open(string, options, function)
when is_binary(string) and is_list(options) and is_function(function, 1) do
+1 -1
View File
@@ -6,7 +6,7 @@ defmodule Tuple do
* `elem/2` - access a tuple by index
* `put_elem/3` - insert a value into a tuple by index
* `tuple_size/3` - get the number of elements in a tuple
* `tuple_size/1` - get the number of elements in a tuple
Tuples are intended as fixed-size containers for multiple elements.
To manipulate a collection of elements, use a list instead. `Enum`
@@ -136,4 +136,4 @@ Non-map as second argument in `URI.decode_query/2` | [v1.3] | Use a map (v1
[v1.4]: https://github.com/elixir-lang/elixir/blob/v1.4/CHANGELOG.md#4-deprecations
[v1.5]: https://github.com/elixir-lang/elixir/blob/v1.5/CHANGELOG.md#4-deprecations
[v1.6]: https://github.com/elixir-lang/elixir/blob/v1.6/CHANGELOG.md#4-deprecations
[v1.7]: https://github.com/elixir-lang/elixir/blob/master/CHANGELOG.md#4-hard-deprecations
[v1.7]: https://github.com/elixir-lang/elixir/blob/v1.7/CHANGELOG.md#4-hard-deprecations
@@ -447,6 +447,20 @@ defmodule Code.Formatter.IntegrationTest do
"""
end
test "when with keywords inside call" do
assert_same """
quote((bar(foo(1)) when bat: foo(1)), [])
"""
assert_same """
quote(do: (bar(foo(1)) when bat: foo(1)), line: 1)
"""
assert_same """
typespec(quote(do: (bar(foo(1)) when bat: foo(1))), [foo: 1], [])
"""
end
test "capture with operators" do
assert_same """
"this works" |> (&String.upcase/1) |> (&String.downcase/1)
+44 -4
View File
@@ -1569,11 +1569,11 @@ defmodule FileTest do
src = fixture_path("utf8_bom.txt")
assert src
|> File.stream!([:utf8])
|> File.stream!([{:encoding, :utf8}])
|> Enum.take(1) == [<<239, 187, 191>> <> "Русский\n"]
assert src
|> File.stream!([:utf8], 1)
|> File.stream!([{:encoding, :utf8}], 1)
|> Enum.take(9) == ["\uFEFF", "Р", "у", "с", "с", "к", "и", "й", "\n"]
end
@@ -1581,11 +1581,51 @@ defmodule FileTest do
src = fixture_path("utf8_bom.txt")
assert src
|> File.stream!([:utf8, :trim_bom])
|> File.stream!([{:encoding, :utf8}, :trim_bom])
|> Enum.take(1) == ["Русский\n"]
assert src
|> File.stream!([:utf8, :trim_bom], 1)
|> File.stream!([{:encoding, :utf8}, :trim_bom], 1)
|> Enum.take(8) == ["Р", "у", "с", "с", "к", "и", "й", "\n"]
end
test "keeps BOM with UTF16 BE" do
src = fixture_path("utf16_be_bom.txt")
assert src
|> File.stream!([{:encoding, {:utf16, :big}}])
|> Enum.take(1) == ["\uFEFFРусский\n"]
end
test "keeps BOM with UTF16 LE" do
src = fixture_path("utf16_le_bom.txt")
assert src
|> File.stream!([{:encoding, {:utf16, :little}}])
|> Enum.take(1) == ["\uFEFFРусский\n"]
end
test "trims BOM via option with utf16 BE encoding" do
src = fixture_path("utf16_be_bom.txt")
assert src
|> File.stream!([{:encoding, {:utf16, :big}}, :trim_bom])
|> Enum.take(1) == ["Русский\n"]
assert src
|> File.stream!([{:encoding, {:utf16, :big}}, :trim_bom], 1)
|> Enum.take(8) == ["Р", "у", "с", "с", "к", "и", "й", "\n"]
end
test "trims BOM via option with utf16 LE encoding" do
src = fixture_path("utf16_le_bom.txt")
assert src
|> File.stream!([{:encoding, {:utf16, :little}}, :trim_bom])
|> Enum.take(1) == ["Русский\n"]
assert src
|> File.stream!([{:encoding, {:utf16, :little}}, :trim_bom], 1)
|> Enum.take(8) == ["Р", "у", "с", "с", "к", "и", "й", "\n"]
end
Binary file not shown.
Binary file not shown.
@@ -8,6 +8,10 @@ defmodule IO.ANSI.DocsTest do
capture_io(fn -> IO.ANSI.Docs.print_heading(str, []) end) |> String.trim_trailing()
end
def format_metadata(map) do
capture_io(fn -> IO.ANSI.Docs.print_metadata(map, []) end)
end
def format(str) do
capture_io(fn -> IO.ANSI.Docs.print(str, []) end) |> String.trim_trailing()
end
@@ -19,6 +23,12 @@ defmodule IO.ANSI.DocsTest do
assert String.contains?(result, " wibble ")
end
test "metadata is formatted" do
result = format_metadata(%{since: "1.2.3", deprecated: "Use that other one", author: "Alice"})
assert result == "\e[33mdeprecated:\e[0m Use that other one\n\e[33msince:\e[0m 1.2.3\n\n"
assert format_metadata(%{author: "Alice"}) == ""
end
test "first level heading is converted" do
result = format("# wibble\n\ntext\n")
assert result == "\e[33m# wibble\e[0m\n\e[0m\ntext\n\e[0m"
+11 -1
View File
@@ -745,6 +745,7 @@ defmodule ExUnit.Assertions do
@doc """
Asserts `expression` will throw a value.
Returns the thrown value or fails otherwise.
## Examples
@@ -758,11 +759,19 @@ defmodule ExUnit.Assertions do
@doc """
Asserts `expression` will exit.
Returns the exit status/message or fails otherwise.
Returns the exit status/message of the current process or fails otherwise.
## Examples
assert catch_exit(exit 1) == 1
To assert exits from linked processes started from the test, trap exits
with `Process.flag/2` and assert the exit message with `assert_received/2`.
Process.flag(:trap_exit, true)
pid = spawn_link(fn -> Process.exit(self(), :normal) end)
assert_receive {:EXIT, ^pid, :normal}
"""
defmacro catch_exit(expression) do
@@ -771,6 +780,7 @@ defmodule ExUnit.Assertions do
@doc """
Asserts `expression` will cause an error.
Returns the error or fails otherwise.
## Examples
+1 -1
View File
@@ -338,7 +338,7 @@ defimpl IEx.Info, for: [Date, Time, NaiveDateTime] do
case @for do
Date -> {"D", "date"}
Time -> {"T", "time"}
NaiveDateTime -> {"N", ~S{"naive" datetime (that is, a datetime without a timezone)}}
NaiveDateTime -> {"N", ~S{"naive" datetime (that is, a datetime without a time zone)}}
end
def info(value) do
+25 -21
View File
@@ -250,8 +250,8 @@ defmodule IEx.Introspection do
case Code.ensure_loaded(module) do
{:module, _} ->
case Code.fetch_docs(module) do
{:docs_v1, _, _, _, %{} = doc, _, _} ->
print_doc(inspect(module), [], doc)
{:docs_v1, _, _, _, %{} = doc, metadata, _} ->
print_doc(inspect(module), [], doc, metadata)
{:docs_v1, _, _, _, _, _, _} ->
docs_not_found(inspect(module))
@@ -376,7 +376,7 @@ defmodule IEx.Introspection do
is_nil(docs) and spec != [] ->
message = %{"en" => "Module was compiled without docs. Showing only specs."}
print_doc("#{inspect(mod)}.#{fun}/#{arity}", spec, message)
print_doc("#{inspect(mod)}.#{fun}/#{arity}", spec, message, %{})
:ok
is_nil(docs) ->
@@ -449,7 +449,7 @@ defmodule IEx.Introspection do
defp has_content?({{_, name, _}, _, _, :none, _}), do: hd(Atom.to_charlist(name)) != ?_
defp has_content?({_, _, _, _, _}), do: true
defp print_fun(mod, {{kind, fun, arity}, _line, signature, doc, _meta}, spec) do
defp print_fun(mod, {{kind, fun, arity}, _line, signature, doc, metadata}, spec) do
if callback_module = doc == :none and callback_module(mod, fun, arity) do
filter = &match?({_, ^fun, ^arity}, elem(&1, 0))
@@ -458,7 +458,7 @@ defmodule IEx.Introspection do
_ -> nil
end
else
print_doc("#{kind_to_def(kind)} #{Enum.join(signature, " ")}", spec, doc)
print_doc("#{kind_to_def(kind)} #{Enum.join(signature, " ")}", spec, doc, metadata)
end
end
@@ -513,7 +513,7 @@ defmodule IEx.Introspection do
{:ok, docs} ->
docs
|> add_optional_callback_docs(mod)
|> Enum.each(fn {definition, _} -> IO.puts(definition) end)
|> Enum.each(fn {definition, _, _} -> IO.puts(definition) end)
end
dont_display_result()
@@ -565,12 +565,12 @@ defmodule IEx.Introspection do
docs
|> Enum.filter(filter)
|> Enum.map(fn
{{:macrocallback, fun, arity}, _, _, doc, _} ->
{{:macrocallback, fun, arity}, _, _, doc, metadata} ->
macro = {:"MACRO-#{fun}", arity + 1}
{format_callback(:macrocallback, fun, macro, callbacks), doc}
{format_callback(:macrocallback, fun, macro, callbacks), doc, metadata}
{{kind, fun, arity}, _, _, doc, _} ->
{format_callback(kind, fun, {fun, arity}, callbacks), doc}
{{kind, fun, arity}, _, _, doc, metadata} ->
{format_callback(kind, fun, {fun, arity}, callbacks), doc, metadata}
end)
{:ok, docs}
@@ -588,7 +588,7 @@ defmodule IEx.Introspection do
if optional_callbacks == [] do
docs
else
docs ++ [{format_optional_callbacks(optional_callbacks), ""}]
docs ++ [{format_optional_callbacks(optional_callbacks), "", %{}}]
end
end
@@ -637,8 +637,8 @@ defmodule IEx.Introspection do
{:ok, types} ->
printed =
for {_, {^type, _, args}} = typespec <- types do
doc = {format_type(typespec), type_doc(module, type, length(args))}
print_typespec(doc)
type_doc(module, type, length(args), typespec)
|> print_typespec()
end
if printed == [] do
@@ -657,8 +657,8 @@ defmodule IEx.Introspection do
{:ok, types} ->
printed =
for {_, {^type, _, args}} = typespec <- types, length(args) == arity do
doc = {format_type(typespec), type_doc(module, type, arity)}
print_typespec(doc)
type_doc(module, type, arity, typespec)
|> print_typespec()
end
if printed == [] do
@@ -674,12 +674,12 @@ defmodule IEx.Introspection do
dont_display_result()
end
defp type_doc(module, type, arity) do
defp type_doc(module, type, arity, typespec) do
if docs = get_docs(module, [:type]) do
{_, _, _, content, _} = Enum.find(docs, &match?({:type, ^type, ^arity}, elem(&1, 0)))
content
{_, _, _, content, metadata} = Enum.find(docs, &match?({:type, ^type, ^arity}, elem(&1, 0)))
{format_type(typespec), content, metadata}
else
:none
{format_type(typespec), :none, %{}}
end
end
@@ -717,27 +717,31 @@ defmodule IEx.Introspection do
IEx.color(:doc_inline_code, left) <> " " <> right
end
defp print_doc(heading, types, doc) do
defp print_doc(heading, types, doc, metadata) do
doc = translate_doc(doc) || ""
if opts = IEx.Config.ansi_docs() do
IO.ANSI.Docs.print_heading(heading, opts)
IO.write(types)
IO.ANSI.Docs.print_metadata(metadata, opts)
IO.ANSI.Docs.print(doc, opts)
else
IO.puts("* #{heading}\n")
IO.write(types)
IO.ANSI.Docs.print_metadata(metadata, enabled: false)
IO.puts(doc)
end
end
defp print_typespec({types, doc}) do
defp print_typespec({types, doc, metadata}) do
IO.puts(types)
doc = translate_doc(doc)
if opts = IEx.Config.ansi_docs() do
IO.ANSI.Docs.print_metadata(metadata, opts)
doc && IO.ANSI.Docs.print(doc, opts)
else
IO.ANSI.Docs.print_metadata(metadata, enabled: false)
doc && IO.puts(doc)
end
end
+80
View File
@@ -403,6 +403,38 @@ defmodule IEx.HelpersTest do
"No documentation for Kernel.__info__ was found\n"
end
test "prints documentation metadata" do
content = """
defmodule Sample do
@moduledoc "Sample module"
@moduledoc deprecated: "Use OtherSample", since: "1.2.3", authors: ["Alice", "Bob"]
@doc "With metadata"
@doc since: "1.2.3", author: "Alice"
@deprecated "Use OtherSample.with_metadata/0"
def with_metadata(), do: 0
@doc "Without metadata"
def without_metadata(), do: 1
end
"""
filename = "sample.ex"
with_file(filename, content, fn ->
assert c(filename, ".") == [Sample]
assert capture_io(fn -> h(Sample) end) ==
"* Sample\n\ndeprecated: Use OtherSample\nsince: 1.2.3\n\nSample module\n"
assert capture_io(fn -> h(Sample.with_metadata()) end) ==
"* def with_metadata()\n\ndeprecated: Use OtherSample.with_metadata/0\nsince: 1.2.3\n\nWith metadata\n"
assert capture_io(fn -> h(Sample.without_metadata()) end) ==
"* def without_metadata()\n\nWithout metadata\n"
end)
after
cleanup_modules([Sample])
end
test "considers underscored functions without docs by default" do
content = """
defmodule Sample do
@@ -593,6 +625,27 @@ defmodule IEx.HelpersTest do
"@callback message(t()) :: String.t()\n\n"
end
test "prints callback documentation metadata" do
filename = "callback_with_metadata.ex"
content = """
defmodule CallbackWithMetadata do
@doc "callback"
@doc since: "1.2.3", deprecated: "Use handle_test/1", purpose: :test
@callback test(:foo) :: integer
end
"""
with_file(filename, content, fn ->
assert c(filename, ".") == [CallbackWithMetadata]
assert capture_io(fn -> b(CallbackWithMetadata.test()) end) ==
"@callback test(:foo) :: integer()\n\ndeprecated: Use handle_test/1\nsince: 1.2.3\n\ncallback\n"
end)
after
cleanup_modules([CallbackWithMetadata])
end
test "prints optional callback" do
filename = "optional_callbacks.ex"
@@ -666,6 +719,33 @@ defmodule IEx.HelpersTest do
after
cleanup_modules([TypeSample])
end
test "prints type documentation metadata" do
content = """
defmodule TypeSample do
@typedoc "An id with description."
@typedoc since: "1.2.3", deprecated: "Use t/0", purpose: :test
@type id_with_desc :: {number, String.t}
end
"""
filename = "typesample.ex"
with_file(filename, content, fn ->
assert c(filename, ".") == [TypeSample]
assert capture_io(fn -> t(TypeSample.id_with_desc()) end) == """
@type id_with_desc() :: {number(), String.t()}
deprecated: Use t/0
since: 1.2.3
An id with description.
"""
end)
after
cleanup_modules([TypeSample])
end
end
describe "v" do
+1 -1
View File
@@ -194,7 +194,7 @@ defmodule IEx.InfoTest do
assert get_key(info, "Reference modules") == "NaiveDateTime, Calendar, Map"
assert get_key(info, "Description") =~
~S{a "naive" datetime (that is, a datetime without a timezone)}
~S{a "naive" datetime (that is, a datetime without a time zone)}
assert get_key(info, "Description") =~ "`~N`"
end
+19 -11
View File
@@ -416,7 +416,7 @@ defmodule Logger do
@type backend :: :gen_event.handler()
@type message :: IO.chardata() | String.Chars.t()
@type level :: :error | :info | :warn | :debug
@type metadata :: keyword(String.Chars.t())
@type metadata :: keyword()
@levels [:error, :info, :warn, :debug]
@metadata :logger_metadata
@@ -436,17 +436,25 @@ defmodule Logger do
@spec metadata(metadata) :: :ok
def metadata(keyword) do
{enabled?, metadata} = __metadata__()
metadata =
Enum.reduce(keyword, metadata, fn
{key, nil}, acc -> Keyword.delete(acc, key)
{key, val}, acc -> Keyword.put(acc, key, val)
end)
Process.put(@metadata, {enabled?, metadata})
Process.put(@metadata, {enabled?, into_metadata(keyword, metadata)})
:ok
end
defp into_metadata([], metadata), do: metadata
defp into_metadata(keyword, metadata), do: into_metadata(keyword, [], metadata)
defp into_metadata([{key, nil} | keyword], prepend, metadata) do
into_metadata(keyword, prepend, :lists.keydelete(key, 1, metadata))
end
defp into_metadata([{key, _} = pair | keyword], prepend, metadata) do
into_metadata(keyword, [pair | prepend], :lists.keydelete(key, 1, metadata))
end
defp into_metadata([], prepend, metadata) do
prepend ++ metadata
end
@doc """
Reads the current process metadata.
"""
@@ -671,7 +679,7 @@ defmodule Logger do
@doc false
def __do_log__({level, config, pdict}, chardata_or_fun, metadata) when is_list(metadata) do
%{utc_log: utc_log?, truncate: truncate, mode: mode} = config
metadata = [pid: self()] ++ Keyword.merge(pdict, metadata)
metadata = [pid: self()] ++ into_metadata(metadata, pdict)
case normalize_message(chardata_or_fun, metadata) do
{message, metadata} ->
@@ -851,7 +859,7 @@ defmodule Logger do
defp normalize_message(fun, metadata) when is_function(fun, 0) do
case fun.() do
{message, fun_metadata} -> {message, Keyword.merge(metadata, fun_metadata)}
{message, fun_metadata} -> {message, into_metadata(fun_metadata, metadata)}
:skip -> :skip
message -> {message, metadata}
end
+4
View File
@@ -339,6 +339,10 @@ defmodule Logger.Translator do
["\nStart Module: ", inspect(mod) | child_debug(min_level, debug)]
end
defp child_info(_min_level, _child) do
[]
end
defp child_debug(:debug, restart_type: restart, shutdown: shutdown, child_type: type) do
["\nRestart: ", inspect(restart), "\nShutdown: ", inspect(shutdown)] ++
["\nType: ", inspect(type)]
+3 -3
View File
@@ -109,7 +109,7 @@ defmodule LoggerTest do
assert capture_log(fn ->
assert Logger.bare_log(:info, "ok", application: nil, module: LoggerTest) == :ok
end) =~ msg("application= module=LoggerTest [info] ok")
end) =~ msg("module=LoggerTest [info] ok")
end
test "metadata compile-time merge" do
@@ -117,7 +117,7 @@ defmodule LoggerTest do
assert capture_log(fn ->
assert Logger.log(:info, "ok", application: nil, module: CustomTest) == :ok
end) =~ msg("application= module=CustomTest [info] ok")
end) =~ msg("module=CustomTest [info] ok")
end
test "metadata merge when the argument function returns metadata" do
@@ -127,7 +127,7 @@ defmodule LoggerTest do
assert capture_log(fn ->
assert Logger.bare_log(:info, fun, application: nil, module: LoggerTest) == :ok
end) =~ msg("application= module=Function [info] ok")
end) =~ msg("module=Function [info] ok")
end
test "enable/1 and disable/1" do
+14 -13
View File
@@ -47,7 +47,6 @@ defmodule Mix.Config do
defp put_config(value) do
Process.put(@config_key, value)
:ok
end
defp delete_config() do
@@ -60,7 +59,6 @@ defmodule Mix.Config do
defp put_files(value) do
Process.put(@files_key, value)
:ok
end
defp delete_files() do
@@ -215,20 +213,23 @@ defmodule Mix.Config do
It returns a tuple with the configuration and the imported paths.
"""
def eval!(file, imported_paths \\ []) do
put_config([])
put_files(imported_paths)
{eval_config, _} = eval_config!(Path.expand(file))
previous_config = put_config([])
previous_files = put_files(imported_paths)
case get_config!() do
[] when is_list(eval_config) ->
{validate!(eval_config), get_files!()}
try do
{eval_config, _} = eval_config!(Path.expand(file))
pdict_config ->
{pdict_config, get_files!()}
case get_config!() do
[] when is_list(eval_config) ->
{validate!(eval_config), get_files!()}
pdict_config ->
{pdict_config, get_files!()}
end
after
if previous_config, do: put_config(previous_config), else: delete_config()
if previous_files, do: put_files(previous_files), else: delete_files()
end
after
delete_config()
delete_files()
end
@doc false
+8 -5
View File
@@ -123,9 +123,12 @@ defmodule Mix.Dep do
defp load_and_cache(config, _top, bottom, _env) do
{_, deps} = Mix.ProjectStack.read_cache({:cached_deps, bottom})
apps = [Keyword.fetch!(config, :app)]
seen = populate_seen(MapSet.new(), apps)
get_deps(deps, tl(Enum.uniq(get_children(deps, seen, apps))))
app = Keyword.fetch!(config, :app)
top_level = for dep <- deps, dep.app == app, child <- dep.deps, do: child.app
seen = populate_seen(MapSet.new(), [app])
children = get_deps(deps, tl(Enum.uniq(get_children(deps, seen, [app]))))
Enum.map(children, &%{&1 | top_level: &1.app in top_level})
end
defp read_cached_deps(project, env) do
@@ -153,8 +156,8 @@ defmodule Mix.Dep do
# TODO: Remove this on v1.8
@doc false
@deprecated "Mix.Dep.loaded/1 was private API and you should not use it"
def loaded([]) do
load_on_environment([])
def loaded(opts) do
load_on_environment(opts)
end
@doc """
+8 -2
View File
@@ -145,7 +145,7 @@ defmodule Mix.Tasks.Test do
## Command line options
* `--color` - enables color in the output
* `--cover` - the directory to include coverage results
* `--cover` - runs coverage tool. See "Coverage" section below
* `--exclude` - excludes tests that match the filter
* `--force` - forces compilation regardless of modification times
* `--formatter` - formatter module
@@ -256,7 +256,13 @@ defmodule Mix.Tasks.Test do
By default, a very simple wrapper around OTP's `cover` is used as a tool,
but it can be overridden as follows:
test_coverage: [tool: CoverModule]
def project() do
[
...
test_coverage: [tool: CoverModule]
...
]
end
`CoverModule` can be any module that exports `start/2`, receiving the
compilation path and the `test_coverage` options as arguments.
+3
View File
@@ -0,0 +1,3 @@
use Mix.Config
Mix.Config.eval!(Path.join([__DIR__, "good_config.exs"]))
:done
+3
View File
@@ -107,6 +107,9 @@ defmodule Mix.ConfigTest do
{[my_app: [key: :value]],
[fixture_path("configs/good_config.exs"), fixture_path("configs/good_import.exs")]}
assert Mix.Config.eval!(fixture_path("configs/nested_import.exs")) ==
{[], [fixture_path("configs/nested_import.exs")]}
assert_raise ArgumentError,
~r"expected runtime config for app :sample to return keyword list",
fn -> Mix.Config.eval!(fixture_path("configs/bad_app.exs")) end
+21
View File
@@ -488,6 +488,27 @@ defmodule Mix.DepTest do
end)
end
test "nested deps with no overrides" do
# deps_repo brings git_repo but it is overriden
deps = [
{:deps_repo, "0.1.0", path: "custom/deps_repo"}
]
with_deps(deps, fn ->
in_fixture("deps_status", fn ->
File.mkdir_p!("custom/deps_repo/lib")
File.write!("custom/deps_repo/lib/a.ex", """
# Check that the child dependency is top_level
[%Mix.Dep{app: :git_repo, top_level: true}] = Mix.Dep.cached()
""")
Mix.Tasks.Deps.Get.run([])
Mix.Tasks.Deps.Compile.run([])
end)
end)
end
test "nested deps with overrides" do
# deps_repo brings git_repo but it is overriden
deps = [