From 2c4b3522db38024e91bba137ed2d7f798df61381 Mon Sep 17 00:00:00 2001 From: Lukasz Samson Date: Tue, 26 Sep 2023 08:22:43 +0200 Subject: [PATCH] don't stringify complex types when building parameter list Fixes https://github.com/elixir-lsp/elixir_sense/issues/279 --- lib/elixir_sense/core/introspection.ex | 10 ++++----- lib/elixir_sense/core/type_info.ex | 16 +++++++++----- .../providers/suggestion/complete.ex | 1 - .../providers/suggestion/complete_test.exs | 21 +++++++++++++++++-- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/lib/elixir_sense/core/introspection.ex b/lib/elixir_sense/core/introspection.ex index 26731589..078f63df 100644 --- a/lib/elixir_sense/core/introspection.ex +++ b/lib/elixir_sense/core/introspection.ex @@ -406,7 +406,7 @@ defmodule ElixirSense.Core.Introspection do results = for {{_name, _arity}, [params | _]} = spec <- specs do - params = TypeInfo.extract_params(params) |> Enum.map(&Atom.to_string/1) + params = TypeInfo.extract_params(params) %{ name: Atom.to_string(fun), @@ -527,7 +527,7 @@ defmodule ElixirSense.Core.Introspection do results = for {{_name, arity}, [params | _]} <- specs do - fun_args_text = TypeInfo.extract_params(params) |> Enum.map_join(", ", &Atom.to_string/1) + fun_args_text = TypeInfo.extract_params(params) |> Enum.join(", ") %{ module: mod, @@ -1846,7 +1846,7 @@ defmodule ElixirSense.Core.Introspection do # we don't expect macros here case TypeInfo.get_callback(behaviour, f, arity) do {_, [params | _]} -> - TypeInfo.extract_params(params) |> Enum.map(&Atom.to_string/1) + TypeInfo.extract_params(params) _ -> # provide dummy @@ -1860,11 +1860,11 @@ defmodule ElixirSense.Core.Introspection do [{:attribute, _, :spec, {{^f, ^arity}, [params | _]}}] -> # erlang doc with signature meta - moduleless form - TypeInfo.extract_params(params) |> Enum.map(&Atom.to_string/1) + TypeInfo.extract_params(params) [{:attribute, _, :spec, {{^mod, ^f, ^arity}, [params | _]}}] -> # erlang doc with signature meta - form with module - TypeInfo.extract_params(params) |> Enum.map(&Atom.to_string/1) + TypeInfo.extract_params(params) end end end diff --git a/lib/elixir_sense/core/type_info.ex b/lib/elixir_sense/core/type_info.ex index ff897fad..d79204c7 100644 --- a/lib/elixir_sense/core/type_info.ex +++ b/lib/elixir_sense/core/type_info.ex @@ -685,17 +685,23 @@ defmodule ElixirSense.Core.TypeInfo do end def extract_params(type) do - case Typespec.spec_to_quoted(:dummy, type) do + quoted = Typespec.spec_to_quoted(:dummy, type) + + case quoted do {:when, _, [{:"::", _, [{:dummy, _, args}, _res]}, _var_args]} -> args {:"::", _, [{:dummy, _, args}, _res]} -> args end |> Enum.map(fn arg -> case arg do - {:"::", _, [left, _right]} -> left - other -> other + {:"::", _, [{atom, _, _}, _right]} when is_atom(atom) -> to_string(atom) + {:|, _, [_left, _right]} -> "term" + [_ | _] -> "list" + {_, _} -> "tuple" + {:{}, _, _} -> "tuple" + %{} -> "map" + {atom, _, _} when is_atom(atom) -> to_string(atom) + _other -> "term" end - |> Macro.to_string() - |> String.to_atom() end) end diff --git a/lib/elixir_sense/providers/suggestion/complete.ex b/lib/elixir_sense/providers/suggestion/complete.ex index 5dc8f2dd..8483deaf 100644 --- a/lib/elixir_sense/providers/suggestion/complete.ex +++ b/lib/elixir_sense/providers/suggestion/complete.ex @@ -1125,7 +1125,6 @@ defmodule ElixirSense.Providers.Suggestion.Complete do defp format_params({{_name, _arity}, [params | _]}, _arity_1) do TypeInfo.extract_params(params) - |> Enum.map(&Atom.to_string/1) end defp format_params(nil, 0), do: [] diff --git a/test/elixir_sense/providers/suggestion/complete_test.exs b/test/elixir_sense/providers/suggestion/complete_test.exs index 6d1424c3..d7e2c0d7 100644 --- a/test/elixir_sense/providers/suggestion/complete_test.exs +++ b/test/elixir_sense/providers/suggestion/complete_test.exs @@ -1943,7 +1943,7 @@ defmodule ElixirSense.Providers.Suggestion.CompleteTest do name: "or", spec: "@spec boolean() or boolean() :: boolean()", type: :function, - args: "boolean(), boolean()", + args: "boolean, boolean", origin: ":erlang", summary: "" }, @@ -1964,7 +1964,7 @@ defmodule ElixirSense.Providers.Suggestion.CompleteTest do name: "and", spec: "@spec boolean() and boolean() :: boolean()", type: :function, - args: "boolean(), boolean()", + args: "boolean, boolean", origin: ":erlang", summary: "" }, @@ -2020,6 +2020,23 @@ defmodule ElixirSense.Providers.Suggestion.CompleteTest do end end + test "provide doc and specs for erlang functions with args from typespec" do + assert [ + %{ + name: "handle_call", + args_list: ["call", "from", "state"] + }, + %{ + name: "handle_cast", + args_list: ["tuple", "state"] + }, + %{ + name: "handle_info", + args_list: ["term", "state"] + } + ] = expand(~c":pg.handle_") + end + test "complete after ! operator" do assert [%{name: "is_binary"}] = expand(~c"!is_bina") end