Skip to content

Commit

Permalink
attach app metadata when it makes sense
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszsamson committed Feb 16, 2024
1 parent fe5b90c commit f7bcb32
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 64 deletions.
2 changes: 1 addition & 1 deletion lib/elixir_sense.ex
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ defmodule ElixirSense do
[%{origin: "List", type: :function, args: "list, index, value",
args_list: ["list", "index", "value"],
arity: 3, def_arity: 3, needed_require: nil, needed_import: nil,
name: "insert_at", metadata: %{}, snippet: nil, visibility: :public,
name: "insert_at", metadata: %{app: :elixir}, snippet: nil, visibility: :public,
spec: "@spec insert_at(list(), integer(), any()) :: list()", summary: "Returns a list with `value` inserted at the specified `index`."}]
"""
@spec suggestions(String.t(), pos_integer, pos_integer, keyword()) :: [Suggestion.suggestion()]
Expand Down
17 changes: 12 additions & 5 deletions lib/elixir_sense/core/normalized/code.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ defmodule ElixirSense.Core.Normalized.Code do
:moduledoc ->
moduledoc_en = extract_docs(moduledoc, mime_type, module, app)

{max(:erl_anno.line(moduledoc_anno), 1), moduledoc_en,
maybe_mark_as_hidden(metadata, moduledoc_en)}
metadata =
maybe_mark_as_hidden(metadata, moduledoc_en)
|> Map.put(:app, app)

{max(:erl_anno.line(moduledoc_anno), 1), moduledoc_en, metadata}

:docs ->
get_fun_docs(module, app, docs, mime_type)
Expand All @@ -59,13 +62,16 @@ defmodule ElixirSense.Core.Normalized.Code do
{{kind, name, arity}, anno, signatures, docs, metadata},
mime_type,
module,
app
app,
original_app \\ nil
) do
docs_en = extract_docs(docs, mime_type, module, app)
# TODO check if we can get column here
line = :erl_anno.line(anno)

metadata = maybe_mark_as_hidden(metadata, docs_en)
metadata =
maybe_mark_as_hidden(metadata, docs_en)
|> Map.put(:app, original_app || app)

case kind do
kind when kind in [:function, :macro] ->
Expand Down Expand Up @@ -154,7 +160,8 @@ defmodule ElixirSense.Core.Normalized.Code do
|> map_doc_entry(
mime_type,
Map.get(metadata, :implementing, module),
Map.get(metadata, :implementing_module_app, app)
Map.get(metadata, :implementing_module_app, app),
app
)
end
)
Expand Down
4 changes: 3 additions & 1 deletion lib/elixir_sense/core/type_info.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ defmodule ElixirSense.Core.TypeInfo do
end

nil ->
app = ElixirSense.Core.Applications.get_application(module)

Check warning on line 40 in lib/elixir_sense/core/type_info.ex

View workflow job for this annotation

GitHub Actions / static analysis (Elixir 1.15.x | Erlang/OTP 26.x)

Nested modules could be aliased at the top of the invoking module.

for {kind, {name, _type, args}} = typedef <- Typespec.get_types(module),
kind in [:type, :opaque],
spec = format_type_spec(typedef, line_length: @param_option_spec_line_length),
Expand All @@ -46,7 +48,7 @@ defmodule ElixirSense.Core.TypeInfo do
name: name,
arity: length(args),
doc: "",
metadata: %{},
metadata: %{app: app},
spec: spec,
signature: signature
},
Expand Down
18 changes: 13 additions & 5 deletions lib/elixir_sense/providers/docs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -402,10 +402,12 @@ defmodule ElixirSense.Providers.Docs do

_ ->
if Code.ensure_loaded?(mod) do
app = ElixirSense.Core.Applications.get_application(mod)

Check warning on line 405 in lib/elixir_sense/providers/docs.ex

View workflow job for this annotation

GitHub Actions / static analysis (Elixir 1.15.x | Erlang/OTP 26.x)

Nested modules could be aliased at the top of the invoking module.

%{
kind: :module,
module: mod,
metadata: %{},
metadata: %{app: app},
docs: ""
}
end
Expand Down Expand Up @@ -479,6 +481,7 @@ defmodule ElixirSense.Providers.Docs do
defp get_func_docs_from_typespec(mod, fun, call_arity) do
# TypeInfo.get_function_specs does fallback to behaviours
{behaviour, specs} = TypeInfo.get_function_specs(mod, fun, call_arity)
app = ElixirSense.Core.Applications.get_application(mod)

Check warning on line 484 in lib/elixir_sense/providers/docs.ex

View workflow job for this annotation

GitHub Actions / static analysis (Elixir 1.15.x | Erlang/OTP 26.x)

Nested modules could be aliased at the top of the invoking module.

meta =
if behaviour do
Expand All @@ -497,7 +500,7 @@ defmodule ElixirSense.Providers.Docs do
function: fun,
arity: arity,
args: fun_args_text,
metadata: meta,
metadata: meta |> Map.put(:app, app),
specs: Introspection.get_specs_text(mod, fun, arity, :function, meta),
docs: ""
}
Expand Down Expand Up @@ -526,9 +529,11 @@ defmodule ElixirSense.Providers.Docs do

metadata =
if {f, arity} in BuiltinFunctions.erlang_builtin_functions(mod) do
%{builtin: true}
%{builtin: true, app: :erts}
else
%{}
# TODO remove this fallback?
app = ElixirSense.Core.Applications.get_application(mod)

Check warning on line 535 in lib/elixir_sense/providers/docs.ex

View workflow job for this annotation

GitHub Actions / static analysis (Elixir 1.15.x | Erlang/OTP 26.x)

Nested modules could be aliased at the top of the invoking module.
%{app: app}
end

%{
Expand Down Expand Up @@ -584,6 +589,9 @@ defmodule ElixirSense.Providers.Docs do

case docs do
[] ->
# TODO remove this fallback?
app = ElixirSense.Core.Applications.get_application(mod)

Check warning on line 593 in lib/elixir_sense/providers/docs.ex

View workflow job for this annotation

GitHub Actions / static analysis (Elixir 1.15.x | Erlang/OTP 26.x)

Nested modules could be aliased at the top of the invoking module.

for {kind, {name, _type, args}} = typedef <- Typespec.get_types(mod),
name == fun,
Introspection.matches_arity?(length(args), arity),
Expand All @@ -598,7 +606,7 @@ defmodule ElixirSense.Providers.Docs do
type: fun,
arity: length(args),
args: type_args,
metadata: %{},
metadata: %{app: app},
spec: spec,
docs: ""
}
Expand Down
5 changes: 3 additions & 2 deletions lib/elixir_sense/providers/suggestion/complete.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1135,11 +1135,12 @@ defmodule ElixirSense.Providers.Suggestion.Complete do
doc =
case func_doc do
nil ->
app = ElixirSense.Core.Applications.get_application(mod)

Check warning on line 1138 in lib/elixir_sense/providers/suggestion/complete.ex

View workflow job for this annotation

GitHub Actions / static analysis (Elixir 1.15.x | Erlang/OTP 26.x)

Nested modules could be aliased at the top of the invoking module.
# TODO provide docs for builtin
if f in [:behaviour_info | @builtin_functions] do
{"", %{builtin: true}}
{"", %{builtin: true, app: app}}
else
{"", %{}}
{"", %{app: app}}
end

{{_fun, _}, _line, _kind, _args, doc, metadata} ->
Expand Down
8 changes: 4 additions & 4 deletions test/elixir_sense/core/introspection_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ defmodule ElixirSense.Core.IntrospectionTest do
""",
signature: "do_stuff(t, term)",
doc: "Does stuff to opaque arg\n",
metadata: %{optional: false},
metadata: %{optional: false, app: :elixir_sense},
kind: :callback
}
]
Expand Down Expand Up @@ -66,7 +66,7 @@ defmodule ElixirSense.Core.IntrospectionTest do
doc:
"Called from `Exception.blame/3` to augment the exception struct.\n\nCan be used to collect additional information about the exception\nor do some additional expensive computation.\n",
signature: "blame(t, stacktrace)",
metadata: %{optional: true},
metadata: %{optional: true, app: :elixir},
kind: :callback
},
%{
Expand All @@ -75,7 +75,7 @@ defmodule ElixirSense.Core.IntrospectionTest do
doc: nil,
callback: "@callback exception(term()) :: t()",
signature: "exception(term)",
metadata: %{optional: false},
metadata: %{optional: false, app: :elixir},
kind: :callback
},
%{
Expand All @@ -84,7 +84,7 @@ defmodule ElixirSense.Core.IntrospectionTest do
callback: "@callback message(t()) :: String.t()",
doc: nil,
signature: "message(t)",
metadata: %{optional: false},
metadata: %{optional: false, app: :elixir},
kind: :callback
}
]
Expand Down
71 changes: 44 additions & 27 deletions test/elixir_sense/core/normalized/code_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,77 +6,94 @@ defmodule ElixirSense.Core.Normalized.CodeTest do
assert [
{{:hard_deprecated_fun, 1}, 71, :function, [{:a, [line: 1], nil}],
"An example fun\n",
%{deprecated: "This function will be removed in a future release"}},
%{
deprecated: "This function will be removed in a future release",
app: :elixir_sense
}},
{{:soft_deprecated_fun, 1}, 57, :function, [{:a, [line: 1], nil}],
"An example fun\n",
%{deprecated: "This function will be removed in a future release"}},
%{
deprecated: "This function will be removed in a future release",
app: :elixir_sense
}},
{{:some_fun, 2}, 21, :function,
[{:a, [line: 1], nil}, {:\\, [line: 1], [{:b, [line: 1], nil}, nil]}],
"An example fun\n", %{defaults: 1, since: "1.1.0"}},
"An example fun\n", %{defaults: 1, since: "1.1.0", app: :elixir_sense}},
{{:some_fun_doc_false, 2}, 26, :function,
[{:a, [line: 1], nil}, {:\\, [line: 1], [{:b, [line: 1], nil}, nil]}], false,
%{defaults: 1, hidden: true}},
%{defaults: 1, hidden: true, app: :elixir_sense}},
{{:some_fun_no_doc, 2}, 28, :function,
[{:a, [line: 1], nil}, {:\\, [line: 1], [{:b, [line: 1], nil}, nil]}], nil,
%{defaults: 1}},
%{defaults: 1, app: :elixir_sense}},
{{:hard_deprecated_macro, 1}, 77, :macro, [{:a, [line: 1], nil}],
"An example macro\n",
%{deprecated: "This macro will be removed in a future release"}},
%{deprecated: "This macro will be removed in a future release", app: :elixir_sense}},
{{:soft_deprecated_macro, 1}, 63, :macro, [{:a, [line: 1], nil}],
"An example macro\n",
%{deprecated: "This macro will be removed in a future release"}},
%{deprecated: "This macro will be removed in a future release", app: :elixir_sense}},
{{:some_macro, 2}, 30, :macro,
[{:a, [line: 1], nil}, {:\\, [line: 1], [{:b, [line: 1], nil}, nil]}],
"An example macro\n", %{defaults: 1, since: "1.1.0"}},
"An example macro\n", %{defaults: 1, since: "1.1.0", app: :elixir_sense}},
{{:some_macro_doc_false, 2}, 35, :macro,
[{:a, [line: 1], nil}, {:\\, [line: 1], [{:b, [line: 1], nil}, nil]}], false,
%{defaults: 1, hidden: true}},
%{defaults: 1, hidden: true, app: :elixir_sense}},
{{:some_macro_no_doc, 2}, 37, :macro,
[{:a, [line: 1], nil}, {:\\, [line: 1], [{:b, [line: 1], nil}, nil]}], nil,
%{defaults: 1}}
%{defaults: 1, app: :elixir_sense}}
] == Code.get_docs(ElixirSenseExample.ModuleWithDocs, :docs)
end

