Skip to content

Commit

Permalink
Collect docs and metadata in metadata builder (#288)
Browse files Browse the repository at this point in the history
* collect docs in metadata builder

return docs and meta in docs provider

* provide docs in signatures

* return docs and meta in suggestions

* add tests

handle more cases

* return subtype on local modules

* return docs and meta from overridable reducer

consume docs when expanding use macro

* consistently return summary in completions and spec

* handle underscored auto hide

handle default hide override

* cover more cases
  • Loading branch information
lukaszsamson committed Feb 13, 2024
1 parent 4b84d06 commit e87bf6d
Show file tree
Hide file tree
Showing 13 changed files with 910 additions and 132 deletions.
42 changes: 38 additions & 4 deletions lib/elixir_sense/core/metadata.ex
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,7 @@ defmodule ElixirSense.Core.Metadata do
%{
name: Atom.to_string(function),
params: params |> Enum.with_index() |> Enum.map(&Introspection.param_to_var/1),
# TODO provide doc
documentation: "",
documentation: Introspection.extract_summary_from_docs(function_info.doc),
spec: spec
}
end)
Expand All @@ -360,8 +359,7 @@ defmodule ElixirSense.Core.Metadata do
%{
name: Atom.to_string(type),
params: type_info.args |> List.last(),
# TODO extract docs
documentation: "",
documentation: Introspection.extract_summary_from_docs(type_info.doc),
spec: spec
}
end)
Expand Down Expand Up @@ -424,4 +422,40 @@ defmodule ElixirSense.Core.Metadata do

behaviours
end

def get_module_subtype(metadata, module) do
has_func = fn f, a -> metadata.mods_funs_to_positions |> Map.has_key?({module, f, a}) end

cond do
has_func.(:__protocol__, 1) ->
:protocol

has_func.(:__impl__, 1) ->
:implementation

has_func.(:__struct__, 0) ->
if has_func.(:exception, 1) do
:exception
else
:struct
end

has_func.(:behaviour_info, 1) ->
:behaviour

match?("Elixir.Mix.Tasks." <> _, Atom.to_string(module)) ->
if has_func.(:run, 1) do
:task
end

module == Elixir ->
:alias

not has_func.(:module_info, 1) and match?("Elixir." <> _, Atom.to_string(module)) ->
:alias

true ->
nil
end
end
end
52 changes: 52 additions & 0 deletions lib/elixir_sense/core/metadata_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,58 @@ defmodule ElixirSense.Core.MetadataBuilder do
pre_func(ast_without_params, state, meta, name, params)
end

defp pre(
{:@, meta_attr, [{:moduledoc, meta, [doc_arg]}]},
state
) do
line = Keyword.fetch!(meta_attr, :line)
column = Keyword.fetch!(meta_attr, :column)
new_ast = {:@, meta_attr, [{:moduledoc, add_no_call(meta), [doc_arg]}]}

state
|> add_moduledoc_positions(
[line: line, column: column],
[{:moduledoc, meta, [doc_arg]}],
line
)
|> register_doc(:moduledoc, doc_arg)
|> result(new_ast)
end

defp pre(
{:@, meta_attr, [{doc, meta, [doc_arg]}]},
state
)
when doc in [:doc, :typedoc] do
new_ast = {:@, meta_attr, [{doc, add_no_call(meta), [doc_arg]}]}

state
|> register_doc(doc, doc_arg)
|> result(new_ast)
end

defp pre(
{:@, meta_attr, [{:impl, meta, [impl_arg]}]},
state
) do
new_ast = {:@, meta_attr, [{:impl, add_no_call(meta), [impl_arg]}]}
# impl adds sets :hidden by default
state
|> register_doc(:doc, :impl)
|> result(new_ast)
end

defp pre(
{:@, meta_attr, [{:deprecated, meta, [deprecated_arg]}]},
state
) do
new_ast = {:@, meta_attr, [{:deprecated, add_no_call(meta), [deprecated_arg]}]}
# treat @deprecated message as @doc deprecated: message
state
|> register_doc(:doc, deprecated: deprecated_arg)
|> result(new_ast)
end

defp pre(
{:@, meta, [{:behaviour, _, [{:__aliases__, _, module_expression}]}]} = ast,
state
Expand Down
Loading

0 comments on commit e87bf6d

Please sign in to comment.