Compare commits

...
27 changed files with 469 additions and 70 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
- otp: 26
otp_version: '26.0'
build_docs: build_docs
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
with:
+5 -3
View File
@@ -15,7 +15,7 @@ permissions:
jobs:
create_draft_release:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
@@ -40,7 +40,7 @@ jobs:
- otp: 26
otp_version: '26.0'
build_docs: build_docs
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
with:
@@ -56,7 +56,9 @@ jobs:
run: |
gh release upload --clobber "${{ github.ref_name }}" \
elixir-otp-${{ matrix.otp }}.zip \
elixir-otp-${{ matrix.otp }}.zip.sha{1,256}sum
elixir-otp-${{ matrix.otp }}.zip.sha{1,256}sum \
elixir-otp-${{ matrix.otp }}.exe \
elixir-otp-${{ matrix.otp }}.exe.sha{1,256}sum
- name: Upload Docs to GitHub
if: ${{ matrix.build_docs }}
env:
@@ -22,6 +22,20 @@ runs:
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: Install NSIS
shell: bash
run: |
sudo apt update
sudo apt install -y nsis
- name: Build Elixir Windows Installer
shell: bash
run: |
export OTP_VERSION=${{ inputs.otp_version }}
export ELIXIR_ZIP=$PWD/elixir-otp-${{ inputs.otp }}.zip
(cd lib/elixir/scripts/windows_installer && ./build.sh)
mv lib/elixir/scripts/windows_installer/tmp/elixir-otp-${{ inputs.otp }}.exe .
shasum -a 1 elixir-otp-${{ inputs.otp }}.exe > elixir-otp-${{ inputs.otp }}.exe.sha1sum
shasum -a 256 elixir-otp-${{ inputs.otp }}.exe > elixir-otp-${{ inputs.otp }}.exe.sha256sum
- name: Get latest stable ExDoc version
if: ${{ inputs.build_docs }}
shell: bash
+36 -6
View File
@@ -68,7 +68,7 @@ In Elixir v1.15, the new reports will look like:
error: undefined function foo/0 (there is no such import)
my_file.exs:1
** (CompileError) nofile: cannot compile file (errors have been logged)
** (CompileError) my_file.exs: cannot compile file (errors have been logged)
A new function, called `Code.with_diagnostics/2`, has been added so this
information can be leveraged by editors, allowing them to point to several
@@ -100,16 +100,46 @@ config :logger, :default_formatter,
format: "$time $message $metadata"
```
If you use `Logger.Backends.Console` or other backends, they are
still fully supported and functional. If you implement your own
backends, you want to consider migrating to
If you use `Logger.Backends.Console` with a custom device or other
backends, they are still fully supported and functional. If you
implement your own backends, you want to consider migrating to
[`:logger_backends`](https://github.com/elixir-lang/logger_backends)
in the long term.
See the new `Logger` documentation for more information on the
new features and on compatibility.
## v1.15.0-rc.1 (2022-05-29)
## v1.15.0-rc.2 (2023-06-12)
### 1. Enhancements
#### Elixir
* [Module] Mark functions as generated in "Docs" chunk
#### ExUnit
* [ExUnit.Doctest] Include `doctest_data` in doctest tags
### 2. Bug fixes
#### Elixir
* [Kernel] Fix `import m, only: :sigils` for multi-letter sigils (regression)
* [Macro] Fix `Macro.to_string/1` for multi-letter sigils (regression)
#### ExUnit
* [ExUnit] Mark test cases as invalid when an exit occurs during `setup_all`
* [ExUnit] Fix ExUnit diffs for multi-letter sigils (regression)
* [ExUnit.Doctest] Fix line information when a doctest with multiple assertions fails
#### Mix
* [mix compile] Keep erts when pruning load paths (regression)
* [mix xref] Raise early if `mix xref` is used at the umbrella root
## v1.15.0-rc.1 (2023-05-29)
### 1. Enhancements
@@ -154,7 +184,7 @@ new features and on compatibility.
* [Kernel] Require pin variable when accessing variable inside binary size in match
## v1.15.0-rc.0 (2022-05-22)
## v1.15.0-rc.0 (2023-05-22)
### 1. Enhancements
+1 -1
View File
@@ -2,7 +2,7 @@ PREFIX ?= /usr/local
TEST_FILES ?= "*_test.exs"
SHARE_PREFIX ?= $(PREFIX)/share
MAN_PREFIX ?= $(SHARE_PREFIX)/man
#CANONICAL := MAJOR.MINOR/
CANONICAL := 1.15/
CANONICAL ?= main/
DOCS_FORMAT ?= html
ELIXIRC := bin/elixirc --ignore-module-conflict $(ELIXIRC_OPTS)
+2 -3
View File
@@ -6,12 +6,11 @@ Elixir applies bug fixes only to the latest minor branch. Security patches are a
Elixir version | Support
:------------- | :-----------------------------
1.15 | Development
1.14 | Bug fixes and security patches
1.15 | Bug fixes and security patches
1.14 | Security patches only
1.13 | Security patches only
1.12 | Security patches only
1.11 | Security patches only
1.10 | Security patches only
## Announcements
+1 -1
View File
@@ -1 +1 @@
1.15.0-rc.1
1.15.0-rc.2
+1 -1
View File
@@ -1,7 +1,7 @@
#!/bin/sh
set -e
ELIXIR_VERSION=1.15.0-rc.1
ELIXIR_VERSION=1.15.0-rc.2
if [ $# -eq 0 ] || { [ $# -eq 1 ] && { [ "$1" = "--help" ] || [ "$1" = "-h" ]; }; }; then
cat <<USAGE >&2
+1 -1
View File
@@ -1,6 +1,6 @@
@if defined ELIXIR_CLI_ECHO (@echo on) else (@echo off)
set ELIXIR_VERSION=1.15.0-rc.1
set ELIXIR_VERSION=1.15.0-rc.2
setlocal enabledelayedexpansion
if ""%1""=="""" if ""%2""=="""" goto documentation
-4
View File
@@ -3,10 +3,6 @@ defmodule Code.Fragment do
This module provides conveniences for analyzing fragments of
textual code and extract available information whenever possible.
Most of the functions in this module provide a best-effort
and may not be accurate under all circumstances. Read each
documentation for more information.
This module should be considered experimental.
"""
@@ -8,12 +8,11 @@ Elixir applies bug fixes only to the latest minor branch. Security patches are a
Elixir version | Support
:------------- | :-----------------------------
1.15 | Development
1.14 | Bug fixes and security patches
1.15 | Bug fixes and security patches
1.14 | Security patches only
1.13 | Security patches only
1.12 | Security patches only
1.11 | Security patches only
1.10 | Security patches only
New releases are announced in the read-only [announcements mailing list](https://groups.google.com/group/elixir-lang-ann). All security releases [will be tagged with `[security]`](https://groups.google.com/forum/#!searchin/elixir-lang-ann/%5Bsecurity%5D%7Csort:date).
@@ -0,0 +1 @@
tmp/
Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
# Usage:
#
# With Elixir archive:
#
# ELIXIR_ZIP=Precompiled.zip OTP_VERSION=25.3.2.2 ./build.sh
#
# With Elixir version:
#
# ELIXIR_VERSION=1.14.5 OTP_VERSION=25.3.2.2 ./build.sh
set -euo pipefail
OTP_VERSION="${OTP_VERSION:-26.0}"
otp_release=`echo "${OTP_VERSION}" | cut -d. -f1`
mkdir -p tmp
ELIXIR_VERSION="${ELIXIR_VERSION:-}"
if [ -n "${ELIXIR_VERSION}" ]; then
ELIXIR_ZIP="tmp/elixir-${ELIXIR_VERSION}-otp-${otp_release}.zip"
if [ ! -f "${ELIXIR_ZIP}" ]; then
url="https://github.com/elixir-lang/elixir/releases/download/v${ELIXIR_VERSION}/elixir-otp-${otp_release}.zip"
echo "downloading ${url}"
curl --fail -L -o "${ELIXIR_ZIP}" "${url}"
fi
basename=elixir-${ELIXIR_VERSION}-otp-${otp_release}
else
basename=elixir-otp-${otp_release}
fi
if [ ! -d "tmp/${basename}" ]; then
unzip -d "tmp/${basename}" "${ELIXIR_ZIP}"
fi
# brew install makensis
# apt install -y nsis
# choco install -y nsis
export PATH="/c/Program Files (x86)/NSIS:${PATH}"
makensis \
-X"OutFile tmp\\${basename}.exe" \
-DOTP_VERSION=${OTP_VERSION} \
-DOTP_RELEASE="${otp_release}" \
-DELIXIR_DIR=tmp\\${basename} \
installer.nsi
echo "Installer path: tmp/${basename}.exe"
@@ -0,0 +1,209 @@
!include "MUI2.nsh"
!include "StrFunc.nsh"
${Using:StrFunc} StrStr
${Using:StrFunc} UnStrStr
${Using:StrFunc} UnStrRep
Name "Elixir"
ManifestDPIAware true
Unicode True
InstallDir "$PROGRAMFILES64\Elixir"
!define MUI_ICON "assets\drop.ico"
; Install Page: Install Erlang/OTP
Page custom CheckOTPPageShow CheckOTPPageLeave
var Dialog
var DownloadOTPLink
var InstalledERTSVersion
var InstalledOTPRelease
var OTPPath
Function CheckOTPPageShow
!insertmacro MUI_HEADER_TEXT "Checking Erlang/OTP" ""
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
EnumRegKey $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" 0
ReadRegStr $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$0" ""
StrCpy $InstalledERTSVersion $0
StrCpy $OTPPath $1
${If} $1 == ""
${NSD_CreateLabel} 0 0 100% 20u "Couldn't find existing Erlang/OTP installation. Click the link below to download and install it before proceeding."
${NSD_CreateLink} 0 25u 100% 20u "Download Erlang/OTP ${OTP_RELEASE}"
Pop $DownloadOTPLink
${NSD_OnClick} $DownloadOTPLink OpenOTPDownloads
${Else}
nsExec::ExecToStack `$OTPPath\bin\erl.exe -noinput -eval "\
io:put_chars(erlang:system_info(otp_release)),\
halt()."`
Pop $0
Pop $1
${If} $0 == 0
StrCpy $InstalledOTPRelease $1
${If} $InstalledOTPRelease == ${OTP_RELEASE}
${NSD_CreateLabel} 0 0 100% 20u "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath. Please proceed."
${ElseIf} $2 < ${OTP_RELEASE}
${NSD_CreateLabel} 0 0 100% 30u "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath but this Elixir installer was precompiled for Erlang/OTP ${OTP_RELEASE}. \
We recommend checking if there is an Elixir version precompiled for Erlang/OTP $InstalledOTPRelease. Otherwise, proceed."
${Else}
SetErrorlevel 5
MessageBox MB_ICONSTOP "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath but this Elixir version was precompiled for Erlang/OTP ${OTP_RELEASE}. \
Please upgrade your Erlang/OTP version or choose an Elixir installer matching your Erlang/OTP version"
Quit
${EndIf}
${Else}
SetErrorlevel 5
MessageBox MB_ICONSTOP "Found existing Erlang/OTP installation at $OTPPath but checking it exited with $0: $1"
Quit
${EndIf}
${EndIf}
nsDialogs::Show
FunctionEnd
Function OpenOTPDownloads
ExecShell "open" "https://www.erlang.org/downloads/${OTP_RELEASE}"
FunctionEnd
Function CheckOTPPageLeave
FunctionEnd
; Install Page: Files
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
; Install Page: Finish
Page custom FinishPageShow FinishPageLeave
var AddOTPToPathCheckbox
var AddElixirToPathCheckbox
Function FinishPageShow
!insertmacro MUI_HEADER_TEXT "Finish Setup" ""
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
${NSD_CreateCheckbox} 0 0 195u 10u "&Add $INSTDIR\bin to %PATH%"
Pop $AddElixirToPathCheckbox
SendMessage $AddElixirToPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
EnumRegKey $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" 0
ReadRegStr $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$0" ""
StrCpy $OTPPath $0
${If} $0 != ""
${NSD_CreateCheckbox} 0 20u 195u 10u "&Add $0\bin to %PATH%"
Pop $AddOTPToPathCheckbox
SendMessage $AddOTPToPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
${EndIf}
nsDialogs::Show
FunctionEnd
Function FinishPageLeave
${NSD_GetState} $AddOTPToPathCheckbox $0
${If} $0 <> ${BST_UNCHECKED}
ReadRegStr $0 HKCU "Environment" "Path"
${StrStr} $1 "$0" "$OTPPath\bin"
${If} $1 == ""
WriteRegExpandStr HKCU "Environment" "Path" "$OTPPath\bin;$0"
${Else}
MessageBox MB_OK "$OTPPath\bin already in %PATH%"
${EndIf}
${EndIf}
${NSD_GetState} $AddElixirToPathCheckbox $0
${If} $0 <> ${BST_UNCHECKED}
ReadRegStr $0 HKCU "Environment" "Path"
${StrStr} $1 "$0" "$INSTDIR\bin"
${If} $1 == ""
WriteRegExpandStr HKCU "Environment" "Path" "$INSTDIR\bin;$0"
${Else}
MessageBox MB_OK "$INSTDIR\bin already in %PATH%"
${EndIf}
${EndIf}
FunctionEnd
Section "Install Elixir" SectionElixir
SetOutPath "$INSTDIR"
File /r "${ELIXIR_DIR}\"
WriteUninstaller "Uninstall.exe"
SectionEnd
; Uninstall Page: Files
!insertmacro MUI_UNPAGE_DIRECTORY
!insertmacro MUI_UNPAGE_INSTFILES
Section "Uninstall"
RMDir /r "$INSTDIR"
SectionEnd
; Uninstall Page: Finish
var RemoveOTPFromPathCheckbox
var RemoveElixirFromPathCheckbox
Function un.FinishPageShow
!insertmacro MUI_HEADER_TEXT "Finish Setup" ""
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
ReadRegStr $0 HKCU "Environment" "Path"
${UnStrStr} $1 "$0" "$INSTDIR\bin"
${If} $1 != ""
${NSD_CreateCheckbox} 0 0 195u 10u "&Remove $INSTDIR\bin from %PATH%"
Pop $RemoveElixirFromPathCheckbox
SendMessage $RemoveElixirFromPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
${EndIf}
EnumRegKey $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" 0
ReadRegStr $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$1" ""
StrCpy $OTPPath $1
${UnStrStr} $1 "$0" "$OTPPath\bin"
${If} $1 != ""
${NSD_CreateCheckbox} 0 20u 195u 10u "&Remove $OTPPath\bin from %PATH%"
Pop $RemoveOTPFromPathCheckbox
SendMessage $RemoveOTPFromPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
${EndIf}
nsDialogs::Show
FunctionEnd
Function un.FinishPageLeave
ReadRegStr $0 HKCU "Environment" "Path"
${NSD_GetState} $RemoveOTPFromPathCheckbox $1
${If} $1 <> ${BST_UNCHECKED}
${UnStrRep} $0 "$0" "$OTPPath\bin;" ""
${EndIf}
${NSD_GetState} $RemoveElixirFromPathCheckbox $1
${If} $1 <> ${BST_UNCHECKED}
${UnStrRep} $0 "$0" "$INSTDIR\bin;" ""
${EndIf}
WriteRegExpandStr HKCU "Environment" "Path" "$0"
FunctionEnd
UninstPage custom un.FinishPageShow un.FinishPageLeave
!insertmacro MUI_LANGUAGE "English"
+5 -2
View File
@@ -510,12 +510,15 @@ get_moduledoc_meta(Set) ->
get_docs(Set, Module, Definitions, Kind) ->
[{Key,
erl_anno:new(Line),
maybe_generated(erl_anno:new(Line), Ctx),
[signature_to_binary(Module, Name, Signature)],
doc_value(Doc, Name),
Meta
} || {Name, Arity} <- Definitions,
{Key, _Ctx, Line, Signature, Doc, Meta} <- ets:lookup(Set, {Kind, Name, Arity})].
{Key, Ctx, Line, Signature, Doc, Meta} <- ets:lookup(Set, {Kind, Name, Arity})].
maybe_generated(Ann, nil) -> Ann;
maybe_generated(Ann, _Ctx) -> erl_anno:set_generated(true, Ann).
get_callback_docs(Set, Callbacks) ->
[{Key,
+3 -3
View File
@@ -1030,8 +1030,8 @@ extract_heredoc_with_interpolation(Line, Column, Scope, Interpol, T, H) ->
end;
error ->
Message = "heredoc allows only zero or more whitespace characters followed by a new line after ",
{error, {Line, Column, io_lib:format(Message, []), [H, H, H]}}
Message = "heredoc allows only whitespace characters followed by a new line after opening ",
{error, {Line, Column + 3, io_lib:format(Message, []), [H, H, H]}}
end.
extract_heredoc_header("\r\n" ++ Rest) ->
@@ -1796,7 +1796,7 @@ prune_tokens([{OpType, _, _} | _] = Tokens, [], Terminators)
OpType =:= in_match_op; OpType =:= type_op; OpType =:= dual_op; OpType =:= mult_op;
OpType =:= power_op; OpType =:= concat_op; OpType =:= range_op; OpType =:= xor_op;
OpType =:= pipe_op; OpType =:= stab_op; OpType =:= when_op; OpType =:= assoc_op;
OpType =:= rel_op; OpType =:= ternary_op ->
OpType =:= rel_op; OpType =:= ternary_op; OpType =:= capture_op ->
{Tokens, Terminators};
%%% or we traverse until the end.
prune_tokens([_ | Tokens], Opener, Terminators) ->
@@ -1098,6 +1098,8 @@ defmodule CodeFragmentTest do
test "keeps operators" do
assert cc2q("1 + 2") == s2q("1 + __cursor__()")
assert cc2q("&foo") == s2q("&__cursor__()")
assert cc2q("&foo/") == s2q("&foo/__cursor__()")
end
test "keeps function calls without parens" do
@@ -1200,11 +1202,6 @@ defmodule CodeFragmentTest do
assert cc2q("(fn x, y -> x + y end") == s2q("(__cursor__())")
end
test "removes captures" do
assert cc2q("[& &1") == s2q("[__cursor__()]")
assert cc2q("[&(&1") == s2q("[__cursor__()]")
end
test "removes closed terminators" do
assert cc2q("foo([1, 2, 3]") == s2q("foo(__cursor__())")
assert cc2q("foo({1, 2, 3}") == s2q("foo(__cursor__())")
@@ -381,4 +381,30 @@ defmodule Kernel.DocsTest do
{{:fuz, 0}, :none}
] = Enum.sort(function_docs)
end
test "generated functions are annotated as such" do
write_beam(
defmodule ToBeUsed do
defmacro __using__(_) do
quote do
@doc "Hello"
def foo, do: :bar
end
end
end
)
write_beam(
defmodule WillBeUsing do
use ToBeUsed
end
)
{:docs_v1, _, _, _, _, _, docs} = Code.fetch_docs(WillBeUsing)
assert [
{{:function, :foo, 0}, [generated: true, location: 399], ["foo()"],
%{"en" => "Hello"}, %{}}
] = docs
end
end
@@ -538,7 +538,7 @@ defmodule Kernel.ParserTest do
describe "syntax errors" do
test "invalid heredoc start" do
assert_syntax_error(
~r/nofile:1:1: heredoc allows only zero or more whitespace characters followed by a new line after \"\"\"/,
~r/nofile:1:4: heredoc allows only whitespace characters followed by a new line after opening \"\"\"/,
~c"\"\"\"bar\n\"\"\""
)
end
+2 -1
View File
@@ -293,8 +293,9 @@ defmodule ExUnit.Runner do
{test_module, invalid_tests, []}
{:DOWN, ^module_ref, :process, ^module_pid, error} ->
invalid_tests = Enum.map(tests, &%{&1 | state: {:invalid, test_module}})
test_module = %{test_module | state: failed({:EXIT, module_pid}, error, [])}
{test_module, [], []}
{test_module, invalid_tests, []}
end
timeout = get_timeout(config, %{})
@@ -124,6 +124,22 @@ defmodule ExUnit.CallbacksTest do
"** (MatchError) no match of right hand side value: :error"
end
test "doesn't choke on setup_all exits" do
defmodule SetupAllExitTest do
use ExUnit.Case
setup_all _ do
Process.exit(self(), :error)
end
test "ok" do
assert true
end
end
assert capture_io(fn -> ExUnit.run() end) =~ "1 test, 0 failures, 1 invalid"
end
test "doesn't choke on dead supervisor" do
defmodule StartSupervisedErrorTest do
use ExUnit.Case
+2 -2
View File
@@ -97,8 +97,8 @@ defmodule Mix.AppLoader do
defp extra_apps(config) do
case Keyword.get(config, :language, :elixir) do
:elixir -> [:ex_unit, :iex, :mix, :elixir]
:erlang -> [:compiler]
:elixir -> [:ex_unit, :iex, :mix, :elixir, :erts]
:erlang -> [:compiler, :erts]
end
end
+31 -14
View File
@@ -38,8 +38,9 @@ defmodule Mix.Tasks.Xref do
$ mix xref trace lib/my_app/router.ex --label compile
If you have an umbrella application, we also recommend using the
`--include-siblings` flag to see the dependencies on other
umbrella applications.
`--include-siblings` flag to see the dependencies from sibling
applications. The `trace` command is not currently supported at the
umbrella root.
### Example
@@ -222,6 +223,12 @@ defmodule Mix.Tasks.Xref do
lib/a.ex
└── lib/b.ex (compile)
If you have an umbrella application, we also recommend using the
`--include-siblings` flag to see the dependencies from sibling
applications. When invoked at the umbrella root, the `graph`
command will list all files from all umbrella children, without
any namespacing.
### Dependency types
Elixir tracks three types of dependencies between modules: compile,
@@ -289,12 +296,6 @@ defmodule Mix.Tasks.Xref do
@impl true
def run(args) do
if Mix.Project.umbrella?() do
Mix.raise(
"mix xref is not supported in the umbrella root. Please run it inside the umbrella applications instead"
)
end
Mix.Task.run("compile", args)
Mix.Task.reenable("xref")
@@ -302,9 +303,11 @@ defmodule Mix.Tasks.Xref do
case args do
["callers", module] ->
no_umbrella!("callers")
handle_callers(module, opts)
["trace", file] ->
no_umbrella!("trace")
handle_trace(file, opts)
["graph"] ->
@@ -327,6 +330,14 @@ defmodule Mix.Tasks.Xref do
end
end
defp no_umbrella!(task) do
if Mix.Project.umbrella?() do
Mix.raise(
"mix xref #{task} is not supported in the umbrella root. Please run it inside the umbrella applications instead"
)
end
end
@doc """
Returns a list of information of all the runtime function calls in the project.
@@ -1058,12 +1069,18 @@ defmodule Mix.Tasks.Xref do
defp manifests(opts) do
siblings =
if opts[:include_siblings] do
for %{scm: Mix.SCM.Path, opts: opts} <- Mix.Dep.cached(),
opts[:in_umbrella],
do: Path.join([opts[:build], ".mix", @manifest])
else
[]
cond do
Mix.Project.umbrella?() ->
for %{opts: opts} <- Mix.Dep.Umbrella.cached(),
do: Path.join([opts[:build], ".mix", @manifest])
opts[:include_siblings] ->
for %{scm: Mix.SCM.Path, opts: opts} <- Mix.Dep.cached(),
opts[:in_umbrella],
do: Path.join([opts[:build], ".mix", @manifest])
true ->
[]
end
[Path.join(Mix.Project.manifest_path(), @manifest) | siblings]
+3
View File
@@ -335,6 +335,9 @@ defmodule Mix.Tasks.CompileTest do
in_fixture("no_mixfile", fn ->
assert Mix.Task.run("compile", []) == {:ok, []}
assert :code.where_is_file(~c"parsetools.app") == :non_existing
# Make sure erts is also kept
assert {:docs_v1, _, _, _, _, _, _} = Code.fetch_docs(:zlib)
end)
end
+37
View File
@@ -915,6 +915,43 @@ defmodule Mix.Tasks.XrefTest do
end)
end
test "generates reports from the umbrella root" do
Mix.Project.pop()
in_fixture("umbrella_dep/deps/umbrella", fn ->
Mix.Project.in_project(:umbrella, ".", fn _ ->
File.write!("apps/bar/lib/bar.ex", """
defmodule Bar do
def bar do
Foo.foo()
end
end
""")
Mix.Task.run("compile")
Mix.shell().flush()
Mix.Tasks.Xref.run(["graph", "--format", "stats", "--include-siblings"])
assert receive_until_no_messages([]) == """
Tracked files: 2 (nodes)
Compile dependencies: 0 (edges)
Exports dependencies: 0 (edges)
Runtime dependencies: 1 (edges)
Cycles: 0
Top 2 files with most outgoing dependencies:
* lib/bar.ex (1)
* lib/foo.ex (0)
Top 2 files with most incoming dependencies:
* lib/foo.ex (1)
* lib/bar.ex (0)
"""
end)
end)
end
test "generates reports considering siblings inside umbrellas" do
Mix.Project.pop()
+21 -18
View File
@@ -1,3 +1,16 @@
home = Path.expand("../tmp/.home", __DIR__)
File.mkdir_p!(home)
System.put_env("HOME", home)
mix = Path.expand("../tmp/.mix", __DIR__)
File.mkdir_p!(mix)
System.put_env("MIX_HOME", mix)
System.delete_env("XDG_DATA_HOME")
System.delete_env("XDG_CONFIG_HOME")
## Setup Mix
Mix.start()
Mix.shell(Mix.Shell.Process)
Application.put_env(:mix, :colors, enabled: false)
@@ -5,6 +18,8 @@ Application.put_env(:mix, :colors, enabled: false)
Logger.remove_backend(:console)
Application.put_env(:logger, :backends, [])
## Setup ExUnit
os_exclude = if match?({:win32, _}, :os.type()), do: [unix: true], else: [windows: true]
epmd_exclude = if match?({:win32, _}, :os.type()), do: [epmd: true], else: []
git_exclude = if Mix.SCM.Git.git_version() <= {1, 7, 4}, do: [git_sparse: true], else: []
@@ -212,18 +227,7 @@ defmodule MixTest.Case do
end
end
## Set up globals
home = MixTest.Case.tmp_path(".home")
File.mkdir_p!(home)
System.put_env("HOME", home)
mix = MixTest.Case.tmp_path(".mix")
File.mkdir_p!(mix)
System.put_env("MIX_HOME", mix)
System.delete_env("XDG_DATA_HOME")
System.delete_env("XDG_CONFIG_HOME")
## Set up Rebar fixtures
rebar3_source = System.get_env("REBAR3") || Path.expand("fixtures/rebar3", __DIR__)
[major, minor | _] = String.split(System.version(), ".")
@@ -231,8 +235,6 @@ rebar3_target = Path.join([mix, "elixir", "#{major}-#{minor}", "rebar3"])
File.mkdir_p!(Path.dirname(rebar3_target))
File.cp!(rebar3_source, rebar3_target)
## Copy fixtures to tmp
fixtures = ~w(rebar_dep rebar_override)
Enum.each(fixtures, fn fixture ->
@@ -242,12 +244,13 @@ Enum.each(fixtures, fn fixture ->
File.cp_r!(source, dest)
end)
## Generate Git repo fixtures
## Set up Git fixtures
System.cmd("git", ~w[config --global user.email mix@example.com])
System.cmd("git", ~w[config --global user.name mix-repo])
System.cmd("git", ~w[config --global init.defaultBranch not-main])
# Git repo
### Git repo
target = Path.expand("fixtures/git_repo", __DIR__)
unless File.dir?(target) do
@@ -329,7 +332,7 @@ unless File.dir?(target) do
end)
end
# Deps on Git repo
### Deps on Git repo
target = Path.expand("fixtures/deps_on_git_repo", __DIR__)
unless File.dir?(target) do
@@ -423,7 +426,7 @@ Enum.each([:invalidapp, :invalidvsn, :noappfile, :nosemver, :ok], fn dep ->
File.mkdir_p!(Path.expand("fixtures/deps_status/deps/#{dep}/.git", __DIR__))
end)
# Archive ebin
### Archive ebin
target = Path.expand("fixtures/archive", __DIR__)
unless File.dir?(Path.join(target, "ebin")) do