Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package elixir for openSUSE:Factory checked 
in at 2022-02-27 22:42:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/elixir (Old)
 and      /work/SRC/openSUSE:Factory/.elixir.new.1958 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "elixir"

Sun Feb 27 22:42:57 2022 rev:21 rq:957806 version:1.13.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/elixir/elixir.changes    2022-01-17 
22:35:00.602282039 +0100
+++ /work/SRC/openSUSE:Factory/.elixir.new.1958/elixir.changes  2022-02-27 
22:43:21.294635008 +0100
@@ -1,0 +2,25 @@
+Tue Feb 22 20:01:32 UTC 2022 - Fabrizio Sestito <[email protected]>
+
+- Elixir 1.13.3
+  * 1. Enhancements
+    Mix
+
+        [mix format] Supply file and line to formatter plugins
+        [mix format] Support embedded Elixir expressions inside formatter 
plugins
+
+  * 2. Bug fixes
+    Elixir
+
+        [Code] Fix duplicate bindings causing errors during evaluation
+        [Kernel] Make sure signatures stored in the Documentation chunk does 
not contain newlines
+        [Kernel] Fix infinite loop when compiling guards with recursive map 
access
+        [Macro] Fix error on Macro.to_string/1 when the plain alias Elixir is 
given
+        [String] Fix error for certain codepoint combinations in 
String.split_at/2
+
+    Mix
+
+        [mix compile] Recompile project files when exports from dependencies 
change
+        [mix test] Fix total coverage always showing in red even when above 
the threshold
+
+
+-------------------------------------------------------------------

Old:
----
  elixir-1.13.2.tar.gz

New:
----
  elixir-1.13.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ elixir-doc.spec ++++++
--- /var/tmp/diff_new_pack.zGzCHS/_old  2022-02-27 22:43:21.842635168 +0100
+++ /var/tmp/diff_new_pack.zGzCHS/_new  2022-02-27 22:43:21.850635169 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           elixir-doc
-Version:        1.13.2
+Version:        1.13.3
 Release:        0
 Summary:        Documentation for elixir
 License:        Apache-2.0

elixir.spec: same change
++++++ elixir-1.13.2.tar.gz -> elixir-1.13.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/CHANGELOG.md 
new/elixir-1.13.3/CHANGELOG.md
--- old/elixir-1.13.2/CHANGELOG.md      2022-01-13 10:51:17.000000000 +0100
+++ new/elixir-1.13.3/CHANGELOG.md      2022-02-09 16:26:17.000000000 +0100
@@ -128,6 +128,30 @@
 
 Finally, the `Code` module has also been augmented with two functions: 
`Code.string_to_quoted_with_comments/2` and `Code.quoted_to_algebra/2`. Those 
functions allow someone to retrieve the Elixir AST with their original source 
code comments, and then convert this AST to formatted code. In other words, 
those functions provide a wrapper around the Elixir Code Formatter, supporting 
developers who wish to create tools that directly manipulate and custom format 
Elixir source code.
 
+## v1.13.3 (2022-02-09)
+
+### 1. Enhancements
+
+#### Mix
+
+  * [mix format] Supply file and line to formatter plugins
+  * [mix format] Support embedded Elixir expressions inside formatter plugins
+
+### 2. Bug fixes
+
+#### Elixir
+
+  * [Code] Fix duplicate bindings causing errors during evaluation
+  * [Kernel] Make sure signatures stored in the Documentation chunk does not 
contain newlines
+  * [Kernel] Fix infinite loop when compiling guards with recursive map access
+  * [Macro] Fix error on `Macro.to_string/1` when the plain alias `Elixir` is 
given
+  * [String] Fix error for certain codepoint combinations in 
`String.split_at/2`
+
+#### Mix
+
+  * [mix compile] Recompile project files when exports from dependencies change
+  * [mix test] Fix total coverage always showing in red even when above the 
threshold
+
 ## v1.13.2 (2022-01-13)
 
 ### 1. Enhancements
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/VERSION new/elixir-1.13.3/VERSION
--- old/elixir-1.13.2/VERSION   2022-01-13 10:51:17.000000000 +0100
+++ new/elixir-1.13.3/VERSION   2022-02-09 16:26:17.000000000 +0100
@@ -1 +1 @@
-1.13.2
\ No newline at end of file
+1.13.3
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/bin/elixir new/elixir-1.13.3/bin/elixir
--- old/elixir-1.13.2/bin/elixir        2022-01-13 10:51:17.000000000 +0100
+++ new/elixir-1.13.3/bin/elixir        2022-02-09 16:26:17.000000000 +0100
@@ -1,7 +1,7 @@
 #!/bin/sh
 set -e
 
-ELIXIR_VERSION=1.13.2
+ELIXIR_VERSION=1.13.3
 
 if [ $# -eq 0 ] || { [ $# -eq 1 ] && { [ "$1" = "--help" ] || [ "$1" = "-h" ]; 
}; }; then
   cat <<USAGE >&2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/bin/elixir.bat 
new/elixir-1.13.3/bin/elixir.bat
--- old/elixir-1.13.2/bin/elixir.bat    2022-01-13 10:51:17.000000000 +0100
+++ new/elixir-1.13.3/bin/elixir.bat    2022-02-09 16:26:17.000000000 +0100
@@ -1,6 +1,6 @@
 @if defined ELIXIR_CLI_ECHO (@echo on) else (@echo off)
 
