Compare commits

...
9 Commits
Author SHA1 Message Date
José Valim 4e6d67c169 Add branch docs publishing 2023-05-30 11:41:49 +02:00
jendis 614ae049e6 Fix elixir test assertion for erlang >=OTP-24.1 (#11311) 2021-10-14 16:43:34 +02:00
MatteoandJosé Valim b1492cb0cf Fix logger translator with otp-24 (#11222)
* Handle new significant key in sasl reports

* Add OTP-24.0 to CI matrix

Co-authored-by: José Valim <jose.valim@dashbit.co>
2021-08-31 23:46:27 +02:00
Wojtek Mach 237a71311c Update warnings for OTP master (#10807) 2021-08-31 19:27:51 +02:00
José Valim e40b280fd8 Print task times on MIX_DEBUG=1 2021-06-01 11:43:49 +02:00
José Valim 308255bda8 Release v1.11.4 2021-03-16 12:25:59 +01:00
José Valim 1e81a5b9a5 Run formatter 2021-02-28 01:33:19 +01:00
José Valim 0627d7b0d4 Pass env and target to Mix.Config readers 2021-02-27 21:52:56 +01:00
Wojtek Mach 99ec7522d3 Backport OTP 24 compatibility patches to v1.11 (#10743)
* Update Erlang warnings translation (#10694)

Since https://github.com/erlang/otp/commit/8ecc648df22dbfe9dd68a3e2b968ba2b6a2ca7fe
instead of `{eval_failure, Reason}` we'd get `{eval_failure, Call, Reason}`

* Fix translating erl compiler errors to diagnostics on OTP 24 (#10719)

The compiler previously emitted just `line` and now emits `{line,
column}`.

The diagnostic struct accepts as position either:

    nil
    line
    {start_line, start_col, end_line, end_col}

so we could have used the `column` to create the 4-tuple but we don't
have enough information to do that correctly, we don't know where the
line ends.

* Fix remaining warning translations for OTP 24 (#10720)

Yecc error message changed so we need to loosen up our assertion:

OTP 23

    iex> iex
    Erlang/OTP 23 [erts-11.1.7] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]

    Interactive Elixir (1.11.3) - press Ctrl+C to exit (type h() ENTER for help)
    iex(1)> :yecc.file('f.yrl')
    f.yrl:1: syntax error before: '.'
    :error

OTP 24

    iex> iex
    Erlang/OTP 24 [DEVELOPMENT] [erts-11.1.7] [source-802d2c5083] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]

    Interactive Elixir (1.12.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
    iex(1)> :yecc.file('f.yrl')
    f.yrl:1:5: syntax error before: .

    :error

* Support 16bit floats in bitstrings (#10740)

On OTP 24:

    iex> <<x::float-16>> = <<60, 0>>
    iex> x
    1.0
    iex> <<x::float-16>>
    <<60, 0>>

Before OTP 24 we'd get errors or wouldn't match:

    iex> <<1.0::float-16>>
    ** (ArgumentError) argument error while evaluating iex at line 1

    <<x::float-16>> = <<60, 0>>
    ** (MatchError) no match of right hand side value: <<60, 0>>

    iex> (fn <<x::float-16>> -> x; _ -> :nomatch end).(<<60, 0>>)
    :nomatch

* Handle :compile.file/2 returning :error on OTP 24 (#10742)

Before OTP 24 when given invalid args, :compile.file/2 would return:

    iex(1)> :compile.file('a.erl', [{:d, 'foo', 'bar'}, :report])
    {:error, :badarg}

On OTP 24:

    iex(1)> :compile.file('a.erl', [{:d, 'foo', 'bar'}, :report])

    *** Internal compiler error ***
    exception error: bad argument
      in function  io_lib:format/2
         called as io_lib:format("badly formed '~s'",[{"foo","bar"}])
      in call from sys_messages:list_errors/3 (sys_messages.erl, line 53)
      in call from lists:foreach/2 (lists.erl, line 1342)
      in call from compile:comp_ret_err/1 (compile.erl, line 546)
      in call from compile:'-internal_fun/2-anonymous-0-'/2 (compile.erl, line 229)
      in call from compile:'-do_compile/2-anonymous-0-'/1 (compile.erl, line 219)
    :error
2021-02-20 14:33:11 +01:00
24 changed files with 368 additions and 95 deletions
+87
View File
@@ -0,0 +1,87 @@
name: builds.hex.pm
on:
push:
branches:
- main
- v*.*
tags:
- v*
env:
ELIXIR_OPTS: "--warnings-as-errors"
ERLC_OPTS: "warnings_as_errors"
LANG: C.UTF-8
concurrency: builds_txt
jobs:
release_pre_built:
strategy:
fail-fast: true
max-parallel: 1
matrix:
include:
- otp: 23
otp_version: '23.3'
build_docs: build_docs
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 50
- name: Get tags
run: git fetch --tags origin
- uses: ./.github/workflows/release_pre_built
with:
otp_version: ${{ matrix.otp_version }}
otp: ${{ matrix.otp }}
build_docs: ${{ matrix.build_docs }}
- name: Utils.sh
run: |
cat << 'EOF' > utils.sh
function purge_key() {
curl \
-X POST \
-H "Fastly-Key: ${FASTLY_KEY}" \
-H "Accept: application/json" \
-H "Content-Length: 0" \
"https://api.fastly.com/service/$1/purge/$2"
}
function purge() {
purge_key ${FASTLY_REPO_SERVICE_ID} $1
purge_key ${FASTLY_BUILDS_SERVICE_ID} $1
sleep 2
purge_key ${FASTLY_REPO_SERVICE_ID} $1
purge_key ${FASTLY_BUILDS_SERVICE_ID} $1
sleep 2
purge_key ${FASTLY_REPO_SERVICE_ID} $1
purge_key ${FASTLY_BUILDS_SERVICE_ID} $1
}
EOF
chmod +x utils.sh
- name: Upload Docs to S3
if: ${{ matrix.build_docs }}
env:
AWS_ACCESS_KEY_ID: ${{ secrets.HEX_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.HEX_AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.HEX_AWS_REGION }}
AWS_S3_BUCKET: ${{ secrets.HEX_AWS_S3_BUCKET }}
FASTLY_REPO_SERVICE_ID: ${{ secrets.HEX_FASTLY_REPO_SERVICE_ID }}
FASTLY_BUILDS_SERVICE_ID: ${{ secrets.HEX_FASTLY_BUILDS_SERVICE_ID }}
FASTLY_KEY: ${{ secrets.HEX_FASTLY_KEY }}
run: |
source utils.sh
version=$(echo ${{ github.ref_name }} | sed -e 's/^v//g')
for f in doc/*; do
if [ -d "$f" ]; then
app=`echo $f | sed s/"doc\/"//`
tarball="${app}-${version}.tar.gz"
surrogate_key="docs/${app}-${version}"
tar -czf "${tarball}" -C "doc/${app}" .
aws s3 cp "${tarball}" "s3://${{ env.AWS_S3_BUCKET }}/docs/${tarball}" \
--cache-control "public,max-age=3600" \
--metadata "{\"surrogate-key\":\"${surrogate_key}\",\"surrogate-control\":\"public,max-age=604800\"}"
purge "${surrogate_key}"
fi
done
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
otp_release: ['OTP-23.0', 'OTP-22.3', 'OTP-22.0', 'OTP-21.3.8', 'OTP-21.0']
otp_release: ['OTP-24.0', 'OTP-23.0', 'OTP-22.3', 'OTP-22.0', 'OTP-21.3.8', 'OTP-21.0']
development: [false]
include:
- otp_release: master
@@ -0,0 +1,51 @@
name: "Release pre built"
description: "Builds elixir release, ExDoc and generates docs"
inputs:
otp:
description: "The major OTP version"
otp_version:
description: "The exact OTP version (major.minor[.patch])"
build_docs:
description: "If docs have to be built or not"
runs:
using: "composite"
steps:
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ inputs.otp_version }}
version-type: strict
- name: Build Elixir Release
shell: bash
run: |
make Precompiled.zip
mv Precompiled.zip elixir-otp-${{ inputs.otp }}.zip
shasum -a 1 elixir-otp-${{ inputs.otp }}.zip > elixir-otp-${{ inputs.otp }}.zip.sha1sum
shasum -a 256 elixir-otp-${{ inputs.otp }}.zip > elixir-otp-${{ inputs.otp }}.zip.sha256sum
echo "$PWD/bin" >> $GITHUB_PATH
- name: Get latest stable ExDoc version
if: ${{ inputs.build_docs }}
shell: bash
run: |
EX_DOC_LATEST_STABLE_VERSION=$(curl -s https://hex.pm/api/packages/ex_doc | jq --raw-output '.latest_stable_version')
echo "EX_DOC_LATEST_STABLE_VERSION=${EX_DOC_LATEST_STABLE_VERSION}" >> $GITHUB_ENV
- uses: actions/checkout@v3
if: ${{ inputs.build_docs }}
with:
repository: elixir-lang/ex_doc
ref: v${{ env.EX_DOC_LATEST_STABLE_VERSION }}
path: ex_doc
- name: Build ex_doc
if: ${{ inputs.build_docs }}
shell: bash
run: |
mv ex_doc ../ex_doc
cd ../ex_doc
../elixir/bin/mix do local.rebar --force, local.hex --force, deps.get, compile
cd ../elixir
- name: Build Docs
if: ${{ inputs.build_docs }}
shell: bash
run: |
make Docs.zip
shasum -a 1 Docs.zip > Docs.zip.sha1sum
shasum -a 256 Docs.zip > Docs.zip.sha256sum
+15
View File
@@ -243,6 +243,21 @@ The Calendar module ships with a new `Calendar.strftime/3` function, which provi
Mix also includes two new tasks: `mix app.config`, for application runtime configuration, and `mix test.coverage`, which generates aggregated coverage reports for umbrella projects and for test suites partitioned across processes.
## v1.11.4 (2021-03-16)
This release introduces fixes for better support of Erlang/OTP 24+.
### 1. Enhancements
#### Elixir
* [Kernel] Update formatting when printing warnings and errors from Erlang/OTP 24+
* [Kernel] Support float-16 on bitstrings
#### Mix
* [mix local.rebar] This task will now install rebar3 version 3.14.4, compiled with Erlang/OTP 21
## v1.11.3 (2021-01-04)
### 1. Enhancements
+25 -17
View File
@@ -178,40 +178,48 @@ clean_residual_files:
LOGO_PATH = $(shell test -f ../docs/logo.png && echo "--logo ../docs/logo.png")
SOURCE_REF = $(shell tag="$(call GIT_TAG)" revision="$(call GIT_REVISION)"; echo "$${tag:-$$revision}")
DOCS_FORMAT = html
COMPILE_DOCS = bin/elixir ../ex_doc/bin/ex_doc "$(1)" "$(VERSION)" "lib/$(2)/ebin" --main "$(3)" --source-url "https://github.com/elixir-lang/elixir" --source-ref "$(call SOURCE_REF)" $(call LOGO_PATH) --output doc/$(2) --canonical "https://hexdocs.pm/$(2)/$(CANONICAL)" --homepage-url "https://elixir-lang.org/docs.html" --formatter "$(DOCS_FORMAT)" $(4)
DOCS_COMPILE = CANONICAL=$(CANONICAL) bin/elixir ../ex_doc/bin/ex_doc "$(1)" "$(VERSION)" "lib/$(2)/ebin" --main "$(3)" --source-url "https://github.com/elixir-lang/elixir" --source-ref "$(call SOURCE_REF)" $(call LOGO_PATH) --output doc/$(2) --canonical "https://hexdocs.pm/$(2)/$(CANONICAL)" --homepage-url "https://elixir-lang.org/docs.html" --formatter "$(DOCS_FORMAT)" $(4)
DOCS_CONFIG = bin/elixir lib/elixir/scripts/docs_config.exs "$(1)"
docs: compile ../ex_doc/bin/ex_doc docs_elixir docs_eex docs_mix docs_iex docs_ex_unit docs_logger
docs_elixir: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (elixir)"
$(Q) rm -rf doc/elixir
$(call COMPILE_DOCS,Elixir,elixir,Kernel,--config "lib/elixir/docs.exs")
$(call DOCS_COMPILE,Elixir,elixir,Kernel,--config "lib/elixir/scripts/elixir_docs.exs")
$(call DOCS_CONFIG,elixir)
docs_eex: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (eex)"
$(Q) rm -rf doc/eex
$(call COMPILE_DOCS,EEx,eex,EEx)
$(call DOCS_COMPILE,EEx,eex,EEx,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,eex)
docs_mix: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (mix)"
$(Q) rm -rf doc/mix
$(call COMPILE_DOCS,Mix,mix,Mix)
$(call DOCS_COMPILE,Mix,mix,Mix,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,mix)
docs_iex: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (iex)"
$(Q) rm -rf doc/iex
$(call COMPILE_DOCS,IEx,iex,IEx)
$(call DOCS_COMPILE,IEx,iex,IEx,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,iex)
docs_ex_unit: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (ex_unit)"
$(Q) rm -rf doc/ex_unit
$(call COMPILE_DOCS,ExUnit,ex_unit,ExUnit)
$(call DOCS_COMPILE,ExUnit,ex_unit,ExUnit,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,ex_unit)
docs_logger: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (logger)"
$(Q) rm -rf doc/logger
$(call COMPILE_DOCS,Logger,logger,Logger)
$(call DOCS_COMPILE,Logger,logger,Logger,--config "lib/elixir/scripts/mix_docs.exs")
$(call DOCS_CONFIG,logger)
../ex_doc/bin/ex_doc:
@ echo "ex_doc is not found in ../ex_doc as expected. See README for more information."
@@ -220,23 +228,23 @@ docs_logger: compile ../ex_doc/bin/ex_doc
#==> Zip tasks
Docs.zip: docs
rm -f Docs-v$(VERSION).zip
zip -9 -r Docs-v$(VERSION).zip CHANGELOG.md doc NOTICE LICENSE README.md
@ echo "Docs file created $(CURDIR)/Docs-v$(VERSION).zip"
rm -f Docs.zip
zip -9 -r Docs.zip CHANGELOG.md doc NOTICE LICENSE README.md
@ echo "Docs file created $(CURDIR)/Docs.zip"
Precompiled.zip: build_man compile
rm -f Precompiled-v$(VERSION).zip
zip -9 -r Precompiled-v$(VERSION).zip bin CHANGELOG.md lib/*/ebin lib/*/lib LICENSE man NOTICE README.md VERSION
@ echo "Precompiled file created $(CURDIR)/Precompiled-v$(VERSION).zip"
rm -f Precompiled.zip
zip -9 -r Precompiled.zip bin CHANGELOG.md lib/*/ebin lib/*/lib LICENSE man NOTICE README.md VERSION
@ echo "Precompiled file created $(CURDIR)/Precompiled.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:"
@ shasum -a 1 < Precompiled.zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA1:"
@ shasum -a 512 < Precompiled.zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA512:"
@ shasum -a 1 < Docs.zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA1:"
@ shasum -a 512 < Docs.zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA512:"
@ echo ""
#==> Test tasks
+1 -1
View File
@@ -1 +1 @@
1.11.3
1.11.4
+2 -2
View File
@@ -233,9 +233,9 @@ defmodule Kernel.SpecialForms do
Sizes for types are a bit more nuanced. The default size for integers is 8.
For floats, it is 64. For floats, `size * unit` must result in 32 or 64,
For floats, it is 64. For floats, `size * unit` must result in 16, 32, or 64,
corresponding to [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point)
binary32 and binary64, respectively.
binary16, binary32, and binary64, respectively.
For binaries, the default is the size of the binary. Only the last binary in a
match can use the default size. All others must have their size specified
+19
View File
@@ -0,0 +1,19 @@
# Generate docs_config.js for version chooser in ExDoc
[app] = System.argv()
{text_tags, 0} = System.cmd("git", ["tag"])
skipped = Version.parse!("1.0.3")
list_contents =
text_tags
|> String.split()
|> Enum.map(fn "v" <> rest -> Version.parse!(rest) end)
|> Enum.filter(&(Version.compare(&1, skipped) == :gt))
|> Enum.sort({:desc, Version})
|> Enum.map_intersperse(", ", fn version ->
version_string = to_string(version)
~s[{"version":"v#{version_string}", "url":"https://hexdocs.pm/#{app}/#{version_string}"}]
end)
File.mkdir_p!("doc/#{app}")
File.write!("doc/#{app}/docs_config.js", ["var versionNodes = [", list_contents, "];\n"])
+12
View File
@@ -0,0 +1,12 @@
canonical = System.fetch_env!("CANONICAL")
[
deps: [
eex: "https://hexdocs.pm/eex/#{canonical}",
elixir: "https://hexdocs.pm/elixir/#{canonical}",
ex_unit: "https://hexdocs.pm/ex_unit/#{canonical}",
iex: "https://hexdocs.pm/iex/#{canonical}",
logger: "https://hexdocs.pm/logger/#{canonical}",
mix: "https://hexdocs.pm/mix/#{canonical}"
]
]
+19 -3
View File
@@ -319,8 +319,13 @@ build_spec(Meta, _Size, Unit, Type, _Endianness, Sign, Spec, E) when Type == bin
build_spec(Meta, Size, Unit, Type, Endianness, Sign, Spec, E) when Type == integer; Type == float ->
NumberSize = number_size(Size, Unit),
if
Type == float, is_integer(NumberSize), NumberSize /= 32, NumberSize /= 64 ->
form_error(Meta, E, ?MODULE, {bittype_float_size, NumberSize});
Type == float, is_integer(NumberSize) ->
case valid_float_size(NumberSize) of
true ->
add_spec(Type, add_spec(Endianness, add_spec(Sign, Spec)));
false ->
form_error(Meta, E, ?MODULE, {bittype_float_size, NumberSize})
end;
Size == default, Unit /= default ->
form_error(Meta, E, ?MODULE, bittype_unit);
true ->
@@ -331,6 +336,12 @@ number_size(Size, default) when is_integer(Size) -> Size;
number_size(Size, Unit) when is_integer(Size) -> Size * Unit;
number_size(Size, _) -> Size.
%% TODO: Simplify when we require OTP 24
valid_float_size(16) -> erlang:system_info(otp_release) >= "24";
valid_float_size(32) -> true;
valid_float_size(64) -> true;
valid_float_size(_) -> false.
add_spec(default, Spec) -> Spec;
add_spec(Key, Spec) -> [{Key, [], []} | Spec].
@@ -372,7 +383,12 @@ format_error(bittype_signed) ->
format_error(bittype_unit) ->
"integer and float types require a size specifier if the unit specifier is given";
format_error({bittype_float_size, Other}) ->
io_lib:format("float requires size*unit to be 32 or 64 (default), got: ~p", [Other]);
Message =
case erlang:system_info(otp_release) >= "24" of
true -> "16, 32, or 64";
false -> "32 or 64"
end,
io_lib:format("float requires size*unit to be ~s (default), got: ~p", [Message, Other]);
format_error({invalid_literal, Literal}) ->
io_lib:format("invalid literal ~ts in <<>>", ['Elixir.Macro':to_string(Literal)]);
format_error({undefined_bittype, Expr}) ->
+29 -10
View File
@@ -94,6 +94,8 @@ handle_file_warning(true, _File, {_Line, sys_core_fold, {nomatch_shadow, _}}) ->
%% Those we implement ourselves
handle_file_warning(_, _File, {_Line, v3_core, {map_key_repeated, _}}) -> ok;
handle_file_warning(_, _File, {_Line, sys_core_fold, {ignored, useless_building}}) -> ok;
%% TODO: remove when we require Erlang/OTP 24
handle_file_warning(_, _File, {_Line, sys_core_fold, useless_building}) -> ok;
%% Ignore all linting errors (only come up on parse transforms)
@@ -112,11 +114,11 @@ handle_file_error(File, {Line, Module, Desc}) ->
elixir_errors:compile_error([{line, Line}], File, Message).
%% Mention the capture operator in make_fun
custom_format(sys_core_fold, {no_effect, {erlang, make_fun, 3}}) ->
custom_format(sys_core_fold, {ignored, {no_effect, {erlang, make_fun, 3}}}) ->
"the result of the capture operator & (:erlang.make_fun/3) is never used";
%% Make no_effect clauses pretty
custom_format(sys_core_fold, {no_effect, {erlang, F, A}}) ->
custom_format(sys_core_fold, {ignored, {no_effect, {erlang, F, A}}}) ->
{Fmt, Args} = case erl_internal:comp_op(F, A) of
true -> {"use of operator ~ts has no effect", [elixir_utils:erlang_comparison_op_to_elixir(F)]};
false ->
@@ -127,16 +129,11 @@ custom_format(sys_core_fold, {no_effect, {erlang, F, A}}) ->
end,
io_lib:format(Fmt, Args);
%% Rewrite nomatch_guard to be more generic it can happen inside if, unless, and the like
custom_format(sys_core_fold, nomatch_guard) ->
%% Rewrite nomatch to be more generic, it can happen inside if, unless, and the like
custom_format(sys_core_fold, {nomatch, X}) when X == guard; X == no_clause ->
"this check/guard will always yield the same result";
%% Handle literal eval failures
custom_format(sys_core_fold, {eval_failure, Error}) ->
#{'__struct__' := Struct} = 'Elixir.Exception':normalize(error, Error),
["this expression will fail with ", elixir_aliases:inspect(Struct)];
custom_format(sys_core_fold, {nomatch_shadow,Line,{ErlName,ErlArity}}) ->
custom_format(sys_core_fold, {nomatch, {shadow, Line, {ErlName, ErlArity}}}) ->
{Name, Arity} = elixir_utils:erl_fa_to_elixir_fa(ErlName, ErlArity),
io_lib:format(
@@ -144,6 +141,28 @@ custom_format(sys_core_fold, {nomatch_shadow,Line,{ErlName,ErlArity}}) ->
[Name, Arity, Line]
);
%% Handle literal eval failures
custom_format(sys_core_fold, {failed, {eval_failure, {Mod, Name, Arity}, Error}}) ->
#{'__struct__' := Struct} = 'Elixir.Exception':normalize(error, Error),
{ExMod, ExName, ExArgs} = elixir_rewrite:erl_to_ex(Mod, Name, lists:duplicate(Arity, nil)),
Call = 'Elixir.Exception':format_mfa(ExMod, ExName, length(ExArgs)),
Trimmed = case Call of
<<"Kernel.", Rest/binary>> -> Rest;
_ -> Call
end,
["the call to ", Trimmed, " will fail with ", elixir_aliases:inspect(Struct)];
%% TODO: remove when we require OTP 24
custom_format(sys_core_fold, {nomatch_shadow, Line, FA}) ->
custom_format(sys_core_fold, {nomatch, {shadow, Line, FA}});
custom_format(sys_core_fold, nomatch_guard) ->
custom_format(sys_core_fold, {nomatch, guard});
custom_format(sys_core_fold, {no_effect, X}) ->
custom_format(sys_core_fold, {ignored, {no_effect, X}});
custom_format(sys_core_fold, {eval_failure, Error}) ->
#{'__struct__' := Struct} = 'Elixir.Exception':normalize(error, Error),
["this expression will fail with ", elixir_aliases:inspect(Struct)];
custom_format([], Desc) ->
io_lib:format("~p", [Desc]);
+5 -4
View File
@@ -446,11 +446,12 @@ defmodule ExceptionTest do
* min/1
"""
assert blame_message(:erlang, & &1.gt_cookie()) == """
function :erlang.gt_cookie/0 is undefined or private. Did you mean one of:
assert blame_message(:erlang, & &1.hal()) == """
function :erlang.hal/0 is undefined or private. Did you mean one of:
* get_cookie/0
* set_cookie/2
* halt/0
* halt/1
* halt/2
"""
end
@@ -2387,17 +2387,49 @@ defmodule Kernel.ExpansionTest do
end
end
test "raises for invalid size * unit for floats" do
message = ~r"float requires size\*unit to be 32 or 64 \(default\), got: 128"
# TODO: Simplify when we require OTP 24
if System.otp_release() >= "24" do
test "16-bit floats" do
import Kernel, except: [-: 2]
assert_raise CompileError, message, fn ->
expand(quote(do: <<12.3::32*4>>))
assert expand(quote(do: <<12.3::float-16>>)) |> clean_meta([:alignment]) ==
quote(do: <<12.3::float()-size(16)>>)
end
message = ~r"float requires size\*unit to be 32 or 64 \(default\), got: 256"
test "raises for invalid size * unit for floats" do
message = ~r"float requires size\*unit to be 16, 32, or 64 \(default\), got: 128"
assert_raise CompileError, message, fn ->
expand(quote(do: <<12.3::256>>))
assert_raise CompileError, message, fn ->
expand(quote(do: <<12.3::32*4>>))
end
message = ~r"float requires size\*unit to be 16, 32, or 64 \(default\), got: 256"
assert_raise CompileError, message, fn ->
expand(quote(do: <<12.3::256>>))
end
end
else
test "16-bit floats" do
message = ~r"float requires size\*unit to be 32 or 64 \(default\), got: 16"
assert_raise CompileError, message, fn ->
expand(quote(do: <<12.3::16>>))
end
end
test "raises for invalid size * unit for floats" do
message = ~r"float requires size\*unit to be 32 or 64 \(default\), got: 128"
assert_raise CompileError, message, fn ->
expand(quote(do: <<12.3::32*4>>))
end
message = ~r"float requires size\*unit to be 32 or 64 \(default\), got: 256"
assert_raise CompileError, message, fn ->
expand(quote(do: <<12.3::256>>))
end
end
end
+11 -27
View File
@@ -931,6 +931,15 @@ defmodule Kernel.WarningTest do
purge(Sample)
end
# TODO: Simplify when we require OTP 24
if System.otp_release() >= "24" do
@argument_error_message "the call to :erlang.atom_to_binary/2"
@arithmetic_error_message "the call to +/2"
else
@argument_error_message "this expression"
@arithmetic_error_message "this expression"
end
test "eval failure warning" do
assert capture_err(fn ->
Code.eval_string("""
@@ -938,7 +947,7 @@ defmodule Kernel.WarningTest do
def foo, do: Atom.to_string "abc"
end
""")
end) =~ ~r"this expression will fail with ArgumentError\n.*nofile:2"
end) =~ "#{@argument_error_message} will fail with ArgumentError\n nofile:2"
assert capture_err(fn ->
Code.eval_string("""
@@ -946,7 +955,7 @@ defmodule Kernel.WarningTest do
def foo, do: 1 + nil
end
""")
end) =~ ~r"this expression will fail with ArithmeticError\n.*nofile:2"
end) =~ "#{@arithmetic_error_message} will fail with ArithmeticError\n nofile:2"
after
purge([Sample1, Sample2])
end
@@ -1145,31 +1154,6 @@ defmodule Kernel.WarningTest do
purge(Sample)
end
test "with and do clauses emit errors, else clauses do not" do
assert capture_err(fn ->
Code.compile_string("""
with {:first, int} when is_integer(int) <- {:second, Integer.gcd(2, 4)} do
int
end
""")
end) =~ "this clause cannot match"
assert capture_err(fn ->
Code.compile_string("""
with {:first, int1} when is_integer(int1) <- {:first, Integer.gcd(2, 4)},
{:second, int2} when is_integer(int2) <- {:second, Integer.gcd(2, 4)} do
{:ok, int1 + int2}
else
{:first, nil} -> {:error, "first number is not integer"}
{:second, nil} -> {:error, "second number is not integer"}
end
""")
end) == ""
after
purge(Sample1)
purge(Sample2)
end
test "warning on code point escape" do
assert capture_err(fn ->
Code.eval_string("? ")
+10 -3
View File
@@ -357,15 +357,22 @@ defmodule Logger.Translator do
[]
end
defp child_debug(:debug, restart_type: restart, shutdown: shutdown, child_type: type) do
["\nRestart: ", inspect(restart), "\nShutdown: ", inspect(shutdown)] ++
["\nType: ", inspect(type)]
defp child_debug(:debug, opts) do
for {key, value} <- opts do
child_debug_key(key, value)
end
end
defp child_debug(_min_level, _child) do
[]
end
defp child_debug_key(:restart_type, value), do: ["\nRestart: " | inspect(value)]
defp child_debug_key(:shutdown, value), do: ["\nShutdown: " | inspect(value)]
defp child_debug_key(:child_type, value), do: ["\nType: " | inspect(value)]
defp child_debug_key(:significant, value), do: if(value, do: "\nSignificant: true", else: [])
defp child_debug_key(_, _), do: []
defp report_crash(min_level, [[{:initial_call, initial_call} | crashed], linked]) do
mfa = initial_call_to_mfa(initial_call)
report_crash(min_level, crashed, [{:initial_call, mfa}], linked)
+7 -2
View File
@@ -271,7 +271,7 @@ defmodule Mix.Compilers.Erlang do
defp to_diagnostics(warnings_or_errors, severity) do
for {file, issues} <- warnings_or_errors,
{line, module, data} <- issues do
position = if is_integer(line) and line >= 1, do: line
position = line(line)
%Mix.Task.Compiler.Diagnostic{
file: Path.absname(file),
@@ -288,7 +288,12 @@ defmodule Mix.Compilers.Erlang do
for {_, warnings} <- entries,
{file, issues} <- warnings,
{line, module, message} <- issues do
IO.puts("#{file}:#{line}: Warning: #{module.format_error(message)}")
IO.puts("#{file}:#{line(line)}: Warning: #{module.format_error(message)}")
end
end
defp line({line, _column}) when is_integer(line) and line >= 1, do: line
# TODO: remove when we require OTP 24
defp line(line) when is_integer(line) and line >= 1, do: line
defp line(_), do: nil
end
+6 -2
View File
@@ -176,7 +176,11 @@ defmodule Mix.Config do
"""
@doc deprecated: "Use Config.Reader.read_imports!/2 instead"
def eval!(file, imported_paths \\ []) do
Config.Reader.read_imports!(file, imports: imported_paths)
Config.Reader.read_imports!(file,
imports: imported_paths,
env: Mix.env(),
target: Mix.target()
)
end
@doc """
@@ -195,7 +199,7 @@ defmodule Mix.Config do
@doc deprecated: "Use Config.Reader.read!/2 instead"
@spec read!(Path.t(), [Path.t()]) :: keyword
def read!(file, imported_paths \\ []) do
Config.Reader.read!(file, imports: imported_paths)
Config.Reader.read!(file, imports: imported_paths, env: Mix.env(), target: Mix.target())
end
@doc """
+18 -9
View File
@@ -387,15 +387,16 @@ defmodule Mix.Task do
Mix.ProjectStack.on_recursing_root(fn -> run(task, args) end)
Mix.TasksServer.run({:task, task, proj}) ->
if Mix.debug?(), do: output_task_debug_info(task, args, proj)
run_requirements(module)
try do
module.run(args)
rescue
e in OptionParser.ParseError ->
Mix.raise("Could not invoke task #{inspect(task)}: " <> Exception.message(e))
end
with_debug(task, args, proj, fn ->
try do
module.run(args)
rescue
e in OptionParser.ParseError ->
Mix.raise("Could not invoke task #{inspect(task)}: " <> Exception.message(e))
end
end)
true ->
:noop
@@ -409,8 +410,16 @@ defmodule Mix.Task do
end)
end
defp output_task_debug_info(task, args, proj) do
Mix.shell().info("** Running mix " <> task_to_string(task, args) <> project_to_string(proj))
defp with_debug(task, args, proj, fun) do
if Mix.debug?() do
shell = Mix.shell()
shell.info(["-> Running mix ", task_to_string(task, args), project_to_string(proj)])
{time, res} = :timer.tc(fun)
shell.info(["<- Ran mix ", task, " in ", Integer.to_string(div(time, 1000)), "ms"])
res
else
fun.()
end
end
defp project_to_string(nil), do: ""
+3 -2
View File
@@ -100,9 +100,10 @@ defmodule Mix.Tasks.Compile.Erlang do
file = Erlang.to_erl_file(Path.rootname(input, ".erl"))
case :compile.file(file, erlc_options) do
{:error, :badarg} ->
# TODO: Don't handle {:error, :badarg} when we require OTP 24
error when error == :error or error == {:error, :badarg} ->
message =
"Compiling Erlang #{inspect(file)} failed with ArgumentError, probably because of invalid :erlc_options"
"Compiling Erlang file #{inspect(file)} failed, probably because of invalid :erlc_options"
Mix.raise(message)
+2 -2
View File
@@ -60,11 +60,11 @@ defmodule Mix.CLITest do
assert contents =~ "This won't appear"
contents = mix(~w[my_hello], [{"MIX_DEBUG", "1"}])
assert contents =~ "** Running mix my_hello (inside MyProject)"
assert contents =~ "-> Running mix my_hello (inside MyProject)"
assert contents =~ "** (Mix.Error) oops"
contents = mix(~w[my_hello], [{"MIX_DEBUG", "0"}])
refute contents =~ "** Running mix my_hello (inside MyProject)"
refute contents =~ "-> Running mix my_hello (inside MyProject)"
refute contents =~ "** (Mix.Error) oops"
end)
end
+2 -1
View File
@@ -59,7 +59,8 @@ defmodule Mix.TaskTest do
Mix.shell(Mix.Shell.IO)
Mix.debug(true)
assert ExUnit.CaptureIO.capture_io(fn -> Mix.Task.run("hello") end) =~ "** Running mix hello"
assert ExUnit.CaptureIO.capture_io(fn -> Mix.Task.run("hello") end) =~
~r"-> Running mix hello\n<- Ran mix hello in \d+ms"
after
Mix.shell(Mix.Shell.Process)
Mix.debug(false)
@@ -14,7 +14,7 @@ defmodule Mix.Tasks.Compile.ErlangTest do
@tag erlc_options: [{:d, 'foo', 'bar'}]
test "raises on invalid erlc_options" do
in_fixture("compile_erlang", fn ->
assert_raise Mix.Error, ~r"failed with ArgumentError", fn ->
assert_raise Mix.Error, ~r"Compiling Erlang file '.*' failed", fn ->
capture_io(fn ->
Mix.Tasks.Compile.Erlang.run([])
end)
+3 -1
View File
@@ -23,10 +23,12 @@ defmodule Mix.Tasks.Compile.YeccTest do
assert %Mix.Task.Compiler.Diagnostic{
compiler_name: "yecc",
file: ^file,
message: "syntax error before: '.'",
message: message,
position: 1,
severity: :error
} = diagnostic
assert message =~ "syntax error before: "
end)
assert File.regular?("src/test_ok.erl")