Skip to content

Commit

Permalink
Make suggested changes from code review
Browse files Browse the repository at this point in the history
  • Loading branch information
zachallaun committed Sep 19, 2023
1 parent 6347711 commit aaf3d9b
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 20 deletions.
4 changes: 2 additions & 2 deletions apps/remote_control/lib/lexical/remote_control/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ defmodule Lexical.RemoteControl.Api do
end

@spec docs(Project.t(), module()) :: {:ok, CodeIntelligence.Docs.t()} | {:error, any()}
def docs(%Project{} = project, module) when is_atom(module) do
RemoteControl.call(project, CodeIntelligence.Docs, :for_module, [module])
def docs(%Project{} = project, module, opts \\ []) when is_atom(module) do
RemoteControl.call(project, CodeIntelligence.Docs, :for_module, [module, opts])
end

def register_listener(%Project{} = project, listener_pid, message_types)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,27 @@ defmodule Lexical.RemoteControl.CodeIntelligence.Docs do

@doc """
Fetches known documentation for the given module.
## Options
* `:include_hidden` - if `false`, returns `{:error, :hidden}` for
modules that have been marked as hidden using `@moduledoc false`.
Defaults to `true`.
"""
@spec for_module(module()) :: {:ok, t} | {:error, any()}
def for_module(module) when is_atom(module) do
@spec for_module(module(), [opt]) :: {:ok, t} | {:error, any()}
when opt: {:include_hidden, boolean()}
def for_module(module, opts) when is_atom(module) do
include_hidden? = Keyword.get(opts, :include_hidden, true)

with {:ok, beam} <- Modules.ensure_beam(module) do
{:ok, parse_docs(module, beam)}
%__MODULE__{} = docs = parse_docs(module, beam)

if docs.doc == :hidden and not include_hidden? do
{:error, :hidden}
else
{:ok, docs}
end
end
end

Expand Down
25 changes: 14 additions & 11 deletions apps/server/lib/lexical/server/code_intelligence/entity.ex
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ defmodule Lexical.Server.CodeIntelligence.Entity do
end

# Modules on a single line, e.g. "Foo.Bar.Baz"
defp resolve_module(charlist, {{line, column}, {line, _}}, document, position) do
defp resolve_module(charlist, {{line, column}, {line, _}}, document, %Position{} = position) do
module_string = module_before_position(charlist, column, position)

with {:ok, module} <- expand_alias(module_string, document, position) do
Expand All @@ -104,7 +104,7 @@ defmodule Lexical.Server.CodeIntelligence.Entity do
# Modules on multiple lines, e.g. "Foo.\n Bar.\n Baz"
# Since we no longer have formatting information at this point, we
# just return the entire module for now.
defp resolve_module(charlist, node_range, document, position) do
defp resolve_module(charlist, node_range, document, %Position{} = position) do
with {:ok, module} <- expand_alias(charlist, document, position) do
{:ok, {:module, module}, node_range}
end
Expand All @@ -113,7 +113,8 @@ defmodule Lexical.Server.CodeIntelligence.Entity do
# Take only the segments at and before the cursor, e.g.
# Foo|.Bar.Baz -> Foo
# Foo.|Bar.Baz -> Foo.Bar
defp module_before_position(charlist, start_column, position) when is_list(charlist) do
defp module_before_position(charlist, start_column, %Position{} = position)
when is_list(charlist) do
charlist
|> List.to_string()
|> module_before_position(position.character - start_column)
Expand All @@ -128,21 +129,21 @@ defmodule Lexical.Server.CodeIntelligence.Entity do
end
end

defp expand_alias({:alias, {:local_or_var, prefix}, charlist}, document, position) do
defp expand_alias({:alias, {:local_or_var, prefix}, charlist}, document, %Position{} = position) do
expand_alias(prefix ++ [?.] ++ charlist, document, position)
end

defp expand_alias({:alias, charlist}, document, position) do
defp expand_alias({:alias, charlist}, document, %Position{} = position) do
expand_alias(charlist, document, position)
end

defp expand_alias(charlist, document, position) when is_list(charlist) do
defp expand_alias(charlist, document, %Position{} = position) when is_list(charlist) do
charlist
|> List.to_string()
|> expand_alias(document, position)
end

defp expand_alias(module, document, position) when is_binary(module) do
defp expand_alias(module, document, %Position{} = position) when is_binary(module) do
[module]
|> Module.concat()
|> Ast.expand_aliases(document, position)
Expand All @@ -151,7 +152,7 @@ defmodule Lexical.Server.CodeIntelligence.Entity do
defp expand_alias(_, _document, _position), do: :error

# Pipes:
defp arity_at_position([{:|>, _, _} = pipe | _], position) do
defp arity_at_position([{:|>, _, _} = pipe | _], %Position{} = position) do
{_call, _, args} =
pipe
|> Macro.unpipe()
Expand All @@ -177,7 +178,7 @@ defmodule Lexical.Server.CodeIntelligence.Entity do
length(args)
end

defp arity_at_position([_non_call | rest], position) do
defp arity_at_position([_non_call | rest], %Position{} = position) do
arity_at_position(rest, position)
end

Expand All @@ -186,15 +187,17 @@ defmodule Lexical.Server.CodeIntelligence.Entity do
# Walk up the path to see whether we're in the right-hand argument of
# a `::` type operator, which would make the kind a `:type`, not a call.
# Calls that occur on the right of a `::` type operator have kind `:type`
defp kind_of_call([{:"::", _, [_, right_arg]} | rest], position) do
defp kind_of_call([{:"::", _, [_, right_arg]} | rest], %Position{} = position) do
if Ast.contains_position?(right_arg, position) do
:type
else
kind_of_call(rest, position)
end
end

defp kind_of_call([_ | rest], position), do: kind_of_call(rest, position)
defp kind_of_call([_ | rest], %Position{} = position) do
kind_of_call(rest, position)
end

defp kind_of_call([], _position), do: :call

Expand Down
8 changes: 4 additions & 4 deletions apps/server/lib/lexical/server/provider/handlers/hover.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ defmodule Lexical.Server.Provider.Handlers.Hover do
end

defp hover_content({kind, module}, env) when kind in [:module, :struct] do
case RemoteControl.Api.docs(env.project, module) do
{:ok, %Docs{doc: doc} = module_docs} when doc != :hidden ->
case RemoteControl.Api.docs(env.project, module, exclude_hidden: false) do
{:ok, %Docs{} = module_docs} ->
header = module_header(kind, module_docs)
types = module_header_types(kind, module_docs)

additional_sections = [
module_doc(doc),
module_doc(module_docs.doc),
module_footer(kind, module_docs)
]

Expand All @@ -58,7 +58,7 @@ defmodule Lexical.Server.Provider.Handlers.Hover do
|> Enum.filter(&(&1.arity >= arity))
|> Enum.map(&entry_content/1)

{:ok, Markdown.join_sections(sections, "\n\n---\n\n")}
{:ok, Markdown.join_sections(sections, Markdown.separator())}
end
end

Expand Down
8 changes: 8 additions & 0 deletions apps/server/lib/lexical/server/provider/markdown.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,12 @@ defmodule Lexical.Server.Provider.Markdown do
_ -> IO.iodata_to_binary([with_rules, "\n"])
end
end

@doc """
Returns a string that can be used to join sections with a horizontal rule.
"""
@spec separator() :: markdown
def separator do
"\n\n---\n\n"
end
end

0 comments on commit aaf3d9b

Please sign in to comment.