-set ELIXIR_VERSION=1.13.2
+set ELIXIR_VERSION=1.13.3
 
 setlocal enabledelayedexpansion
 if    ""%1""==""""                if ""%2""=="""" goto documentation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/lib/code/formatter.ex 
new/elixir-1.13.3/lib/elixir/lib/code/formatter.ex
--- old/elixir-1.13.2/lib/elixir/lib/code/formatter.ex  2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/lib/code/formatter.ex  2022-02-09 
16:26:17.000000000 +0100
@@ -177,6 +177,7 @@
   defp state(comments, opts) do
     force_do_end_blocks = Keyword.get(opts, :force_do_end_blocks, false)
     locals_without_parens = Keyword.get(opts, :locals_without_parens, [])
+    file = Keyword.get(opts, :file, nil)
     sigils = Keyword.get(opts, :sigils, [])
 
     sigils =
@@ -199,7 +200,8 @@
       operand_nesting: 2,
       skip_eol: false,
       comments: comments,
-      sigils: sigils
+      sigils: sigils,
+      file: file
     }
   end
 
@@ -1320,7 +1322,14 @@
       entries =
         case state.sigils do
           %{^name => callback} ->
-            case callback.(hd(entries), sigil: List.to_atom([name]), 
modifiers: modifiers) do
+            metadata = [
+              file: state.file,
+              line: meta[:line],
+              sigil: List.to_atom([name]),
+              modifiers: modifiers
+            ]
+
+            case callback.(hd(entries), metadata) do
               binary when is_binary(binary) ->
                 [binary]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/lib/code/normalizer.ex 
new/elixir-1.13.3/lib/elixir/lib/code/normalizer.ex
--- old/elixir-1.13.2/lib/elixir/lib/code/normalizer.ex 2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/lib/code/normalizer.ex 2022-02-09 
16:26:17.000000000 +0100
@@ -251,12 +251,16 @@
 
     if is_atom(literal) and Code.Identifier.classify(literal) == :alias and
          is_nil(meta[:delimiter]) do
-      "Elixir." <> segments = Atom.to_string(literal)
-
       segments =
-        segments
-        |> String.split(".")
-        |> Enum.map(&String.to_atom/1)
+        case Atom.to_string(literal) do
+          "Elixir" ->
+            [:"Elixir"]
+
+          "Elixir." <> segments ->
+            segments
+            |> String.split(".")
+            |> Enum.map(&String.to_atom/1)
+        end
 
       {:__aliases__, meta, segments}
     else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/lib/map.ex 
