From 8658e820c5d1664ebb95fe7c2541d7984c6a25a3 Mon Sep 17 00:00:00 2001 From: "zhuzhenfeng.code" Date: Sat, 17 Jul 2021 22:58:30 +0800 Subject: [PATCH 1/8] add quick search to hexdocs.pm Change-Id: Ifd888136b0c7cd9936bf02612bd87fdcce639ba7 --- .../lib/language_server/providers/hover.ex | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index 450fd90eb..a78dd35cb 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -15,7 +15,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do line_text = Enum.at(SourceFile.lines(text), line) range = highlight_range(line_text, line, character, subject) - %{"contents" => contents(docs), "range" => range} + %{"contents" => contents(docs, subject), "range" => range} end {:ok, response} @@ -44,14 +44,32 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end) end - defp contents(%{docs: "No documentation available\n"}) do + defp contents(%{docs: "No documentation available\n"}, _subject \\ "") do [] end - defp contents(%{docs: markdown}) do + defp contents(%{docs: markdown}, subject) do %{ kind: "markdown", - value: markdown + value: format_query(markdown, subject) } end + + defp title(s) do + s |> String.split("\n\n") |> hd() + end + + defp format_query(markdown, subject) do + t = markdown |> title() + + String.replace( + markdown, + t, + "[#{t}](https://hexdocs.pm/elixir/search.html?q=#{remove_special_symbol(subject)})" + ) + end + + defp remove_special_symbol(s) do + s |> String.replace("!", "") |> String.replace("?", "") + end end From 25e5ea844bd6930b4a0539cece512df81621e74b Mon Sep 17 00:00:00 2001 From: "zhuzhenfeng.code" Date: Mon, 19 Jul 2021 18:26:31 +0800 Subject: [PATCH 2/8] add hexdoc link for elixir std modlue and func Change-Id: I2f858ccab0a13fac426666263d59f4cf215db8a4 --- .../lib/language_server/providers/hover.ex | 162 ++++++++++++++++-- 1 file changed, 152 insertions(+), 10 deletions(-) diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index a78dd35cb..b46bcd69f 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -51,25 +51,167 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do defp contents(%{docs: markdown}, subject) do %{ kind: "markdown", - value: format_query(markdown, subject) + value: add_hexdocs_link(markdown, subject) } end - defp title(s) do - s |> String.split("\n\n") |> hd() + defp add_hexdocs_link(markdown, subject) do + IO.inspect(subject) + + [hd | tail] = markdown |> String.split("\n\n") + + link = hexdocs_link(markdown, subject) + + case link do + "" -> + markdown + + _ -> + hd <> " [view on hexdocs](#{link})\n\n" <> Enum.join(tail, "") + end end - defp format_query(markdown, subject) do - t = markdown |> title() + defp hexdocs_link(markdown, subject) do + t = markdown |> String.split("\n\n") |> hd() |> String.replace(">", "") |> String.trim() - String.replace( - markdown, - t, - "[#{t}](https://hexdocs.pm/elixir/search.html?q=#{remove_special_symbol(subject)})" - ) + cond do + func?(t) -> + mod_name = module_name(t) + + if elixir_module?(mod_name) do + "https://hexdocs.pm/elixir/#{module_name(subject)}.html##{func_name(subject)}/#{params_cnt(t)}" + else + "" + end + + true -> + if elixir_module?(t) do + "https://hexdocs.pm/elixir/#{t}.html" + else + "" + end + end end defp remove_special_symbol(s) do s |> String.replace("!", "") |> String.replace("?", "") end + + defp groups_for_modules do + [ + Kernel: [Kernel, Kernel.SpecialForms], + "Basic Types": [ + Atom, + Base, + Bitwise, + Date, + DateTime, + Exception, + Float, + Function, + Integer, + Module, + NaiveDateTime, + Record, + Regex, + String, + Time, + Tuple, + URI, + Version, + Version.Requirement + ], + "Collections & Enumerables": [ + Access, + Date.Range, + Enum, + Keyword, + List, + Map, + MapSet, + Range, + Stream + ], + "IO & System": [ + File, + File.Stat, + File.Stream, + IO, + IO.ANSI, + IO.Stream, + OptionParser, + Path, + Port, + StringIO, + System + ], + Calendar: [ + Calendar, + Calendar.ISO, + Calendar.TimeZoneDatabase, + Calendar.UTCOnlyTimeZoneDatabase + ], + "Processes & Applications": [ + Agent, + Application, + Config, + Config.Provider, + Config.Reader, + DynamicSupervisor, + GenServer, + Node, + Process, + Registry, + Supervisor, + Task, + Task.Supervisor + ], + Protocols: [ + Collectable, + Enumerable, + Inspect, + Inspect.Algebra, + Inspect.Opts, + List.Chars, + Protocol, + String.Chars + ], + "Code & Macros": [ + Code, + Kernel.ParallelCompiler, + Macro, + Macro.Env + ] + ] + end + + defp func?(s) do + s =~ ~r/.*\..*\(.*\)/ + end + + defp elixir_module?(s) do + groups_for_modules() + |> Enum.map(fn x -> elem(x, 1) end) + |> Enum.reduce(fn x, y -> x ++ y end) + |> Enum.any?(fn x -> + x == String.to_atom("Elixir." <> s) + end) + end + + defp module_name(s) do + [_ | tail] = s |> String.split(".") |> Enum.reverse() + Enum.join(tail, ".") + end + + defp func_name(s) do + s |> String.split(".") |> Enum.reverse() |> hd() + end + + defp params_cnt(s) do + cond do + true == (s =~ ~r/\(\)/) -> 0 + false == String.contains?(s, ",") -> 1 + true -> s |> String.split(",") |> length() + end + end end From 521120eaac92b3798f6b0d64c6c78fb772bf5feb Mon Sep 17 00:00:00 2001 From: "zhuzhenfeng.code" Date: Wed, 21 Jul 2021 13:09:07 +0800 Subject: [PATCH 3/8] parse deps at compile to gen hexdocs link Change-Id: Ief6e0fd0c13b2e42ddaf1817dfbf20b600971011 --- .../lib/language_server/providers/hover.ex | 161 ++++++------------ 1 file changed, 55 insertions(+), 106 deletions(-) diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index b46bcd69f..b9d9349c2 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -5,6 +5,8 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do Hover provider utilizing Elixir Sense """ + @hex_base_url "https://hexdocs.pm" + def hover(text, line, character) do response = case ElixirSense.docs(text, line + 1, character + 1) do @@ -56,8 +58,6 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end defp add_hexdocs_link(markdown, subject) do - IO.inspect(subject) - [hd | tail] = markdown |> String.split("\n\n") link = hexdocs_link(markdown, subject) @@ -73,20 +73,19 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do defp hexdocs_link(markdown, subject) do t = markdown |> String.split("\n\n") |> hd() |> String.replace(">", "") |> String.trim() + dep = subject |> root_module_name() |> dep_name() cond do func?(t) -> - mod_name = module_name(t) - - if elixir_module?(mod_name) do - "https://hexdocs.pm/elixir/#{module_name(subject)}.html##{func_name(subject)}/#{params_cnt(t)}" + if dep != "" do + "#{@hex_base_url}/#{dep}/#{module_name(subject)}.html##{func_name(subject)}/#{params_cnt(t)}" else "" end true -> - if elixir_module?(t) do - "https://hexdocs.pm/elixir/#{t}.html" + if dep != "" do + "#{@hex_base_url}/#{dep}/#{t}.html" else "" end @@ -97,110 +96,13 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do s |> String.replace("!", "") |> String.replace("?", "") end - defp groups_for_modules do - [ - Kernel: [Kernel, Kernel.SpecialForms], - "Basic Types": [ - Atom, - Base, - Bitwise, - Date, - DateTime, - Exception, - Float, - Function, - Integer, - Module, - NaiveDateTime, - Record, - Regex, - String, - Time, - Tuple, - URI, - Version, - Version.Requirement - ], - "Collections & Enumerables": [ - Access, - Date.Range, - Enum, - Keyword, - List, - Map, - MapSet, - Range, - Stream - ], - "IO & System": [ - File, - File.Stat, - File.Stream, - IO, - IO.ANSI, - IO.Stream, - OptionParser, - Path, - Port, - StringIO, - System - ], - Calendar: [ - Calendar, - Calendar.ISO, - Calendar.TimeZoneDatabase, - Calendar.UTCOnlyTimeZoneDatabase - ], - "Processes & Applications": [ - Agent, - Application, - Config, - Config.Provider, - Config.Reader, - DynamicSupervisor, - GenServer, - Node, - Process, - Registry, - Supervisor, - Task, - Task.Supervisor - ], - Protocols: [ - Collectable, - Enumerable, - Inspect, - Inspect.Algebra, - Inspect.Opts, - List.Chars, - Protocol, - String.Chars - ], - "Code & Macros": [ - Code, - Kernel.ParallelCompiler, - Macro, - Macro.Env - ] - ] - end - defp func?(s) do s =~ ~r/.*\..*\(.*\)/ end - defp elixir_module?(s) do - groups_for_modules() - |> Enum.map(fn x -> elem(x, 1) end) - |> Enum.reduce(fn x, y -> x ++ y end) - |> Enum.any?(fn x -> - x == String.to_atom("Elixir." <> s) - end) - end - defp module_name(s) do [_ | tail] = s |> String.split(".") |> Enum.reverse() - Enum.join(tail, ".") + tail |> Enum.reverse() |> Enum.join(".") end defp func_name(s) do @@ -214,4 +116,51 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do true -> s |> String.split(",") |> length() end end + + defp dep_name(root_mod_name) do + s = root_mod_name |> source() + + cond do + third_dep?(s) -> third_dep_name(s) + builtin?(s) -> builtin_dep_name(s) + true -> "" + end + end + + defp root_module_name(subject) do + subject |> String.split(".") |> hd() + end + + defp source(mod_name) do + dep = ("Elixir." <> mod_name) |> String.to_atom() + dep.__info__(:compile) |> Keyword.get(:source) |> List.to_string() + end + + defp third_dep?(source) do + prefix = File.cwd!() <> "/deps" + String.starts_with?(source, prefix) + end + + defp third_dep_name(source) do + prefix = File.cwd!() <> "/deps/" + String.replace(source, prefix, "") |> String.split("/") |> hd() + end + + defp builtin?(source) do + [ + "elixir", + "eex", + "ex_unit", + "iex", + "logger", + "mix" + ] + |> Enum.map(fn x -> "lib/#{x}/lib" end) + |> Enum.any?(fn y -> String.contains?(source, y) end) + end + + def builtin_dep_name(source) do + [_, name | _] = String.split(source, "/lib/") + name + end end From dbb999da6493dde1389f678b13932c0a57b1527a Mon Sep 17 00:00:00 2001 From: "zhuzhenfeng.code" Date: Tue, 27 Jul 2021 09:55:44 +0800 Subject: [PATCH 4/8] fix ci Change-Id: I25228974078c7f09c6afc748c22144556b5cdc63 --- .../lib/language_server/providers/hover.ex | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index b9d9349c2..77da18b13 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -6,6 +6,15 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do """ @hex_base_url "https://hexdocs.pm" + @buildin_flag [ + "elixir", + "eex", + "ex_unit", + "iex", + "logger", + "mix" + ] + |> Enum.map(fn x -> "lib/#{x}/lib" end) def hover(text, line, character) do response = @@ -46,7 +55,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end) end - defp contents(%{docs: "No documentation available\n"}, _subject \\ "") do + defp contents(%{docs: "No documentation available\n"}, subject) do [] end @@ -60,7 +69,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do defp add_hexdocs_link(markdown, subject) do [hd | tail] = markdown |> String.split("\n\n") - link = hexdocs_link(markdown, subject) + link = hexdocs_link(hd, subject) case link do "" -> @@ -71,9 +80,9 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end end - defp hexdocs_link(markdown, subject) do - t = markdown |> String.split("\n\n") |> hd() |> String.replace(">", "") |> String.trim() - dep = subject |> root_module_name() |> dep_name() + defp hexdocs_link(hd, subject) do + t = hd |> String.replace(">", "") |> String.trim() |> URI.encode() + dep = subject |> root_module_name() |> dep_name() |> URI.encode() cond do func?(t) -> @@ -102,17 +111,17 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do defp module_name(s) do [_ | tail] = s |> String.split(".") |> Enum.reverse() - tail |> Enum.reverse() |> Enum.join(".") + tail |> Enum.reverse() |> Enum.join(".") |> URI.encode() end defp func_name(s) do - s |> String.split(".") |> Enum.reverse() |> hd() + s |> String.split(".") |> Enum.at(-1) |> URI.encode() end defp params_cnt(s) do cond do - true == (s =~ ~r/\(\)/) -> 0 - false == String.contains?(s, ",") -> 1 + s =~ ~r/\(\)/ -> 0 + not String.contains?(s, ",") -> 1 true -> s |> String.split(",") |> length() end end @@ -137,30 +146,26 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end defp third_dep?(source) do - prefix = File.cwd!() <> "/deps" + prefix = project_dir() <> "/deps" String.starts_with?(source, prefix) end defp third_dep_name(source) do - prefix = File.cwd!() <> "/deps/" - String.replace(source, prefix, "") |> String.split("/") |> hd() + prefix = project_dir() <> "/deps/" + String.replace_prefix(source, prefix, "") |> String.split("/") |> hd() end defp builtin?(source) do - [ - "elixir", - "eex", - "ex_unit", - "iex", - "logger", - "mix" - ] - |> Enum.map(fn x -> "lib/#{x}/lib" end) - |> Enum.any?(fn y -> String.contains?(source, y) end) + @buildin_flag |> Enum.any?(fn y -> String.contains?(source, y) end) end def builtin_dep_name(source) do [_, name | _] = String.split(source, "/lib/") name end + + defp project_dir() do + state = :sys.get_state(ElixirLS.LanguageServer.Server) + state.project_dir + end end From d3dc135bce799ac8aee3f47f6f809e62644f6ce4 Mon Sep 17 00:00:00 2001 From: "zhuzhenfeng.code" Date: Tue, 27 Jul 2021 10:01:34 +0800 Subject: [PATCH 5/8] fix ci Change-Id: I7e6debee937d2e4de5a3b990e4086b59e78a3aba --- apps/language_server/lib/language_server/providers/hover.ex | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index 77da18b13..b21a61f14 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -55,7 +55,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end) end - defp contents(%{docs: "No documentation available\n"}, subject) do + defp contents(%{docs: "No documentation available\n"}, _subject) do [] end @@ -101,10 +101,6 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end end - defp remove_special_symbol(s) do - s |> String.replace("!", "") |> String.replace("?", "") - end - defp func?(s) do s =~ ~r/.*\..*\(.*\)/ end From 229f4fae794c222105fdbfc0d147f3a312c33594 Mon Sep 17 00:00:00 2001 From: "zhuzhenfeng.code" Date: Wed, 28 Jul 2021 14:42:44 +0800 Subject: [PATCH 6/8] pass project_dir from server Change-Id: Iff48c16cf6a5d518004f7f211235e0be085985f2 --- .../lib/language_server/providers/hover.ex | 35 ++++++++----------- .../lib/language_server/server.ex | 2 +- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index b21a61f14..1f3494a32 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -16,7 +16,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do ] |> Enum.map(fn x -> "lib/#{x}/lib" end) - def hover(text, line, character) do + def hover(text, line, character, project_dir) do response = case ElixirSense.docs(text, line + 1, character + 1) do %{subject: ""} -> @@ -26,7 +26,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do line_text = Enum.at(SourceFile.lines(text), line) range = highlight_range(line_text, line, character, subject) - %{"contents" => contents(docs, subject), "range" => range} + %{"contents" => contents(docs, subject, project_dir), "range" => range} end {:ok, response} @@ -55,21 +55,21 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end) end - defp contents(%{docs: "No documentation available\n"}, _subject) do + defp contents(%{docs: "No documentation available\n"}, _subject, _project_dir) do [] end - defp contents(%{docs: markdown}, subject) do + defp contents(%{docs: markdown}, subject, project_dir) do %{ kind: "markdown", - value: add_hexdocs_link(markdown, subject) + value: add_hexdocs_link(markdown, subject, project_dir) } end - defp add_hexdocs_link(markdown, subject) do + defp add_hexdocs_link(markdown, subject, project_dir) do [hd | tail] = markdown |> String.split("\n\n") - link = hexdocs_link(hd, subject) + link = hexdocs_link(hd, subject, project_dir) case link do "" -> @@ -80,9 +80,9 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end end - defp hexdocs_link(hd, subject) do + defp hexdocs_link(hd, subject, project_dir) do t = hd |> String.replace(">", "") |> String.trim() |> URI.encode() - dep = subject |> root_module_name() |> dep_name() |> URI.encode() + dep = subject |> root_module_name() |> dep_name(project_dir) |> URI.encode() cond do func?(t) -> @@ -122,11 +122,11 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end end - defp dep_name(root_mod_name) do + defp dep_name(root_mod_name, project_dir) do s = root_mod_name |> source() cond do - third_dep?(s) -> third_dep_name(s) + third_dep?(s, project_dir) -> third_dep_name(s, project_dir) builtin?(s) -> builtin_dep_name(s) true -> "" end @@ -141,13 +141,13 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do dep.__info__(:compile) |> Keyword.get(:source) |> List.to_string() end - defp third_dep?(source) do - prefix = project_dir() <> "/deps" + defp third_dep?(source, project_dir) do + prefix = project_dir <> "/deps" String.starts_with?(source, prefix) end - defp third_dep_name(source) do - prefix = project_dir() <> "/deps/" + defp third_dep_name(source, project_dir) do + prefix = project_dir <> "/deps/" String.replace_prefix(source, prefix, "") |> String.split("/") |> hd() end @@ -159,9 +159,4 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do [_, name | _] = String.split(source, "/lib/") name end - - defp project_dir() do - state = :sys.get_state(ElixirLS.LanguageServer.Server) - state.project_dir - end end diff --git a/apps/language_server/lib/language_server/server.ex b/apps/language_server/lib/language_server/server.ex index 714ca974a..9e2dff86a 100644 --- a/apps/language_server/lib/language_server/server.ex +++ b/apps/language_server/lib/language_server/server.ex @@ -600,7 +600,7 @@ defmodule ElixirLS.LanguageServer.Server do source_file = get_source_file(state, uri) fun = fn -> - Hover.hover(source_file.text, line, character) + Hover.hover(source_file.text, line, character, state.project_dir) end {:async, fun, state} From 7df1f2df96c1d01d1b22c8408edde641d1161e73 Mon Sep 17 00:00:00 2001 From: "zhuzhenfeng.code" Date: Sat, 31 Jul 2021 10:58:59 +0800 Subject: [PATCH 7/8] add some test for hover Change-Id: Id40baed74aeecf62f086f158185ed03345ef5ee0 --- .../lib/language_server/providers/hover.ex | 4 +- .../test/providers/hover_test.exs | 103 ++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 apps/language_server/test/providers/hover_test.exs diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index 1f3494a32..c81195a80 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -6,7 +6,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do """ @hex_base_url "https://hexdocs.pm" - @buildin_flag [ + @builtin_flag [ "elixir", "eex", "ex_unit", @@ -152,7 +152,7 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end defp builtin?(source) do - @buildin_flag |> Enum.any?(fn y -> String.contains?(source, y) end) + @builtin_flag |> Enum.any?(fn y -> String.contains?(source, y) end) end def builtin_dep_name(source) do diff --git a/apps/language_server/test/providers/hover_test.exs b/apps/language_server/test/providers/hover_test.exs new file mode 100644 index 000000000..9c335bcb7 --- /dev/null +++ b/apps/language_server/test/providers/hover_test.exs @@ -0,0 +1,103 @@ +defmodule ElixirLS.LanguageServer.Providers.HoverTest do + use ElixirLS.Utils.MixTest.Case, async: false + import ElixirLS.LanguageServer.Test.PlatformTestHelpers + + alias ElixirLS.LanguageServer.Providers.Hover + # mix cmd --app language_server mix test test/providers/hover_test.exs + + def fake_dir() do + Path.join(__DIR__, "../../../..") |> Path.expand() |> maybe_convert_path_separators() + end + + test "blank hover" do + text = """ + defmodule MyModule do + def hello() do + IO.inspect("hello world") + end + end + """ + + {line, char} = {2, 1} + + assert {:ok, resp} = Hover.hover(text, line, char, fake_dir()) + assert nil == resp + end + + test "Elixir builtin module hover" do + text = """ + defmodule MyModule do + def hello() do + IO.inspect("hello world") + end + end + """ + + {line, char} = {2, 5} + + assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + Hover.hover(text, line, char, fake_dir()) + + assert String.starts_with?(v, "> IO [view on hexdocs](https://hexdocs.pm/elixir/IO.html)") + end + + test "Elixir builtin function hover" do + text = """ + defmodule MyModule do + def hello() do + IO.inspect("hello world") + end + end + """ + + {line, char} = {2, 10} + + assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + Hover.hover(text, line, char, fake_dir()) + + assert String.starts_with?( + v, + "> IO.inspect(item, opts \\\\\\\\ []) [view on hexdocs](https://hexdocs.pm/elixir/IO.html#inspect/2)" + ) + end + + test "Third deps module hover" do + text = """ + defmodule MyModule do + def hello() do + StreamData.integer() |> Stream.map(&abs/1) |> Enum.take(3) |> IO.inspect() + end + end + """ + + {line, char} = {2, 10} + + assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + Hover.hover(text, line, char, fake_dir()) + + assert String.starts_with?( + v, + "> StreamData [view on hexdocs](https://hexdocs.pm/stream_data/StreamData.html)" + ) + end + + test "Third deps function hover" do + text = """ + defmodule MyModule do + def hello() do + StreamData.integer() |> Stream.map(&abs/1) |> Enum.take(3) |> IO.inspect() + end + end + """ + + {line, char} = {2, 18} + + assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + Hover.hover(text, line, char, fake_dir()) + + assert String.starts_with?( + v, + "> StreamData.integer() [view on hexdocs](https://hexdocs.pm/stream_data/StreamData.html#integer/0)" + ) + end +end From b019a172646826ff5cc1536369535c115ab6085d Mon Sep 17 00:00:00 2001 From: "zhuzhenfeng.code" Date: Mon, 27 Sep 2021 11:15:55 +0800 Subject: [PATCH 8/8] filter erlang module Change-Id: I77d984c72513b75d84958bdc63db093b7028142f --- .../lib/language_server/providers/hover.ex | 38 ++++++++++++------- .../test/providers/hover_test.exs | 24 +++++++++++- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index c81195a80..ca1426788 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -81,22 +81,30 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do end defp hexdocs_link(hd, subject, project_dir) do - t = hd |> String.replace(">", "") |> String.trim() |> URI.encode() - dep = subject |> root_module_name() |> dep_name(project_dir) |> URI.encode() + title = hd |> String.replace(">", "") |> String.trim() |> URI.encode() cond do - func?(t) -> - if dep != "" do - "#{@hex_base_url}/#{dep}/#{module_name(subject)}.html##{func_name(subject)}/#{params_cnt(t)}" - else - "" - end + erlang_module?(subject) -> + # erlang moudle is not support now. + "" true -> - if dep != "" do - "#{@hex_base_url}/#{dep}/#{t}.html" - else - "" + dep = subject |> root_module_name() |> dep_name(project_dir) |> URI.encode() + + cond do + func?(title) -> + if dep != "" do + "#{@hex_base_url}/#{dep}/#{module_name(subject)}.html##{func_name(subject)}/#{params_cnt(title)}" + else + "" + end + + true -> + if dep != "" do + "#{@hex_base_url}/#{dep}/#{title}.html" + else + "" + end end end end @@ -155,8 +163,12 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do @builtin_flag |> Enum.any?(fn y -> String.contains?(source, y) end) end - def builtin_dep_name(source) do + defp builtin_dep_name(source) do [_, name | _] = String.split(source, "/lib/") name end + + defp erlang_module?(subject) do + subject |> root_module_name() |> String.starts_with?(":") + end end diff --git a/apps/language_server/test/providers/hover_test.exs b/apps/language_server/test/providers/hover_test.exs index 9c335bcb7..cc1aa967d 100644 --- a/apps/language_server/test/providers/hover_test.exs +++ b/apps/language_server/test/providers/hover_test.exs @@ -61,7 +61,7 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do ) end - test "Third deps module hover" do + test "Umbrella projects: Third deps module hover" do text = """ defmodule MyModule do def hello() do @@ -81,7 +81,7 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do ) end - test "Third deps function hover" do + test "Umbrella projects: Third deps function hover" do text = """ defmodule MyModule do def hello() do @@ -100,4 +100,24 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do "> StreamData.integer() [view on hexdocs](https://hexdocs.pm/stream_data/StreamData.html#integer/0)" ) end + + test "Erlang module hover is not support now" do + text = """ + defmodule MyModule do + def hello() do + :timer.sleep(1000) + end + end + """ + + {line, char} = {2, 10} + + assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + Hover.hover(text, line, char, fake_dir()) + + assert not String.contains?( + v, + "[view on hexdocs]" + ) + end end