From 7930becae5fcf88f6ea4f92bd7da9471aa0a348b Mon Sep 17 00:00:00 2001 From: Lukasz Samson Date: Thu, 15 Feb 2024 21:27:40 +0100 Subject: [PATCH] return metadata from completions provider Fixes https://github.com/elixir-lsp/elixir-ls/issues/952 --- .../lib/language_server/markdown_utils.ex | 95 +++++++++++++++++++ .../language_server/providers/completion.ex | 12 ++- .../lib/language_server/providers/hover.ex | 91 +----------------- 3 files changed, 105 insertions(+), 93 deletions(-) diff --git a/apps/language_server/lib/language_server/markdown_utils.ex b/apps/language_server/lib/language_server/markdown_utils.ex index 680df1b89..053c6ca54 100644 --- a/apps/language_server/lib/language_server/markdown_utils.ex +++ b/apps/language_server/lib/language_server/markdown_utils.ex @@ -38,4 +38,99 @@ defmodule ElixirLS.LanguageServer.MarkdownUtils do |> String.replace_trailing("\n", "") end) <> "\n" end + + def get_metadata_md(metadata) do + text = + metadata + |> Enum.sort() + |> Enum.map(&get_metadata_entry_md/1) + |> Enum.reject(&is_nil/1) + |> Enum.join("\n\n") + + case text do + "" -> "" + not_empty -> not_empty <> "\n\n" + end + end + + # erlang name + defp get_metadata_entry_md({:name, _text}), do: nil + + # erlang signature + defp get_metadata_entry_md({:signature, _text}), do: nil + + # erlang edit_url + defp get_metadata_entry_md({:edit_url, _text}), do: nil + + # erlang :otp_doc_vsn + defp get_metadata_entry_md({:otp_doc_vsn, _text}), do: nil + + # erlang :source + defp get_metadata_entry_md({:source, _text}), do: nil + + # erlang :types + defp get_metadata_entry_md({:types, _text}), do: nil + + # erlang :equiv + defp get_metadata_entry_md({:equiv, {:function, name, arity}}) do + "**Equivalent** #{name}/#{arity}" + end + + defp get_metadata_entry_md({:deprecated, text}) do + "**Deprecated** #{text}" + end + + defp get_metadata_entry_md({:since, text}) do + "**Since** #{text}" + end + + defp get_metadata_entry_md({:group, text}) do + "**Group** #{text}" + end + + defp get_metadata_entry_md({:guard, true}) do + "**Guard**" + end + + defp get_metadata_entry_md({:hidden, true}) do + "**Hidden**" + end + + defp get_metadata_entry_md({:builtin, true}) do + "**Built-in**" + end + + defp get_metadata_entry_md({:implementing, module}) do + "**Implementing behaviour** #{inspect(module)}" + end + + defp get_metadata_entry_md({:implementing_module_app, app}) do + "**Behaviour defined in application** #{inspect(app)}" + end + + defp get_metadata_entry_md({:optional, true}) do + "**Optional**" + end + + defp get_metadata_entry_md({:optional, false}), do: nil + + defp get_metadata_entry_md({:overridable, true}) do + "**Overridable**" + end + + defp get_metadata_entry_md({:overridable, false}), do: nil + + defp get_metadata_entry_md({:opaque, true}) do + "**Opaque**" + end + + defp get_metadata_entry_md({:defaults, _}), do: nil + + defp get_metadata_entry_md({:delegate_to, {m, f, a}}) do + "**Delegates to** #{inspect(m)}.#{f}/#{a}" + end + + defp get_metadata_entry_md({key, value}) do + "**#{key}** #{inspect(value)}" + end end diff --git a/apps/language_server/lib/language_server/providers/completion.ex b/apps/language_server/lib/language_server/providers/completion.ex index 9adc37ed5..5b950b6ed 100644 --- a/apps/language_server/lib/language_server/providers/completion.ex +++ b/apps/language_server/lib/language_server/providers/completion.ex @@ -12,6 +12,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do import ElixirLS.LanguageServer.Protocol, only: [range: 4] alias ElixirSense.Providers.Suggestion.Matcher alias ElixirSense.Core.Normalized.Code, as: NormalizedCode + alias ElixirLS.LanguageServer.MarkdownUtils require Logger @enforce_keys [:label, :kind, :insert_text, :priority, :tags] @@ -610,7 +611,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do label: name, kind: kind, detail: detail, - documentation: summary, + documentation: summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata), insert_text: insert_text, filter_text: name, label_details: label_details, @@ -661,7 +662,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do label: label, kind: :interface, detail: "#{origin} #{subtype}", - documentation: summary, + documentation: summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata), insert_text: insert_text, priority: 12, filter_text: filter_text, @@ -695,7 +696,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do label: label, kind: :interface, detail: "#{origin} protocol function", - documentation: summary, + documentation: summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata), insert_text: insert_text, priority: 12, filter_text: name, @@ -842,7 +843,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do "detail" => "(#{Enum.join(args_list, ", ")})", "description" => if(origin, do: "#{origin}.#{name}/#{arity}", else: "#{name}/#{arity}") }, - documentation: "#{doc}#{formatted_spec}", + documentation: "#{doc}\n\n#{MarkdownUtils.get_metadata_md(metadata)}\n\n#{formatted_spec}", insert_text: snippet, priority: 10, kind: :class, @@ -1307,7 +1308,8 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do "detail" => "(#{Enum.join(args_list, ", ")})", "description" => "#{origin}.#{label}/#{arity}" }, - documentation: summary <> footer, + documentation: + summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata) <> "\n\n" <> footer, insert_text: insert_text, priority: 17, tags: metadata_to_tags(metadata), diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index ed92dae0b..9aba4b844 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -113,7 +113,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do *module* #{build_module_link(info.module)} - #{get_metadata_md(info.metadata)} + #{MarkdownUtils.get_metadata_md(info.metadata)} #{documentation_section(info.docs)} """ @@ -150,7 +150,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do *#{kind}* #{build_function_link(info.module, info.function, info.arity)} - #{get_metadata_md(info.metadata)} + #{MarkdownUtils.get_metadata_md(info.metadata)} #{spec_text} @@ -178,7 +178,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do *type* #{build_type_link(info.module, info.type, info.arity)} - #{get_metadata_md(info.metadata)} + #{MarkdownUtils.get_metadata_md(info.metadata)} ### Definition @@ -232,91 +232,6 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do """ end - def get_metadata_md(metadata) do - text = - metadata - |> Enum.sort() - |> Enum.map(&get_metadata_entry_md/1) - |> Enum.reject(&is_nil/1) - |> Enum.join("\n\n") - - case text do - "" -> "" - not_empty -> not_empty <> "\n\n" - end - end - - # erlang name - defp get_metadata_entry_md({:name, _text}), do: nil - - # erlang signature - defp get_metadata_entry_md({:signature, _text}), do: nil - - # erlang edit_url - defp get_metadata_entry_md({:edit_url, _text}), do: nil - - # erlang :otp_doc_vsn - defp get_metadata_entry_md({:otp_doc_vsn, _text}), do: nil - - # erlang :source - defp get_metadata_entry_md({:source, _text}), do: nil - - # erlang :types - defp get_metadata_entry_md({:types, _text}), do: nil - - # erlang :equiv - defp get_metadata_entry_md({:equiv, {:function, name, arity}}) do - "**Equivalent** #{name}/#{arity}" - end - - defp get_metadata_entry_md({:deprecated, text}) do - "**Deprecated** #{text}" - end - - defp get_metadata_entry_md({:since, text}) do - "**Since** #{text}" - end - - defp get_metadata_entry_md({:group, text}) do - "**Group** #{text}" - end - - defp get_metadata_entry_md({:guard, true}) do - "**Guard**" - end - - defp get_metadata_entry_md({:hidden, true}) do - "**Hidden**" - end - - defp get_metadata_entry_md({:builtin, true}) do - "**Built-in**" - end - - defp get_metadata_entry_md({:implementing, module}) do - "**Implementing behaviour** #{inspect(module)}" - end - - defp get_metadata_entry_md({:optional, true}) do - "**Optional**" - end - - defp get_metadata_entry_md({:optional, false}), do: nil - - defp get_metadata_entry_md({:opaque, true}) do - "**Opaque**" - end - - defp get_metadata_entry_md({:defaults, _}), do: nil - - defp get_metadata_entry_md({:delegate_to, {m, f, a}}) do - "**Delegates to** #{inspect(m)}.#{f}/#{a}" - end - - defp get_metadata_entry_md({key, value}) do - "**#{key}** #{inspect(value)}" - end - defp format_header(text) do text |> Code.format_string!(line_length: 40)