new/elixir-1.13.3/lib/elixir/lib/map.ex
--- old/elixir-1.13.2/lib/elixir/lib/map.ex     2022-01-13 10:51:17.000000000 
+0100
+++ new/elixir-1.13.3/lib/elixir/lib/map.ex     2022-02-09 16:26:17.000000000 
+0100
@@ -214,7 +214,24 @@
 
   """
   @spec new(Enumerable.t(), (term -> {key, value})) :: map
-  def new(enumerable, transform) when is_function(transform, 1) do
+  def new(enumerable, transform)
+  def new(%_{} = enumerable, transform), do: new_from_enum(enumerable, 
transform)
+  def new(%{} = map, transform), do: new_from_map(map, transform)
+  def new(enumerable, transform), do: new_from_enum(enumerable, transform)
+
+  defp new_from_map(map, transform) when is_function(transform, 1) do
+    iter = :maps.iterator(map)
+    next = :maps.next(iter)
+    :maps.from_list(do_map(next, transform))
+  end
+
+  defp do_map(:none, _fun), do: []
+
+  defp do_map({key, value, iter}, transform) do
+    [transform.({key, value}) | do_map(:maps.next(iter), transform)]
+  end
+
+  defp new_from_enum(enumerable, transform) when is_function(transform, 1) do
     enumerable
     |> Enum.map(transform)
     |> :maps.from_list()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/lib/module/types/pattern.ex 
new/elixir-1.13.3/lib/elixir/lib/module/types/pattern.ex
--- old/elixir-1.13.2/lib/elixir/lib/module/types/pattern.ex    2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/lib/module/types/pattern.ex    2022-02-09 
16:26:17.000000000 +0100
@@ -403,10 +403,8 @@
     # bar, {:ok, baz}
     # bar, {:ok, bat}
 
-    expanded_args =
-      args
-      |> Enum.map(&flatten_union(&1, context))
-      |> cartesian_product()
+    flatten_args = Enum.map(args, &flatten_union(&1, context))
+    cartesian_args = cartesian_product(flatten_args)
 
     # Remove clauses that do not match the expected type
     # Ignore type variables in parameters by changing them to dynamic
@@ -425,11 +423,11 @@
     # the type contexts from unifying argument and parameter to
     # infer type variables in arguments
     result =
-      flat_map_ok(expanded_args, fn expanded_args ->
+      flat_map_ok(cartesian_args, fn cartesian_args ->
         result =
           Enum.flat_map(clauses, fn {params, return} ->
             result =
-              map_ok(Enum.zip(expanded_args, params), fn {arg, param} ->
+              map_ok(Enum.zip(cartesian_args, params), fn {arg, param} ->
                 case unify(arg, param, stack, context) do
                   {:ok, _type, context} -> {:ok, context}
                   {:error, reason} -> {:error, reason}
@@ -453,7 +451,13 @@
       {:ok, returns_contexts} ->
         {success_returns, contexts} = Enum.unzip(returns_contexts)
         contexts = Enum.concat(contexts)
-        indexes = Enum.uniq(Enum.flat_map(args, 
&collect_var_indexes_from_type/1))
+
+        indexes =
+          for types <- flatten_args,
+              type <- types,
+              index <- collect_var_indexes_from_type(type),
+              do: index,
+              uniq: true
 
         # Build unions from collected type contexts to unify with
         # type variables from arguments
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/lib/string.ex 
new/elixir-1.13.3/lib/elixir/lib/string.ex
--- old/elixir-1.13.2/lib/elixir/lib/string.ex  2022-01-13 10:51:17.000000000 
+0100
+++ new/elixir-1.13.3/lib/elixir/lib/string.ex  2022-02-09 16:26:17.000000000 
+0100
@@ -2723,12 +2723,16 @@
             graphemes_and_length: 1,
             reverse_characters_to_binary: 1}
 
-  defp byte_size_remaining_at(binary, 0) do
-    byte_size(binary)
+  defp byte_size_unicode(binary) when is_binary(binary), do: byte_size(binary)
+  defp byte_size_unicode([head]), do: byte_size_unicode(head)
+  defp byte_size_unicode([head | tail]), do: byte_size_unicode(head) + 
byte_size_unicode(tail)
+
+  defp byte_size_remaining_at(unicode, 0) do
+    byte_size_unicode(unicode)
   end
 
-  defp byte_size_remaining_at(binary, n) do
-    case :unicode_util.gc(binary) do
+  defp byte_size_remaining_at(unicode, n) do
+    case :unicode_util.gc(unicode) do
       [_] -> 0
       [_ | rest] -> byte_size_remaining_at(rest, n - 1)
       [] -> 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/src/elixir.erl 
new/elixir-1.13.3/lib/elixir/src/elixir.erl
--- old/elixir-1.13.2/lib/elixir/src/elixir.erl 2022-01-13 10:51:17.000000000 
+0100
+++ new/elixir-1.13.3/lib/elixir/src/elixir.erl 2022-02-09 16:26:17.000000000 
+0100
@@ -254,7 +254,7 @@
 eval_forms(Tree, Binding, Opts) when is_list(Opts) ->
   eval_forms(Tree, Binding, env_for_eval(Opts));
 eval_forms(Tree, RawBinding, OrigE) ->
-  {Vars, Binding} = normalize_binding(RawBinding, [], [], 0),
+  {Vars, Binding} = normalize_binding(RawBinding, #{}, [], 0),
   E = elixir_env:with_vars(OrigE, Vars),
   {_, S} = elixir_env:env_to_erl(E),
   {Erl, NewErlS, NewExS, NewE} = quoted_to_erl(Tree, E, S),
@@ -275,12 +275,19 @@
       {Value, elixir_erl_var:dump_binding(NewBinding, NewExS, NewErlS), NewE}
   end.
 
-normalize_binding([{Key, Value} | Binding], Vars, Acc, I) when is_atom(Key) ->
-  normalize_binding(Binding, [{{Key, nil}, I} | Vars], [{{Key, nil}, Value} | 
Acc], I + 1);
-normalize_binding([{Pair, Value} | Binding], Vars, Acc, I) ->
-  normalize_binding(Binding, [{Pair, I} | Vars], [{Pair, Value} | Acc], I + 1);
-normalize_binding([], Vars, Acc, _I) ->
-  {maps:from_list(Vars), Acc}.
+normalize_binding([Binding | NextBindings], VarsMap, Normalized, Counter) ->
+  {Pair, Value} = normalize_pair(Binding),
+  case VarsMap of
+    #{Pair := _} ->
+      normalize_binding(NextBindings, VarsMap, [{Pair, Value} | Normalized], 
Counter);
+    #{} ->
+      normalize_binding(NextBindings, VarsMap#{Pair => Counter}, [{Pair, 
Value} | Normalized], Counter + 1)
+  end;
+normalize_binding([], VarsMap, Normalized, _Counter) ->
+  {VarsMap, Normalized}.
+
+normalize_pair({Key, Value}) when is_atom(Key) -> {{Key, nil}, Value};
+normalize_pair({Pair, Value}) -> {Pair, Value}.
 
 recur_eval([Expr | Exprs], Binding, Env) ->
   {value, Value, NewBinding} =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/src/elixir_erl.erl 
new/elixir-1.13.3/lib/elixir/src/elixir_erl.erl
--- old/elixir-1.13.2/lib/elixir/src/elixir_erl.erl     2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/src/elixir_erl.erl     2022-02-09 
16:26:17.000000000 +0100
@@ -552,7 +552,9 @@
   <<"%", ('Elixir.Kernel':inspect(Module))/binary, "{}">>;
 
 signature_to_binary(_, Name, Signature) ->
-  'Elixir.Macro':to_string({Name, [{closing, []}], Signature}).
+  Quoted = {Name, [{closing, []}], Signature},
+  Doc = 
'Elixir.Inspect.Algebra':format('Elixir.Code':quoted_to_algebra(Quoted), 
infinity),
+  'Elixir.IO':iodata_to_binary(Doc).
 
 checker_chunk(#{definitions := Definitions, deprecated := Deprecated, 
is_behaviour := IsBehaviour}) ->
   DeprecatedMap = maps:from_list(Deprecated),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.13.2/lib/elixir/test/elixir/code_formatter/general_test.exs 
new/elixir-1.13.3/lib/elixir/test/elixir/code_formatter/general_test.exs
--- old/elixir-1.13.2/lib/elixir/test/elixir/code_formatter/general_test.exs    
2022-01-13 10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/test/elixir/code_formatter/general_test.exs    
2022-02-09 16:26:17.000000000 +0100
@@ -126,7 +126,7 @@
       """
 
       formatter = fn content, opts ->
