Skip to content

Commit 23de15f

Browse files
authored
Return references to elixir modules (#854)
* trace alias references * bump metadata version * cover more cases of module usage * do not try to read code from `nofile` references
1 parent e1b2562 commit 23de15f

File tree

5 files changed

+65
-2
lines changed

5 files changed

+65
-2
lines changed

apps/language_server/lib/language_server/providers/references.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ defmodule ElixirLS.LanguageServer.Providers.References do
4545
"uri" => build_uri(ref, current_file_uri)
4646
}
4747

48+
{:error, :nofile} ->
49+
Logger.debug("Skipping reference from `nofile`")
50+
nil
51+
4852
{:error, reason} ->
4953
# workaround for elixir tracer returning invalid paths
5054
# https://github.com/elixir-lang/elixir/issues/12393
@@ -67,6 +71,7 @@ defmodule ElixirLS.LanguageServer.Providers.References do
6771
def get_text(elixir_sense_ref, current_file_text) do
6872
case elixir_sense_ref.uri do
6973
nil -> {:ok, current_file_text}
74+
"nofile" -> {:error, :nofile}
7075
path when is_binary(path) -> File.read(path)
7176
end
7277
end

apps/language_server/lib/language_server/tracer.ex

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ defmodule ElixirLS.LanguageServer.Tracer do
44
use GenServer
55
require Logger
66

7-
@version 2
7+
@version 3
88

99
@tables ~w(modules calls)a
1010

@@ -205,6 +205,18 @@ defmodule ElixirLS.LanguageServer.Tracer do
205205
register_call(meta, env.module, name, arity, env)
206206
end
207207

208+
def trace({:alias_reference, meta, module}, %Macro.Env{} = env) do
209+
register_call(meta, module, nil, nil, env)
210+
end
211+
212+
def trace({:alias, meta, module, _as, _opts}, %Macro.Env{} = env) do
213+
register_call(meta, module, nil, nil, env)
214+
end
215+
216+
def trace({kind, meta, module, _opts}, %Macro.Env{} = env) when kind in [:import, :require] do
217+
register_call(meta, module, nil, nil, env)
218+
end
219+
208220
def trace(_trace, _env) do
209221
# IO.inspect(trace, label: "skipped")
210222
:ok
@@ -264,6 +276,7 @@ defmodule ElixirLS.LanguageServer.Tracer do
264276

265277
line = meta[:line]
266278
column = meta[:column]
279+
# TODO meta can have last or maybe other?
267280

268281
:ets.insert(table_name(:calls), {{callee, env.file, line, column}, :ok})
269282
end

apps/language_server/test/providers/references_test.exs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do
3333
Code.compile_file(FixtureHelpers.get_path("uses_macro_a.ex"))
3434
Code.compile_file(FixtureHelpers.get_path("macro_a.ex"))
3535
Code.compile_file(FixtureHelpers.get_path("references_erlang.ex"))
36+
Code.compile_file(FixtureHelpers.get_path("references_alias.ex"))
3637
{:ok, context}
3738
end
3839

@@ -215,4 +216,25 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do
215216
assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_erlang.ex")))
216217
assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_referenced.ex")))
217218
end
219+
220+
test "finds alias references" do
221+
file_path = FixtureHelpers.get_path("references_referenced.ex")
222+
text = File.read!(file_path)
223+
uri = SourceFile.Path.to_uri(file_path)
224+
225+
{line, char} = {0, 25}
226+
227+
ElixirLS.Test.TextLoc.annotate_assert(file_path, line, char, """
228+
defmodule ElixirLS.Test.ReferencesReferenced do
229+
^
230+
""")
231+
232+
list =
233+
References.references(text, uri, line, char, true)
234+
|> Enum.filter(&String.ends_with?(&1["uri"], "references_alias.ex"))
235+
236+
references_lines = Enum.map(list, & &1["range"]["start"]["line"])
237+
238+
assert references_lines == [1, 2, 3, 4, 7, 11, 15, 19, 20]
239+
end
218240
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
defmodule ElixirLS.Test.ReferencesAlias do
2+
require ElixirLS.Test.ReferencesReferenced, as: ReferencesReferenced
3+
alias ElixirLS.Test.ReferencesReferenced, as: Some
4+
alias Some, as: Other
5+
import Other
6+
7+
def uses_alias_1 do
8+
ReferencesReferenced
9+
end
10+
11+
def uses_alias_2 do
12+
Some
13+
end
14+
15+
def uses_alias_3 do
16+
ElixirLS.Test.ReferencesReferenced
17+
end
18+
19+
def uses_alias_4 do
20+
uses_attribute()
21+
Other
22+
end
23+
end

apps/language_server/test/tracer_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ defmodule ElixirLS.LanguageServer.TracerTest do
160160
project_path = FixtureHelpers.get_path("")
161161
Tracer.write_manifest(project_path)
162162

163-
assert 2 == Tracer.read_manifest(project_path)
163+
assert 3 == Tracer.read_manifest(project_path)
164164
end
165165
end
166166
end

0 commit comments

Comments
 (0)