From ee80f0634e96a8445d66b41e021a3ebbd4cf2fa0 Mon Sep 17 00:00:00 2001 From: Luca Cervello Date: Tue, 2 Apr 2024 10:48:45 +0200 Subject: [PATCH] fix: after review --- lib/next_ls.ex | 4 +- lib/next_ls/autocomplete.ex | 2 +- lib/next_ls/helpers/ast_helpers.ex | 30 +++++++ .../{hover_helpers.ex => docs_helpers.ex} | 2 +- lib/next_ls/signature_help.ex | 86 ++++++------------- ...helpers_test.exs => docs_helpers_test.exs} | 14 +-- test/next_ls/signature_help_test.exs | 7 +- 7 files changed, 75 insertions(+), 70 deletions(-) rename lib/next_ls/helpers/{hover_helpers.ex => docs_helpers.ex} (98%) rename test/next_ls/helpers/{hover_helpers_test.exs => docs_helpers_test.exs} (95%) diff --git a/lib/next_ls.ex b/lib/next_ls.ex index 9ee84900..b8d14172 100644 --- a/lib/next_ls.ex +++ b/lib/next_ls.ex @@ -405,7 +405,7 @@ defmodule NextLS do """ ## #{reference.module} - #{NextLS.HoverHelpers.to_markdown(content_type, mod_doc)} + #{NextLS.DocsHelpers.to_markdown(content_type, mod_doc)} """ "function" -> @@ -419,7 +419,7 @@ defmodule NextLS do """ ## #{Macro.to_string(mod)}.#{reference.identifier}/#{reference.arity} - #{NextLS.HoverHelpers.to_markdown(content_type, fdoc)} + #{NextLS.DocsHelpers.to_markdown(content_type, fdoc)} """ _ -> diff --git a/lib/next_ls/autocomplete.ex b/lib/next_ls/autocomplete.ex index 040a5985..6d158fe4 100644 --- a/lib/next_ls/autocomplete.ex +++ b/lib/next_ls/autocomplete.ex @@ -636,7 +636,7 @@ defmodule NextLS.Autocomplete do """ ## #{Macro.to_string(mod)}.#{name}/#{arity} - #{NextLS.HoverHelpers.to_markdown(content_type, fdoc)} + #{NextLS.DocsHelpers.to_markdown(content_type, fdoc)} """ _ -> diff --git a/lib/next_ls/helpers/ast_helpers.ex b/lib/next_ls/helpers/ast_helpers.ex index 109cff13..795a84c3 100644 --- a/lib/next_ls/helpers/ast_helpers.ex +++ b/lib/next_ls/helpers/ast_helpers.ex @@ -152,4 +152,34 @@ defmodule NextLS.ASTHelpers do end end) end + + defmodule Function do + @moduledoc false + + alias Sourceror.Zipper + + def find_aliased_function_call_within(ast, {line, column}) do + position = [line: line, column: column] + + result = + ast + |> Zipper.zip() + |> Zipper.find(fn + {{:., _, _}, _metadata, _} = node -> + range = Sourceror.get_range(node) + + Sourceror.compare_positions(range.start, position) == :lt && + Sourceror.compare_positions(range.end, position) == :gt + + _ -> + false + end) + + if result do + {:ok, Zipper.node(result)} + else + {:error, :not_found} + end + end + end end diff --git a/lib/next_ls/helpers/hover_helpers.ex b/lib/next_ls/helpers/docs_helpers.ex similarity index 98% rename from lib/next_ls/helpers/hover_helpers.ex rename to lib/next_ls/helpers/docs_helpers.ex index efe4d4e8..f7637a01 100644 --- a/lib/next_ls/helpers/hover_helpers.ex +++ b/lib/next_ls/helpers/docs_helpers.ex @@ -1,4 +1,4 @@ -defmodule NextLS.HoverHelpers do +defmodule NextLS.DocsHelpers do @moduledoc false @spec to_markdown(String.t(), String.t() | list()) :: String.t() diff --git a/lib/next_ls/signature_help.ex b/lib/next_ls/signature_help.ex index 85fb310d..17ffed89 100644 --- a/lib/next_ls/signature_help.ex +++ b/lib/next_ls/signature_help.ex @@ -6,89 +6,59 @@ defmodule NextLS.SignatureHelp do alias GenLSP.Structures.ParameterInformation alias GenLSP.Structures.SignatureHelp alias GenLSP.Structures.SignatureInformation - alias Sourceror.Zipper + alias NextLS.ASTHelpers def fetch_mod_and_name(uri, position) do with {:ok, text} <- File.read(URI.parse(uri).path), ast = text - |> Spitfire.parse() + |> Spitfire.parse(literal_encoder: &{:ok, {:__literal__, &2, [&1]}}) |> then(fn {:ok, ast} -> ast {:error, ast, _} -> ast end), - {:ok, result} <- find_node(ast, position) do + {:ok, result} <- ASTHelpers.Function.find_aliased_function_call_within(ast, position) do case result do {{:., _, [{:__aliases__, _, modules}, name]}, _, _} -> {:ok, {Module.concat(modules), name}} end end end - def format({:ok, {:docs_v1, _, :elixir, _, _, _, docs}}, func_name) do - docs - |> Enum.filter(fn - {{_, name, _arity}, _, _, _, _} -> name == func_name - end) - |> Enum.map(fn - {{_, _name, _arity}, _, [signature], _, _} -> - params_info = - signature - |> Spitfire.parse!() - |> then(fn {_, _, args} -> - Enum.map(args, fn {name, _, _} -> name end) - end) - |> Enum.map(fn name -> + def format({:ok, {:docs_v1, _, _lang, content_type, _, _, docs}}, func_name) do + for {{_, name, _arity}, _, [signature], fdoc, _} <- docs, name == func_name do + params_info = + signature + |> Spitfire.parse!() + |> then(fn {_, _, args} -> + Enum.map(args, fn {name, _, _} -> %ParameterInformation{ label: Atom.to_string(name) } end) + end) - %SignatureHelp{ - signatures: [ - %SignatureInformation{ - label: signature, - parameters: params_info, - documentation: %MarkupContent{ - kind: MarkupKind.markdown(), - value: "" - } - } - ] - } - - # {{_, _name, _arity}, _, [], _, _} -> - # [] - - _otherwise -> - [] - end) + %SignatureHelp{ + signatures: [ + %SignatureInformation{ + label: signature, + parameters: params_info, + documentation: maybe_doc(content_type, fdoc) + } + ] + } + end end def format({:ok, {:error, :module_not_found}}, _func_name) do [] end - defp find_node(ast, {line, column}) do - position = [line: line, column: column] - - result = - ast - |> Zipper.zip() - |> Zipper.find(fn - {{:., _, _}, _metadata, _} = node -> - range = Sourceror.get_range(node) - - Sourceror.compare_positions(range.start, position) == :lt && - Sourceror.compare_positions(range.end, position) == :gt - - _ -> - false - end) - - if result do - {:ok, Zipper.node(result)} - else - {:error, :not_found} - end + defp maybe_doc(content_type, %{"en" => fdoc}) do + %MarkupContent{ + kind: MarkupKind.markdown(), + value: NextLS.DocsHelpers.to_markdown(content_type, fdoc) + } end + + defp maybe_doc(_content_type, _fdoc), do: nil end diff --git a/test/next_ls/helpers/hover_helpers_test.exs b/test/next_ls/helpers/docs_helpers_test.exs similarity index 95% rename from test/next_ls/helpers/hover_helpers_test.exs rename to test/next_ls/helpers/docs_helpers_test.exs index 012502f6..d2e45a77 100644 --- a/test/next_ls/helpers/hover_helpers_test.exs +++ b/test/next_ls/helpers/docs_helpers_test.exs @@ -1,7 +1,7 @@ -defmodule NextLS.HoverHelpersTest do +defmodule NextLS.DocsHelpersTest do use ExUnit.Case, async: true - alias NextLS.HoverHelpers + alias NextLS.DocsHelpers describe "converts erlang html format to markdown" do test "some divs and p and code" do @@ -35,7 +35,7 @@ defmodule NextLS.HoverHelpersTest do ]} ] - actual = HoverHelpers.to_markdown("application/erlang+html", html) + actual = DocsHelpers.to_markdown("application/erlang+html", html) assert actual == String.trim(""" @@ -60,7 +60,7 @@ defmodule NextLS.HoverHelpersTest do ]} ] - actual = HoverHelpers.to_markdown("application/erlang+html", html) + actual = DocsHelpers.to_markdown("application/erlang+html", html) assert actual == String.trim(""" @@ -103,7 +103,7 @@ defmodule NextLS.HoverHelpersTest do {:p, [], ["Allowed in guard tests."]} ] - actual = HoverHelpers.to_markdown("application/erlang+html", html) + actual = DocsHelpers.to_markdown("application/erlang+html", html) assert actual == String.trim(""" @@ -191,7 +191,7 @@ defmodule NextLS.HoverHelpersTest do ]} ] - actual = HoverHelpers.to_markdown("application/erlang+html", html) + actual = DocsHelpers.to_markdown("application/erlang+html", html) assert String.trim(actual) == String.trim(""" @@ -231,7 +231,7 @@ defmodule NextLS.HoverHelpersTest do {:p, [], ["Returns ", {:code, [], ["error"]}, " if no value is associated with ", {:code, [], ["Flag"]}, "."]} ] - actual = HoverHelpers.to_markdown("application/erlang+html", html) + actual = DocsHelpers.to_markdown("application/erlang+html", html) assert String.trim(actual) == String.trim(""" diff --git a/test/next_ls/signature_help_test.exs b/test/next_ls/signature_help_test.exs index 5e9ad385..f306c540 100644 --- a/test/next_ls/signature_help_test.exs +++ b/test/next_ls/signature_help_test.exs @@ -20,6 +20,7 @@ defmodule NextLS.SignatureHelpTest do File.write!(remote, """ defmodule Remote do + @doc "doc example" def bang!(bang) do bang end @@ -116,7 +117,11 @@ defmodule NextLS.SignatureHelpTest do "parameters" => [ %{"label" => "bang"} ], - "label" => "bang!(bang)" + "label" => "bang!(bang)", + "documentation" => %{ + "kind" => "markdown", + "value" => "doc example" + } } ] }