Skip to content

Commit 45e183d

Browse files
committed
feat(definition): aliases
1 parent 1d3b022 commit 45e183d

File tree

6 files changed

+141
-30
lines changed

6 files changed

+141
-30
lines changed

lib/next_ls.ex

+4-3
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ defmodule NextLS do
117117
nil ->
118118
nil
119119

120+
[] ->
121+
nil
122+
120123
[{file, line, column} | _] ->
121124
%Location{
122125
uri: "file://#{file}",
@@ -372,13 +375,11 @@ defmodule NextLS do
372375

373376
def handle_info({:tracer, payload}, lsp) do
374377
SymbolTable.put_symbols(lsp.assigns.symbol_table, payload)
375-
GenLSP.log(lsp, "[NextLS] Updated the symbols table!")
376378
{:noreply, lsp}
377379
end
378380

379-
def handle_info({{:tracer, :local_function}, payload}, lsp) do
381+
def handle_info({{:tracer, :reference}, payload}, lsp) do
380382
SymbolTable.put_reference(lsp.assigns.symbol_table, payload)
381-
GenLSP.log(lsp, "[NextLS] Updated the reference table!")
382383
{:noreply, lsp}
383384
end
384385

lib/next_ls/definition.ex

+25-9
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,34 @@ defmodule NextLS.Definition do
1616
# :dets.traverse(dets_symbol_table, fn x -> {:continue, x} end) |> dbg
1717
# :dets.traverse(dets_ref_table, fn x -> {:continue, x} end) |> dbg
1818

19-
case ref do
20-
[ref] ->
21-
:dets.select(
22-
dets_symbol_table,
19+
# dbg(ref)
20+
21+
query =
22+
case ref do
23+
[%{type: :alias} = ref] ->
2324
[
24-
{{:_, %{line: :"$3", name: :"$2", module: :"$1", col: :"$4", file: :"$5"}},
25-
[{:andalso, {:==, :"$1", ref.module}, {:==, :"$2", ref.func}}], [{{:"$5", :"$3", :"$4"}}]}
25+
{{:_, %{line: :"$3", name: :"$2", file: :"$5", module: :"$1", col: :"$4"}},
26+
[
27+
{:andalso, {:==, :"$1", ref.module}, {:==, :"$2", Macro.to_string(ref.module)}}
28+
], [{{:"$5", :"$3", :"$4"}}]}
2629
]
27-
)
2830

29-
_ ->
30-
nil
31+
[%{type: :function} = ref] ->
32+
[
33+
{{:_, %{line: :"$3", name: :"$2", file: :"$5", module: :"$1", col: :"$4"}},
34+
[
35+
{:andalso, {:==, :"$1", ref.module}, {:==, :"$2", ref.identifier}}
36+
], [{{:"$5", :"$3", :"$4"}}]}
37+
]
38+
39+
_ ->
40+
nil
41+
end
42+
43+
if query do
44+
:dets.select(dets_symbol_table, query)
45+
else
46+
nil
3147
end
3248
end
3349
end

lib/next_ls/runtime.ex

+7
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ defmodule NextLS.Runtime do
8787
|> :code.priv_dir()
8888
|> Path.join("monkey/_next_ls_private_compiler.ex")
8989
|> then(&:rpc.call(node, Code, :compile_file, [&1]))
90+
|> tap(fn
91+
{:badrpc, :EXIT, {error, _}} ->
92+
send(parent, {:log, error})
93+
94+
_ ->
95+
:ok
96+
end)
9097

9198
:rpc.call(node, Code, :put_compiler_option, [:parser_options, [columns: true, token_metadata: true]])
9299

lib/next_ls/symbol_table.ex

+5-10
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,14 @@ defmodule NextLS.SymbolTable do
9191
def handle_cast({:put_reference, reference}, state) do
9292
%{
9393
meta: meta,
94-
func: func,
95-
arity: _arity,
96-
file: file,
97-
module: _module
94+
identifier: identifier,
95+
file: file
9896
} = reference
9997

10098
col = meta[:column] || 0
101-
range = {{meta[:line], col}, {meta[:line], col + String.length(to_string(func))}}
99+
100+
range =
101+
{{meta[:line], col}, {meta[:line], col + String.length(to_string(identifier) |> String.replace("Elixir.", ""))}}
102102

103103
:dets.insert(state.reference_table, {
104104
{file, range},
@@ -150,9 +150,6 @@ defmodule NextLS.SymbolTable do
150150
end
151151

152152
for {name, {:v1, type, _meta, clauses}} <- defs, {meta, _, _, _} <- clauses do
153-
_ = foo()
154-
_ = foo()
155-
156153
:dets.insert(
157154
state.table,
158155
{mod,
@@ -169,6 +166,4 @@ defmodule NextLS.SymbolTable do
169166

170167
{:noreply, state}
171168
end
172-
173-
def foo(), do: :ok
174169
end

priv/monkey/_next_ls_private_compiler.ex

+35-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
11
defmodule NextLSPrivate.Tracer do
2-
def trace(:start, env) do
2+
def trace(:start, _env) do
3+
:ok
4+
end
5+
6+
def trace({:alias_reference, meta, module}, env) do
7+
parent = parent_pid()
8+
9+
alias_map = Map.new(env.aliases, fn {alias, mod} -> {mod, alias} end)
10+
11+
Process.send(
12+
parent,
13+
{{:tracer, :reference},
14+
%{
15+
meta: meta,
16+
identifier: Map.get(alias_map, module, module),
17+
file: env.file,
18+
type: :alias,
19+
module: module
20+
}},
21+
[]
22+
)
23+
324
:ok
425
end
526

627
def trace({type, meta, module, func, arity}, env)
728
when type in [:remote_function, :remote_macro, :imported_macro] and
829
module not in [:elixir_def, :elixir_utils, Kernel, Enum] do
9-
parent = "NEXTLS_PARENT_PID" |> System.get_env() |> Base.decode64!() |> :erlang.binary_to_term()
30+
parent = parent_pid()
1031

1132
if type == :remote_macro && meta[:closing][:line] != meta[:line] do
1233
# this is the case that a macro is getting expanded from inside
@@ -15,12 +36,13 @@ defmodule NextLSPrivate.Tracer do
1536
else
1637
Process.send(
1738
parent,
18-
{{:tracer, :local_function},
39+
{{:tracer, :reference},
1940
%{
2041
meta: meta,
21-
func: func,
42+
identifier: func,
2243
arity: arity,
2344
file: env.file,
45+
type: :function,
2446
module: module
2547
}},
2648
[]
@@ -31,16 +53,17 @@ defmodule NextLSPrivate.Tracer do
3153
end
3254

3355
def trace({type, meta, func, arity}, env) when type in [:local_function, :local_macro] do
34-
parent = "NEXTLS_PARENT_PID" |> System.get_env() |> Base.decode64!() |> :erlang.binary_to_term()
56+
parent = parent_pid()
3557

3658
Process.send(
3759
parent,
38-
{{:tracer, :local_function},
60+
{{:tracer, :reference},
3961
%{
4062
meta: meta,
41-
func: func,
63+
identifier: func,
4264
arity: arity,
4365
file: env.file,
66+
type: :function,
4467
module: env.module
4568
}},
4669
[]
@@ -50,7 +73,7 @@ defmodule NextLSPrivate.Tracer do
5073
end
5174

5275
def trace({:on_module, bytecode, _}, env) do
53-
parent = "NEXTLS_PARENT_PID" |> System.get_env() |> Base.decode64!() |> :erlang.binary_to_term()
76+
parent = parent_pid()
5477

5578
defs = Module.definitions_in(env.module)
5679

@@ -82,6 +105,10 @@ defmodule NextLSPrivate.Tracer do
82105
def trace(_event, _env) do
83106
:ok
84107
end
108+
109+
defp parent_pid() do
110+
"NEXTLS_PARENT_PID" |> System.get_env() |> Base.decode64!() |> :erlang.binary_to_term()
111+
end
85112
end
86113

87114
defmodule :_next_ls_private_compiler do

test/next_ls_test.exs

+65
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,71 @@ defmodule NextLSTest do
801801
end
802802
end
803803

804+
describe "module go to definition" do
805+
setup %{cwd: cwd} do
806+
peace = Path.join(cwd, "lib/peace.ex")
807+
808+
File.write!(peace, """
809+
defmodule MyApp.Peace do
810+
def and_love() do
811+
"✌️"
812+
end
813+
end
814+
""")
815+
816+
bar = Path.join(cwd, "lib/bar.ex")
817+
818+
File.write!(bar, """
819+
defmodule Bar do
820+
alias MyApp.Peace
821+
def run() do
822+
Peace.and_love()
823+
end
824+
end
825+
""")
826+
827+
[bar: bar, peace: peace]
828+
end
829+
830+
setup :with_lsp
831+
832+
test "go to module definition", %{client: client, bar: bar, peace: peace} do
833+
assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}})
834+
assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime ready..."}
835+
assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"}
836+
837+
uri = uri(bar)
838+
839+
request(client, %{
840+
method: "textDocument/definition",
841+
id: 4,
842+
jsonrpc: "2.0",
843+
params: %{
844+
position: %{line: 3, character: 5},
845+
textDocument: %{uri: uri}
846+
}
847+
})
848+
849+
uri = uri(peace)
850+
851+
assert_result 4,
852+
%{
853+
"range" => %{
854+
"start" => %{
855+
"line" => 0,
856+
"character" => 0
857+
},
858+
"end" => %{
859+
"line" => 0,
860+
"character" => 0
861+
}
862+
},
863+
"uri" => ^uri
864+
},
865+
500
866+
end
867+
end
868+
804869
defp with_lsp(%{tmp_dir: tmp_dir}) do
805870
root_path = Path.absname(tmp_dir)
806871

0 commit comments

Comments
 (0)