diff --git a/lib/next_ls/symbol_table.ex b/lib/next_ls/symbol_table.ex index a5cd9355..3bd6f82b 100644 --- a/lib/next_ls/symbol_table.ex +++ b/lib/next_ls/symbol_table.ex @@ -97,7 +97,8 @@ defmodule NextLS.SymbolTable do module: _module } = reference - range = {{meta[:line], meta[:column]}, {meta[:line], meta[:column] + String.length(to_string(func))}} + col = meta[:column] || 0 + range = {{meta[:line], col}, {meta[:line], col + String.length(to_string(func))}} :dets.insert(state.reference_table, { {file, range}, diff --git a/priv/monkey/_next_ls_private_compiler.ex b/priv/monkey/_next_ls_private_compiler.ex index 62de067b..83987553 100644 --- a/priv/monkey/_next_ls_private_compiler.ex +++ b/priv/monkey/_next_ls_private_compiler.ex @@ -3,15 +3,9 @@ defmodule NextLSPrivate.Tracer do :ok end - def trace({:local_function, meta, func, arity}, env) do + def trace({:remote_function, meta, module, func, arity}, env) do parent = "NEXTLS_PARENT_PID" |> System.get_env() |> Base.decode64!() |> :erlang.binary_to_term() - module = - case Macro.Env.lookup_import(env, {func, arity}) do - [{_, module}] -> module - [] -> env.module - end - Process.send( parent, {{:tracer, :local_function}, @@ -28,6 +22,25 @@ defmodule NextLSPrivate.Tracer do :ok end + def trace({:local_function, meta, func, arity}, env) do + parent = "NEXTLS_PARENT_PID" |> System.get_env() |> Base.decode64!() |> :erlang.binary_to_term() + + Process.send( + parent, + {{:tracer, :local_function}, + %{ + meta: meta, + func: func, + arity: arity, + file: env.file, + module: env.module + }}, + [] + ) + + :ok + end + def trace({:on_module, bytecode, _}, env) do parent = "NEXTLS_PARENT_PID" |> System.get_env() |> Base.decode64!() |> :erlang.binary_to_term() diff --git a/test/next_ls_test.exs b/test/next_ls_test.exs index a2de804b..be0e89b3 100644 --- a/test/next_ls_test.exs +++ b/test/next_ls_test.exs @@ -468,26 +468,38 @@ defmodule NextLSTest do describe "two" do setup %{cwd: cwd} do - path = Path.join(cwd, "lib/bar.ex") + imported = Path.join(cwd, "lib/imported.ex") - File.write!(path, """ + File.write!(imported, """ + defmodule Imported do + def boom() do + "💣" + end + end + """) + + bar = Path.join(cwd, "lib/bar.ex") + + File.write!(bar, """ defmodule Foo do + import Imported def run() do process() end defp process() do + boom() :ok end end """) - [path: path] + [bar: bar, imported: imported] end setup :with_lsp - test "go to local function definition", %{client: client, path: path} do + test "go to local function definition", %{client: client, bar: bar} do assert :ok == notify(client, %{ method: "initialized", @@ -498,14 +510,14 @@ defmodule NextLSTest do assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime ready..."} assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} - uri = uri(path) + uri = uri(bar) request(client, %{ method: "textDocument/definition", id: 4, jsonrpc: "2.0", params: %{ - position: %{line: 2, character: 6}, + position: %{line: 3, character: 6}, textDocument: %{uri: uri} } }) @@ -513,11 +525,51 @@ defmodule NextLSTest do assert_result 4, %{ "range" => %{ "start" => %{ - "line" => 5, + "line" => 6, + "character" => 0 + }, + "end" => %{ + "line" => 6, + "character" => 0 + } + }, + "uri" => ^uri + } + end + + test "go to imported function definition", %{client: client, bar: bar, imported: imported} do + assert :ok == + notify(client, %{ + method: "initialized", + jsonrpc: "2.0", + params: %{} + }) + + assert_notification "window/logMessage", %{"message" => "[NextLS] Runtime ready..."} + assert_notification "window/logMessage", %{"message" => "[NextLS] Compiled!"} + + uri = uri(bar) + + request(client, %{ + method: "textDocument/definition", + id: 4, + jsonrpc: "2.0", + params: %{ + position: %{line: 7, character: 5}, + textDocument: %{uri: uri} + } + }) + + uri = uri(imported) + + assert_result 4, %{ + "range" => %{ + "start" => %{ + "line" => 1, "character" => 0 }, "end" => %{ - "line" => 5, + "line" => 1, "character" => 0 } },