-        assert opts == [sigil: :W, modifiers: []]
+        assert opts == [file: nil, line: 1, sigil: :W, modifiers: []]
         content |> String.split(~r/ +/) |> Enum.join(" ")
       end
 
@@ -141,7 +141,7 @@
       """
 
       formatter = fn content, opts ->
-        assert opts == [sigil: :W, modifiers: 'abc']
+        assert opts == [file: nil, line: 1, sigil: :W, modifiers: 'abc']
         content |> String.split(~r/ +/) |> Enum.join(" ")
       end
 
@@ -162,7 +162,7 @@
       """
 
       formatter = fn content, opts ->
-        assert opts == [sigil: :W, modifiers: []]
+        assert opts == [file: nil, line: 1, sigil: :W, modifiers: []]
         content |> String.split(~r/ +/) |> Enum.join(" ")
       end
 
@@ -189,7 +189,7 @@
       """
 
       formatter = fn content, opts ->
-        assert opts == [sigil: :W, modifiers: 'abc']
+        assert opts == [file: nil, line: 2, sigil: :W, modifiers: 'abc']
         content |> String.split(~r/ +/) |> Enum.join("\n")
       end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.13.2/lib/elixir/test/elixir/code_normalizer/formatted_ast_test.exs 
new/elixir-1.13.3/lib/elixir/test/elixir/code_normalizer/formatted_ast_test.exs
--- 
old/elixir-1.13.2/lib/elixir/test/elixir/code_normalizer/formatted_ast_test.exs 
    2022-01-13 10:51:17.000000000 +0100
+++ 
new/elixir-1.13.3/lib/elixir/test/elixir/code_normalizer/formatted_ast_test.exs 
    2022-02-09 16:26:17.000000000 +0100
@@ -115,6 +115,7 @@
 
     test "does not reformat aliases" do
       assert_same ~S[:"Elixir.String"]
+      assert_same ~S[:"Elixir"]
     end
 
     test "quoted operators" do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.13.2/lib/elixir/test/elixir/code_normalizer/quoted_ast_test.exs 
new/elixir-1.13.3/lib/elixir/test/elixir/code_normalizer/quoted_ast_test.exs
--- 
old/elixir-1.13.2/lib/elixir/test/elixir/code_normalizer/quoted_ast_test.exs    
    2022-01-13 10:51:17.000000000 +0100
+++ 
new/elixir-1.13.3/lib/elixir/test/elixir/code_normalizer/quoted_ast_test.exs    
    2022-02-09 16:26:17.000000000 +0100
@@ -620,6 +620,7 @@
       assert quoted_to_string({:__block__, [], [:"a\nb\tc"]}, escape: false) 
== ~s/:"a\nb\tc"/
       assert quoted_to_string({:__block__, [], [:"a\nb\tc"]}) == ~S/:"a\nb\tc"/
 
+      assert quoted_to_string(quote(do: :"Elixir")) == "Elixir"
       assert quoted_to_string(quote(do: :"Elixir.Foo")) == "Foo"
       assert quoted_to_string(quote(do: :"Elixir.Foo.Bar")) == "Foo.Bar"
       assert quoted_to_string(quote(do: :"Elixir.foobar")) == 
~S/:"Elixir.foobar"/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/test/elixir/code_test.exs 
new/elixir-1.13.3/lib/elixir/test/elixir/code_test.exs
--- old/elixir-1.13.2/lib/elixir/test/elixir/code_test.exs      2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/test/elixir/code_test.exs      2022-02-09 
16:26:17.000000000 +0100
@@ -52,6 +52,9 @@
       # The order of which values win is not guaranteed, but it should 
evaluate successfully.
       assert Code.eval_string("b = String.Chars.to_string(a)", a: 0, a: 1) ==
                {"1", [{:b, "1"}, {:a, 1}]}
+
+      assert Code.eval_string("b = String.Chars.to_string(a)", a: 0, a: 1, c: 
2) ==
+               {"1", [{:c, 2}, {:b, "1"}, {:a, 1}]}
     end
 
     test "with many options" do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.13.2/lib/elixir/test/elixir/kernel/docs_test.exs 
new/elixir-1.13.3/lib/elixir/test/elixir/kernel/docs_test.exs
--- old/elixir-1.13.2/lib/elixir/test/elixir/kernel/docs_test.exs       
2022-01-13 10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/test/elixir/kernel/docs_test.exs       
2022-02-09 16:26:17.000000000 +0100
@@ -119,6 +119,14 @@
 
           def two_good_names(first, :ok), do: first
           def two_good_names(second, :error), do: second
+
+          def really_long_signature(
+                really_long_var_named_one,
+                really_long_var_named_two,
+                really_long_var_named_three
+              ) do
+            {really_long_var_named_one, really_long_var_named_two, 
really_long_var_named_three}
+          end
         end
       )
 
@@ -128,6 +136,7 @@
       assert [
                arg_names,
                only_underscore,
+               really_long_signature,
                two_good_names,
                with_defaults,
                with_map_and_default,
@@ -141,6 +150,12 @@
       # only_underscore/1
       assert {{:only_underscore, 1}, ["only_underscore(_)"]} = only_underscore
 
+      # really_long_signature/3
+      assert {{:really_long_signature, 3},
+              [
+                "really_long_signature(really_long_var_named_one, 
really_long_var_named_two, really_long_var_named_three)"
+              ]} = really_long_signature
+
       # two_good_names/2
       assert {{:two_good_names, 2}, ["two_good_names(first, atom)"]} = 
two_good_names
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.13.2/lib/elixir/test/elixir/kernel/quote_test.exs 
new/elixir-1.13.3/lib/elixir/test/elixir/kernel/quote_test.exs
--- old/elixir-1.13.2/lib/elixir/test/elixir/kernel/quote_test.exs      
2022-01-13 10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/test/elixir/kernel/quote_test.exs      
2022-02-09 16:26:17.000000000 +0100
@@ -521,6 +521,9 @@
     assert {:__aliases__, [alias: false], [:Foo, :Bar]} = quote(do: Foo.Bar)
     assert {:__aliases__, [alias: false], [:Dict, :Bar]} = quote(do: Dict.Bar)
     assert {:__aliases__, [alias: Dict.Bar], [:SuperDict, :Bar]} = quote(do: 
SuperDict.Bar)
+
+    # Edge-case
+    assert {:__aliases__, _, [Elixir]} = quote(do: Elixir)
   end
 
   test "expand aliases" do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/test/elixir/macro_test.exs 
new/elixir-1.13.3/lib/elixir/test/elixir/macro_test.exs
--- old/elixir-1.13.2/lib/elixir/test/elixir/macro_test.exs     2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/test/elixir/macro_test.exs     2022-02-09 
16:26:17.000000000 +0100
@@ -326,6 +326,8 @@
     end
 
     test "aliases call" do
+      assert macro_to_string(quote(do: Elixir)) == "Elixir"
+      assert macro_to_string(quote(do: Foo)) == "Foo"
       assert macro_to_string(quote(do: Foo.Bar.baz(1, 2, 3))) == 
"Foo.Bar.baz(1, 2, 3)"
       assert macro_to_string(quote(do: Foo.Bar.baz([1, 2, 3]))) == 
"Foo.Bar.baz([1, 2, 3])"
       assert macro_to_string(quote(do: Foo.bar(<<>>, []))) == "Foo.bar(<<>>, 
[])"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.13.2/lib/elixir/test/elixir/module/types/types_test.exs 
new/elixir-1.13.3/lib/elixir/test/elixir/module/types/types_test.exs
--- old/elixir-1.13.2/lib/elixir/test/elixir/module/types/types_test.exs        
2022-01-13 10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/test/elixir/module/types/types_test.exs        
2022-02-09 16:26:17.000000000 +0100
@@ -687,5 +687,18 @@
                end
              ) == :none
     end
+
+    test "no-recursion on guards with map fields" do
+      assert warning(
+               [assigns],
+               (
+                 variable_enum = assigns.variable_enum
+
+                 case true do
+                   _ when variable_enum != nil -> assigns.variable_enum
+                 end
+               )
+             ) == :none
+    end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/elixir/test/elixir/string_test.exs 
new/elixir-1.13.3/lib/elixir/test/elixir/string_test.exs
--- old/elixir-1.13.2/lib/elixir/test/elixir/string_test.exs    2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/elixir/test/elixir/string_test.exs    2022-02-09 
16:26:17.000000000 +0100
@@ -131,6 +131,11 @@
     end
   end
 
+  test "split_at/2 with invalid guard" do
+    assert String.split_at(<<?a, 195, 10, ?a>>, 2) == {<<?a, 195>>, <<10, ?a>>}
+    assert String.split_at(<<107, 205, 135, 184>>, 1) == {<<107, 205, 135>>, 
<<184>>}
+  end
+
   test "upcase/1" do
     assert String.upcase("123 abcd 456 efg hij ( %$#) kl mnop @ qrst = -_ 
uvwxyz") ==
              "123 ABCD 456 EFG HIJ ( %$#) KL MNOP @ QRST = -_ UVWXYZ"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/mix/lib/mix/compilers/elixir.ex 
new/elixir-1.13.3/lib/mix/lib/mix/compilers/elixir.ex
--- old/elixir-1.13.2/lib/mix/lib/mix/compilers/elixir.ex       2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/mix/lib/mix/compilers/elixir.ex       2022-02-09 
16:26:17.000000000 +0100
@@ -2,6 +2,7 @@
   @moduledoc false
 
   @manifest_vsn 13
+  @checkpoint_vsn 2
 
   import Record
 
@@ -102,7 +103,7 @@
           {false, stale, old_lock, old_config}
       end
 
-    {stale_local_mods, stale_local_exports, all_local_exports} =
+    {stale_modules, stale_exports, all_local_exports} =
       stale_local_deps(manifest, stale, modified, all_local_exports)
 
     prev_paths = for source(source: source) <- all_sources, do: source
@@ -120,8 +121,8 @@
           all_modules,
           all_sources,
           removed,
-          stale_local_mods,
-          Map.merge(stale_local_exports, removed_modules),
+          Map.merge(stale_modules, removed_modules),
+          Map.merge(stale_exports, removed_modules),
           dest
         )
       end
@@ -180,7 +181,7 @@
         delete_compiler_info()
       end
     else
-      # We need to return ok if deps_changed? or stale_local_mods changed,
+      # We need to return ok if deps_changed? or stale_modules changed,
       # even if no code was compiled, because we need to propagate the changed
       # status to compile.protocols. This will be the case whenever:
       #
@@ -193,7 +194,7 @@
       # will only compute the diff with current protocols. In fact, there is no
       # need to reconsolidate if an Erlang file changes and it doesn't trigger
       # any other change, but the diff check should be reasonably fast anyway.
-      status = if removed != [] or deps_changed? or stale_local_mods != %{}, 
do: :ok, else: :noop
+      status = if removed != [] or deps_changed? or stale_modules != %{}, do: 
:ok, else: :noop
 
       # If nothing changed but there is one more recent mtime, bump the 
manifest
       if status != :noop or Enum.any?(Map.values(sources_stats), &(elem(&1, 0) 
> modified)) do
@@ -283,8 +284,8 @@
          all_modules,
          all_sources,
          removed,
-         stale_local_mods,
-         stale_local_exports,
+         stale_modules,
+         stale_exports,
          dest
        ) do
     # TODO: Use :maps.from_keys/2 on Erlang/OTP 24+
@@ -294,13 +295,17 @@
           into: %{},
           do: {module, []}
 
-    {checkpoint_stale, checkpoint_modules} = parse_checkpoint(manifest)
+    {checkpoint_stale_modules, checkpoint_stale_exports, checkpoint_modules} =
+      parse_checkpoint(manifest)
+
     modules_to_recompile = Map.merge(checkpoint_modules, modules_to_recompile)
-    stale_local_mods = Map.merge(checkpoint_stale, stale_local_mods)
+    stale_modules = Map.merge(checkpoint_stale_modules, stale_modules)
+    stale_exports = Map.merge(checkpoint_stale_exports, stale_exports)
 
-    if map_size(stale_local_mods) != map_size(checkpoint_stale) or
+    if map_size(stale_modules) != map_size(checkpoint_stale_modules) or
+         map_size(stale_exports) != map_size(checkpoint_stale_exports) or
          map_size(modules_to_recompile) != map_size(checkpoint_modules) do
-      write_checkpoint(manifest, stale_local_mods, modules_to_recompile)
+      write_checkpoint(manifest, stale_modules, stale_exports, 
modules_to_recompile)
     end
 
     sources_stats =
@@ -332,8 +337,8 @@
         all_modules,
         all_sources,
         removed ++ changed,
-        stale_local_mods,
-        stale_local_exports,
+        stale_modules,
+        stale_exports,
         dest
       )
 
@@ -654,16 +659,16 @@
   # files that have changed. Then it recursively figures out
   # all the files that changed (via the module dependencies) and
   # return the non-changed entries and the removed sources.
-  defp update_stale_entries(modules, _sources, [], stale_mods, stale_exports, 
_compile_path)
-       when stale_mods == %{} and stale_exports == %{} do
+  defp update_stale_entries(modules, _sources, [], stale_modules, 
stale_exports, _compile_path)
+       when stale_modules == %{} and stale_exports == %{} do
     {modules, %{}, []}
   end
 
-  defp update_stale_entries(modules, sources, changed, stale_mods, 
stale_exports, compile_path) do
+  defp update_stale_entries(modules, sources, changed, stale_modules, 
stale_exports, compile_path) do
     # TODO: Use :maps.from_keys/2 on Erlang/OTP 24+
     changed = Enum.into(changed, %{}, &{&1, []})
     reducer = &remove_stale_entry(&1, &2, sources, stale_exports, compile_path)
-    remove_stale_entries(modules, %{}, changed, stale_mods, reducer)
+    remove_stale_entries(modules, %{}, changed, stale_modules, reducer)
   end
 
   defp remove_stale_entries(modules, exports, old_changed, old_stale, reducer) 
do
@@ -720,6 +725,8 @@
   defp stale_local_deps(manifest, stale_modules, modified, old_exports) do
     base = Path.basename(manifest)
 
+    # The stale modules so far will become both stale_modules and 
stale_exports,
+    # as any export from a dependency needs to be recompiled.
     # TODO: Use :maps.from_keys/2 on Erlang/OTP 24+
     stale_modules = for module <- stale_modules, do: {module, []}, into: %{}
 
@@ -727,7 +734,7 @@
         not scm.fetchable?,
         manifest = Path.join([opts[:build], ".mix", base]),
         Mix.Utils.last_modified(manifest) > modified,
-        reduce: {stale_modules, %{}, old_exports} do
+        reduce: {stale_modules, stale_modules, old_exports} do
       {modules, exports, new_exports} ->
         {_manifest_modules, dep_sources} = read_manifest(manifest)
 
@@ -1017,19 +1024,19 @@
       (manifest <> ".checkpoint") |> File.read!() |> :erlang.binary_to_term()
     rescue
       _ ->
-        {%{}, %{}}
+        {%{}, %{}, %{}}
     else
-      {@manifest_vsn, stale, recompile_modules} ->
-        {stale, recompile_modules}
+      {@checkpoint_vsn, stale_modules, stale_exports, recompile_modules} ->
+        {stale_modules, stale_exports, recompile_modules}
 
       _ ->
-        {%{}, %{}}
+        {%{}, %{}, %{}}
     end
   end
 
-  defp write_checkpoint(manifest, stale, recompile_modules) do
+  defp write_checkpoint(manifest, stale_modules, stale_exports, 
recompile_modules) do
     File.mkdir_p!(Path.dirname(manifest))
-    term = {@manifest_vsn, stale, recompile_modules}
+    term = {@checkpoint_vsn, stale_modules, stale_exports, recompile_modules}
     checkpoint_data = :erlang.term_to_binary(term, [:compressed])
     File.write!(manifest <> ".checkpoint", checkpoint_data)
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/mix/lib/mix/tasks/format.ex 
new/elixir-1.13.3/lib/mix/lib/mix/tasks/format.ex
--- old/elixir-1.13.2/lib/mix/lib/mix/tasks/format.ex   2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/mix/lib/mix/tasks/format.ex   2022-02-09 
16:26:17.000000000 +0100
@@ -104,11 +104,11 @@
 
   The `opts` passed to `format/2` contains all the formatting options and 
either:
 
-      * `:sigil` (atom) - the sigil being formatted, e.g. `:M`.
+    * `:sigil` (atom) - the sigil being formatted, e.g. `:M`.
 
-      * `:modifiers` (charlist) - list of sigil modifiers.
+    * `:modifiers` (charlist) - list of sigil modifiers.
 
-      * `:extension` (string) - the extension of the file being formatted, 
e.g. `".md"`.
+    * `:extension` (string) - the extension of the file being formatted, e.g. 
`".md"`.
 
   Now any application can use your formatter as follows:
 
@@ -288,7 +288,15 @@
       end
     end
 
-    formatter_opts = Keyword.put(formatter_opts, :plugins, plugins)
+    sigils =
+      for plugin <- plugins,
+          sigil <- find_sigils_from_plugins(plugin, formatter_opts),
+          do: {sigil, &plugin.format(&1, &2 ++ formatter_opts)}
+
+    formatter_opts =
+      formatter_opts
+      |> Keyword.put(:plugins, plugins)
+      |> Keyword.put(:sigils, sigils)
 
     if deps == [] and subs == [] do
       {{formatter_opts, []}, sources}
@@ -496,7 +504,7 @@
 
     cond do
       plugin = find_plugin_for_extension(formatter_opts, ext) ->
-        &plugin.format(&1, [extension: ext] ++ formatter_opts)
+        &plugin.format(&1, [extension: ext, file: file] ++ formatter_opts)
 
       ext in ~w(.ex .exs) ->
         &elixir_format(&1, [file: file] ++ formatter_opts)
@@ -537,12 +545,7 @@
   defp stdin_or_wildcard(path), do: path |> Path.expand() |> 
Path.wildcard(match_dot: true)
 
   defp elixir_format(content, formatter_opts) do
-    sigils =
-      for plugin <- Keyword.fetch!(formatter_opts, :plugins),
-          sigil <- find_sigils_from_plugins(plugin, formatter_opts),
-          do: {sigil, &plugin.format(&1, &2 ++ formatter_opts)}
-
-    IO.iodata_to_binary([Code.format_string!(content, [sigils: sigils] ++ 
formatter_opts), ?\n])
+    IO.iodata_to_binary([Code.format_string!(content, formatter_opts), ?\n])
   end
 
   defp find_sigils_from_plugins(plugin, formatter_opts) do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/mix/lib/mix/tasks/test.coverage.ex 
new/elixir-1.13.3/lib/mix/lib/mix/tasks/test.coverage.ex
--- old/elixir-1.13.2/lib/mix/lib/mix/tasks/test.coverage.ex    2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/mix/lib/mix/tasks/test.coverage.ex    2022-02-09 
16:26:17.000000000 +0100
@@ -350,7 +350,7 @@
     Mix.shell().info("-----------|--------------------------")
     results |> Enum.sort() |> Enum.each(&display(&1, threshold))
     Mix.shell().info("-----------|--------------------------")
-    display({totals, "Total"}, opts)
+    display({totals, "Total"}, threshold)
     Mix.shell().info("")
   end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.13.2/lib/mix/test/mix/tasks/compile.elixir_test.exs 
new/elixir-1.13.3/lib/mix/test/mix/tasks/compile.elixir_test.exs
--- old/elixir-1.13.2/lib/mix/test/mix/tasks/compile.elixir_test.exs    
2022-01-13 10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/mix/test/mix/tasks/compile.elixir_test.exs    
2022-02-09 16:26:17.000000000 +0100
@@ -182,6 +182,11 @@
       Process.put({MixTest.Case.Sample, :application}, extra_applications: 
[:logger])
       File.mkdir_p!("config")
 
+      File.write!("config/config.exs", """
+      import Config
+      config :logger, :level, :debug
+      """)
+
       File.write!("lib/a.ex", """
       defmodule A do
         _ = Logger.metadata()
