Skip to content

Commit

Permalink
Do not override signatures of Elixir functions, closes phoenixframewo…
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Sep 25, 2022
1 parent 5d81c71 commit 1fcf180
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 17 deletions.
22 changes: 19 additions & 3 deletions lib/phoenix_component/declarative.ex
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,31 @@ defmodule Phoenix.Component.Declarative do
end
end

defp annotate_call(_kind, {name, meta, [{:\\, _, _} = arg]}),
do: {name, meta, [arg]}
defp annotate_call(kind, {name, meta, [{:\\, default_meta, [left, right]}]}),
do: {name, meta, [{:\\, default_meta, [annotate_arg(kind, left), right]}]}

defp annotate_call(kind, {name, meta, [arg]}),
do: {name, meta, [quote(do: unquote(__MODULE__).__pattern__!(unquote(kind), unquote(arg)))]}
do: {name, meta, [annotate_arg(kind, arg)]}

defp annotate_call(_kind, left),
do: left

defp annotate_arg(kind, {:=, meta, [{name, _, ctx} = var, arg]}) when is_atom(name) and is_atom(ctx) do
{:=, meta, [var, quote(do: unquote(__MODULE__).__pattern__!(unquote(kind), unquote(arg)))]}
end

defp annotate_arg(kind, {:=, meta, [arg, {name, _, ctx} = var]}) when is_atom(name) and is_atom(ctx) do
{:=, meta, [quote(do: unquote(__MODULE__).__pattern__!(unquote(kind), unquote(arg))), var]}
end

defp annotate_arg(kind, {name, meta, ctx} = var) when is_atom(name) and is_atom(ctx) do
{:=, meta, [quote(do: unquote(__MODULE__).__pattern__!(unquote(kind), _)), var]}
end

defp annotate_arg(kind, arg) do
quote(do: unquote(__MODULE__).__pattern__!(unquote(kind), unquote(arg)))
end

## Attrs/slots

@doc false
Expand Down
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Phoenix.LiveView.MixProject do
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
elixirc_paths: elixirc_paths(Mix.env()),
test_options: [docs: true],
package: package(),
xref: [exclude: [Floki]],
deps: deps(),
Expand Down
36 changes: 23 additions & 13 deletions test/phoenix_component/declarative_assigns_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,20 @@ defmodule Phoenix.ComponentDeclarativeAssignsTest do
end
end

test "does not override signature of Elixir functions" do
{:docs_v1, _, :elixir, "text/markdown", _, _, docs} =
Code.fetch_docs(Phoenix.LiveViewTest.FunctionComponentWithAttrs)

assert {{:function, :identity, 1}, _, ["identity(var)"], _, %{}} =
List.keyfind(docs, {:function, :identity, 1}, 0)

assert {{:function, :map_identity, 1}, _, ["map_identity(map)"], _, %{}} =
List.keyfind(docs, {:function, :map_identity, 1}, 0)

assert Phoenix.LiveViewTest.FunctionComponentWithAttrs.identity(:not_a_map) == :not_a_map
assert Phoenix.LiveViewTest.FunctionComponentWithAttrs.identity(%{}) == %{}
end

test "raise if attr :doc is not a string" do
msg = ~r"doc must be a string or false, got: :foo"

Expand Down Expand Up @@ -1363,23 +1377,19 @@ defmodule Phoenix.ComponentDeclarativeAssignsTest do
end

test "does not raise if multiple slots with different names share the same attr names" do
mod = fn ->
defmodule MultipleSlotAttrs do
use Phoenix.Component

slot :foo do
attr :attr, :any
end
defmodule MultipleSlotAttrs do
use Phoenix.Component

slot :bar do
attr :attr, :any
end
slot :foo do
attr :attr, :any
end

def func(assigns), do: ~H[]
slot :bar do
attr :attr, :any
end
end

assert mod.()
def func(assigns), do: ~H[]
end
end

test "raise if slot with name :inner_block has slot attrs" do
Expand Down
5 changes: 4 additions & 1 deletion test/support/live_views/components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ defmodule Phoenix.LiveViewTest.FunctionComponentWithAttrs do
defstruct []
end

def identity(var), do: var
def map_identity(%{} = map), do: map

attr :attr, :any
def fun_attr_any(assigns), do: ~H[]

Expand Down Expand Up @@ -196,7 +199,7 @@ defmodule Phoenix.LiveViewTest.StatefulComponent do
~H"""
<div phx-click="transform" id={@id} phx-target={"#" <> @id <> include_parent_id(@parent_id)}>
<%= @name %> says hi
<%= if @dup_name, do: live_component __MODULE__, id: @dup_name, name: @dup_name %>
<%= if @dup_name, do: live_component(__MODULE__, id: @dup_name, name: @dup_name) %>
</div>
"""
end
Expand Down

0 comments on commit 1fcf180

Please sign in to comment.