Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(definitions): macros #81

Merged
merged 2 commits into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rtx.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[tools]
elixir = "1.15.0"
elixir = "1.15.2"
erlang = "26.0.2"
3 changes: 2 additions & 1 deletion lib/next_ls/definition.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ defmodule NextLS.Definition do
]
)

:dets.traverse(dets_symbol_table, fn x -> {:continue, x} end)
# :dets.traverse(dets_symbol_table, fn x -> {:continue, x} end) |> dbg
# :dets.traverse(dets_ref_table, fn x -> {:continue, x} end) |> dbg

case ref do
[ref] ->
Expand Down
36 changes: 22 additions & 14 deletions priv/monkey/_next_ls_private_compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,34 @@ defmodule NextLSPrivate.Tracer do
:ok
end

def trace({:remote_function, meta, module, func, arity}, env) do
def trace({type, meta, module, func, arity}, env)
when type in [:remote_function, :remote_macro, :imported_macro] and
module not in [:elixir_def, :elixir_utils, Kernel, Enum] 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: module
}},
[]
)
if type == :remote_macro && meta[:closing][:line] != meta[:line] do
# this is the case that a macro is getting expanded from inside
# another macro expansion
:noop
else
Process.send(
parent,
{{:tracer, :local_function},
%{
meta: meta,
func: func,
arity: arity,
file: env.file,
module: module
}},
[]
)
end

:ok
end

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

Process.send(
Expand Down
174 changes: 173 additions & 1 deletion test/next_ls_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ defmodule NextLSTest do
end
end

describe "two" do
describe "function go to definition" do
setup %{cwd: cwd} do
remote = Path.join(cwd, "lib/remote.ex")

Expand Down Expand Up @@ -629,6 +629,178 @@ defmodule NextLSTest do
end
end

describe "macro go to definition" do
setup %{cwd: cwd} do
remote = Path.join(cwd, "lib/remote.ex")

File.write!(remote, """
defmodule Remote do
defmacro bang!() do
quote do
"‼️"
end
end
end
""")

imported = Path.join(cwd, "lib/imported.ex")

File.write!(imported, """
defmodule Imported do
defmacro boom() do
quote do
"💣"
end
end
end
""")

bar = Path.join(cwd, "lib/bar.ex")

File.write!(bar, """
defmodule Foo do
require Remote
import Imported

defmacrop process() do
quote location: :keep do
boom()
:ok
end
end

def run() do
Remote.bang!()
boom()
process()
end
end
""")

[bar: bar, imported: imported, remote: remote]
end

setup :with_lsp

test "go to local macro definition", %{client: client, bar: bar} 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: 14, character: 6},
textDocument: %{uri: uri}
}
})

assert_result 4, %{
"range" => %{
"start" => %{
"line" => 4,
"character" => 0
},
"end" => %{
"line" => 4,
"character" => 0
}
},
"uri" => ^uri
}
end

test "go to imported macro 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: 13, character: 5},
textDocument: %{uri: uri}
}
})

uri = uri(imported)

assert_result 4, %{
"range" => %{
"start" => %{
"line" => 1,
"character" => 0
},
"end" => %{
"line" => 1,
"character" => 0
}
},
"uri" => ^uri
}
end

test "go to remote macro definition", %{client: client, bar: bar, remote: remote} 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: 12, character: 13},
textDocument: %{uri: uri}
}
})

uri = uri(remote)

assert_result 4, %{
"range" => %{
"start" => %{
"line" => 1,
"character" => 0
},
"end" => %{
"line" => 1,
"character" => 0
}
},
"uri" => ^uri
}
end
end

defp with_lsp(%{tmp_dir: tmp_dir}) do
root_path = Path.absname(tmp_dir)

Expand Down