@@ -234,6 +239,12 @@
       refute_received {:mix_shell, :info, ["Compiled lib/b.ex"]}
       assert File.stat!("_build/dev/lib/sample/.mix/compile.elixir").mtime > 
@old_time
 
+      # No-op does not recompile
+      File.touch!("_build/dev/lib/sample/.mix/compile.elixir", @old_time)
+      assert recompile.() == {:ok, []}
+      refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
+      refute_received {:mix_shell, :info, ["Compiled lib/b.ex"]}
+
       # Changing self fully recompiles
       File.write!("config/config.exs", """
       import Config
@@ -263,6 +274,76 @@
     Application.delete_env(:sample, :foo, persistent: true)
   end
 
+  test "recompiles files when config changes export dependencies" do
+    in_fixture("no_mixfile", fn ->
+      Mix.Project.push(MixTest.Case.Sample)
+      Process.put({MixTest.Case.Sample, :application}, extra_applications: 
[:ex_unit])
+      File.mkdir_p!("config")
+
+      File.write!("lib/a.ex", """
+      defmodule A do
+        def test_struct do
+          %ExUnit.Test{}
+        end
+      end
+      """)
+
+      assert Mix.Tasks.Compile.Elixir.run(["--verbose"]) == {:ok, []}
+      assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
+      assert_received {:mix_shell, :info, ["Compiled lib/b.ex"]}
+
+      recompile = fn ->
+        Mix.ProjectStack.pop()
+        Mix.Project.push(MixTest.Case.Sample)
+        Mix.Tasks.Loadconfig.load_compile("config/config.exs")
+        Mix.Tasks.Compile.Elixir.run(["--verbose"])
+      end
+
+      # Adding config recompiles
+      File.write!("config/config.exs", """
+      import Config
+      config :ex_unit, :some, :config
+      """)
+
+      File.touch!("_build/dev/lib/sample/.mix/compile.elixir", @old_time)
+      assert recompile.() == {:ok, []}
+      assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
+      refute_received {:mix_shell, :info, ["Compiled lib/b.ex"]}
+      assert File.stat!("_build/dev/lib/sample/.mix/compile.elixir").mtime > 
@old_time
+
+      # Changing config recompiles
+      File.write!("config/config.exs", """
+      import Config
+      config :ex_unit, :some, :another
+      """)
+
+      File.touch!("_build/dev/lib/sample/.mix/compile.elixir", @old_time)
+      assert recompile.() == {:ok, []}
+      assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
+      refute_received {:mix_shell, :info, ["Compiled lib/b.ex"]}
+      assert File.stat!("_build/dev/lib/sample/.mix/compile.elixir").mtime > 
@old_time
+
+      # Removing config recompiles
+      File.write!("config/config.exs", """
+      import Config
+      """)
+
+      File.touch!("_build/dev/lib/sample/.mix/compile.elixir", @old_time)
+      assert recompile.() == {:ok, []}
+      assert_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
+      refute_received {:mix_shell, :info, ["Compiled lib/b.ex"]}
+      assert File.stat!("_build/dev/lib/sample/.mix/compile.elixir").mtime > 
@old_time
+
+      # No-op does not recompile
+      File.touch!("_build/dev/lib/sample/.mix/compile.elixir", @old_time)
+      assert recompile.() == {:ok, []}
+      refute_received {:mix_shell, :info, ["Compiled lib/a.ex"]}
+      refute_received {:mix_shell, :info, ["Compiled lib/b.ex"]}
+    end)
+  after
+    Application.delete_env(:ex_unit, :some, persistent: true)
+  end
+
   test "recompiles files when config changes with crashes" do
     in_fixture("no_mixfile", fn ->
       Mix.Project.push(MixTest.Case.Sample)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.13.2/lib/mix/test/mix/tasks/format_test.exs 
new/elixir-1.13.3/lib/mix/test/mix/tasks/format_test.exs
--- old/elixir-1.13.2/lib/mix/test/mix/tasks/format_test.exs    2022-01-13 
10:51:17.000000000 +0100
+++ new/elixir-1.13.3/lib/mix/test/mix/tasks/format_test.exs    2022-02-09 
16:26:17.000000000 +0100
@@ -206,6 +206,8 @@
       assert opts[:from_formatter_exs] == :yes
       assert opts[:sigil] == :W
       assert opts[:modifiers] == 'abc'
+      assert opts[:line] == 2
+      assert opts[:file] =~ ~r/\/a\.ex$/
       contents |> String.split(~r/\s/) |> Enum.join("\n")
     end
   end
@@ -247,12 +249,15 @@
 
     def features(opts) do
       assert opts[:from_formatter_exs] == :yes
-      [extensions: ~w(.w)]
+      [extensions: ~w(.w), sigils: [:W]]
     end
 
     def format(contents, opts) do
       assert opts[:from_formatter_exs] == :yes
       assert opts[:extension] == ".w"
+      assert opts[:file] =~ ~r/\/a\.w$/
+      assert [W: sigil_fun] = opts[:sigils]
+      assert is_function(sigil_fun, 2)
       contents |> String.split(~r/\s/) |> Enum.join("\n")
     end
   end

Reply via email to