test "gets type docs" do
assert [
{{:some_type, 0}, 7, :type, "An example type\n", %{since: "1.1.0"}},
{{:some_type_doc_false, 0}, 12, :type, false, %{hidden: true}},
{{:some_type_no_doc, 0}, 14, :type, nil, %{}},
{{:some_type, 0}, 7, :type, "An example type\n",
%{since: "1.1.0", app: :elixir_sense}},
{{:some_type_doc_false, 0}, 12, :type, false, %{hidden: true, app: :elixir_sense}},
{{:some_type_no_doc, 0}, 14, :type, nil, %{app: :elixir_sense}},
{{:soft_deprecated_type, 0}, 95, :type, "An example type\n",
%{deprecated: "This type will be removed in a future release"}},
{{:opaque_type, 0}, 16, :type, "An example opaque type\n", %{opaque: true}}
%{deprecated: "This type will be removed in a future release", app: :elixir_sense}},
{{:opaque_type, 0}, 16, :type, "An example opaque type\n",
%{opaque: true, app: :elixir_sense}}
] == Code.get_docs(ElixirSenseExample.ModuleWithDocs, :type_docs)
end

test "gets callback docs" do
assert [
{{:soft_deprecated_callback, 1}, 83, :callback, "An example callback\n",
%{deprecated: "This callback will be removed in a future release"}},
{{:some_callback, 1}, 39, :callback, "An example callback\n", %{since: "1.1.0"}},
{{:some_callback_doc_false, 1}, 44, :callback, false, %{hidden: true}},
{{:some_callback_no_doc, 1}, 46, :callback, nil, %{}},
%{
deprecated: "This callback will be removed in a future release",
app: :elixir_sense
}},
{{:some_callback, 1}, 39, :callback, "An example callback\n",
%{since: "1.1.0", app: :elixir_sense}},
{{:some_callback_doc_false, 1}, 44, :callback, false,
%{hidden: true, app: :elixir_sense}},
{{:some_callback_no_doc, 1}, 46, :callback, nil, %{app: :elixir_sense}},
{{:soft_deprecated_macrocallback, 1}, 89, :macrocallback,
"An example macrocallback\n",
%{deprecated: "This callback will be removed in a future release"}},
%{
deprecated: "This callback will be removed in a future release",
app: :elixir_sense
}},
{{:some_macrocallback, 1}, 48, :macrocallback, "An example callback\n",
%{since: "1.1.0"}},
{{:some_macrocallback_doc_false, 1}, 53, :macrocallback, false, %{hidden: true}},
{{:some_macrocallback_no_doc, 1}, 55, :macrocallback, nil, %{}}
%{since: "1.1.0", app: :elixir_sense}},
{{:some_macrocallback_doc_false, 1}, 53, :macrocallback, false,
%{hidden: true, app: :elixir_sense}},
{{:some_macrocallback_no_doc, 1}, 55, :macrocallback, nil, %{app: :elixir_sense}}
] == Code.get_docs(ElixirSenseExample.ModuleWithDocs, :callback_docs)
end

test "gets module docs" do
assert {2, "An example module\n", %{since: "1.2.3"}} ==
assert {2, "An example module\n", %{since: "1.2.3", app: :elixir_sense}} ==
Code.get_docs(ElixirSenseExample.ModuleWithDocs, :moduledoc)

assert {105, false, %{hidden: true}} ==
assert {105, false, %{hidden: true, app: :elixir_sense}} ==
Code.get_docs(ElixirSenseExample.ModuleWithDocFalse, :moduledoc)

assert {108, nil, %{}} ==
assert {108, nil, %{app: :elixir_sense}} ==
Code.get_docs(ElixirSenseExample.ModuleWithNoDocs, :moduledoc)

assert {112, "An example module\n",
%{deprecated: "This module will be removed in a future release"}} ==
%{deprecated: "This module will be removed in a future release", app: :elixir_sense}} ==
Code.get_docs(ElixirSenseExample.SoftDeprecatedModule, :moduledoc)
end

Expand Down
Loading

0 comments on commit f7bcb32

Please sign in to comment.