diff --git a/lib/elixir/lib/code/formatter.ex b/lib/elixir/lib/code/formatter.ex index b9774c2172..6410b0430c 100644 --- a/lib/elixir/lib/code/formatter.ex +++ b/lib/elixir/lib/code/formatter.ex @@ -694,9 +694,16 @@ defmodule Code.Formatter do op in @left_new_line_before_binary_operators -> op_string = op_string <> " " - doc = glue(left, concat(op_string, nest_by_length(right, op_string))) - doc = if Keyword.get(meta, :eol, false), do: force_break(doc), else: doc - if op_info == parent_info, do: doc, else: group(doc) + + # If the parent is of the same type (computed via same precedence), + # we cannot group the left side yet. + left = if op_info == parent_info, do: left, else: group(left) + + # The right side is never the same operator, so we can group and nest + right = group(nest_by_length(right, op_string)) + + doc = glue(left, concat(op_string, right)) + if Keyword.get(meta, :eol, false), do: force_break(doc), else: doc op in @right_new_line_before_binary_operators -> op_string = op_string <> " " @@ -707,23 +714,19 @@ defmodule Code.Formatter do if op_info == parent_info do nest_by_length(left, op_string) else - left + group(left) end - # If the right side is of the same type, we do the nesting above - # on the left side later on. + # If the right side is of the same type, we will keep recursing + # and do the nesting on the left side later on (as written above). right = case right_arg do {^op, _, [_, _]} -> right - _ -> nest_by_length(right, op_string) + _ -> right |> nest_by_length(op_string) |> force_keyword(right_arg) |> group() end - # Finally, group keyword args such as when foo: bar, baz: bat - right = if keyword?(right_arg), do: group(force_keyword(right, right_arg)), else: right - doc = glue(left, concat(op_string, right)) - doc = if Keyword.get(meta, :eol, false), do: force_break(doc), else: doc - if op_info == parent_info, do: doc, else: group(doc) + if Keyword.get(meta, :eol, false), do: force_break(doc), else: doc true -> next_break_fits? = diff --git a/lib/elixir/lib/kernel/typespec.ex b/lib/elixir/lib/kernel/typespec.ex index d53eb7e316..6c59babf3a 100644 --- a/lib/elixir/lib/kernel/typespec.ex +++ b/lib/elixir/lib/kernel/typespec.ex @@ -379,7 +379,8 @@ defmodule Kernel.Typespec do def spec_to_signature(other), do: type_to_signature(other) @doc false - def type_to_signature({:::, _, [{name, _, context}, _]}) when is_atom(name) and is_atom(context), + def type_to_signature({:::, _, [{name, _, context}, _]}) + when is_atom(name) and is_atom(context), do: {name, 0} def type_to_signature({:::, _, [{name, _, args}, _]}) when is_atom(name), diff --git a/lib/elixir/lib/macro.ex b/lib/elixir/lib/macro.ex index 89b9c4f8dd..2b8f9d3812 100644 --- a/lib/elixir/lib/macro.ex +++ b/lib/elixir/lib/macro.ex @@ -404,7 +404,8 @@ defmodule Macro do defp find_invalid({left, right}), do: find_invalid(left) || find_invalid(right) - defp find_invalid({left, meta, right}) when is_list(meta) and (is_atom(right) or is_list(right)), + defp find_invalid({left, meta, right}) + when is_list(meta) and (is_atom(right) or is_list(right)), do: find_invalid(left) || find_invalid(right) defp find_invalid(list) when is_list(list), do: Enum.find_value(list, &find_invalid/1)