Skip to content

Commit

Permalink
feat(definition): local function (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhanberg committed Jul 3, 2023
1 parent d0ae204 commit 57ccc2e
Show file tree
Hide file tree
Showing 7 changed files with 626 additions and 402 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ jobs:
MIX_ENV: test
run: mix compile

- name: remove tmp dir
run: rm -rf tmp

- name: Run Tests
run: mix test

Expand Down
41 changes: 40 additions & 1 deletion lib/next_ls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ defmodule NextLS do
Initialize,
Shutdown,
TextDocumentDocumentSymbol,
TextDocumentDefinition,
TextDocumentFormatting,
WorkspaceSymbol
}
Expand All @@ -45,6 +46,7 @@ defmodule NextLS do
alias NextLS.DiagnosticCache
alias NextLS.Runtime
alias NextLS.SymbolTable
alias NextLS.Definition

def start_link(args) do
{args, opts} =
Expand Down Expand Up @@ -97,12 +99,43 @@ defmodule NextLS do
},
document_formatting_provider: true,
workspace_symbol_provider: true,
document_symbol_provider: true
document_symbol_provider: true,
definition_provider: true
},
server_info: %{name: "NextLS"}
}, assign(lsp, root_uri: root_uri)}
end

def handle_request(%TextDocumentDefinition{params: %{text_document: %{uri: uri}, position: position}}, lsp) do
result =
case Definition.fetch(
URI.parse(uri).path,
{position.line + 1, position.character + 1},
:symbol_table,
:reference_table
) do
nil ->
nil

[{file, line, column} | _] ->
%Location{
uri: "file://#{file}",
range: %Range{
start: %Position{
line: line - 1,
character: column - 1
},
end: %Position{
line: line - 1,
character: column - 1
}
}
}
end

{:reply, result, lsp}
end

def handle_request(%TextDocumentDocumentSymbol{params: %{text_document: %{uri: uri}}}, lsp) do
symbols =
try do
Expand Down Expand Up @@ -343,6 +376,12 @@ defmodule NextLS do
{:noreply, lsp}
end

def handle_info({{:tracer, :local_function}, payload}, lsp) do
SymbolTable.put_reference(lsp.assigns.symbol_table, payload)
GenLSP.log(lsp, "[NextLS] Updated the reference table!")
{:noreply, lsp}
end

def handle_info(:publish, lsp) do
GenLSP.log(lsp, "[NextLS] Compiled!")

Expand Down
32 changes: 32 additions & 0 deletions lib/next_ls/definition.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule NextLS.Definition do
def fetch(file, {line, col}, dets_symbol_table, dets_ref_table) do
ref =
:dets.select(
dets_ref_table,
[
{{{:"$1", {{:"$2", :"$3"}, {:"$4", :"$5"}}}, :"$6"},
[
{:andalso,
{:andalso, {:andalso, {:andalso, {:==, :"$1", file}, {:"=<", :"$2", line}}, {:"=<", :"$3", col}},
{:"=<", line, :"$4"}}, {:"=<", col, :"$5"}}
], [:"$6"]}
]
)

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

case ref do
[ref] ->
:dets.select(
dets_symbol_table,
[
{{:_, %{line: :"$3", name: :"$2", module: :"$1", col: :"$4", file: :"$5"}},
[{:andalso, {:==, :"$1", ref.module}, {:==, :"$2", ref.func}}], [{{:"$5", :"$3", :"$4"}}]}
]
)

_ ->
nil
end
end
end
36 changes: 35 additions & 1 deletion lib/next_ls/symbol_table.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ defmodule NextLS.SymbolTable do
@spec put_symbols(pid() | atom(), list(tuple())) :: :ok
def put_symbols(server, symbols), do: GenServer.cast(server, {:put_symbols, symbols})

@spec put_reference(pid() | atom(), map()) :: :ok
def put_reference(server, reference), do: GenServer.cast(server, {:put_reference, reference})

@spec symbols(pid() | atom()) :: list(struct())
def symbols(server), do: GenServer.call(server, :symbols)

Expand All @@ -42,7 +45,13 @@ defmodule NextLS.SymbolTable do
type: :duplicate_bag
)

{:ok, %{table: name}}
{:ok, ref_name} =
:dets.open_file(:reference_table,
file: Path.join(path, "reference_table.dets") |> String.to_charlist(),
type: :duplicate_bag
)

{:ok, %{table: name, reference_table: ref_name}}
end

def handle_call({:symbols, file}, _, state) do
Expand Down Expand Up @@ -74,10 +83,30 @@ defmodule NextLS.SymbolTable do

def handle_call(:close, _, state) do
:dets.close(state.table)
:dets.close(state.reference_table)

{:reply, :ok, state}
end

def handle_cast({:put_reference, reference}, state) do
%{
meta: meta,
func: func,
arity: _arity,
file: file,
module: _module
} = reference

range = {{meta[:line], meta[:column]}, {meta[:line], meta[:column] + String.length(to_string(func))}}

:dets.insert(state.reference_table, {
{file, range},
reference
})

{:noreply, state}
end

def handle_cast({:put_symbols, symbols}, state) do
%{
module: mod,
Expand Down Expand Up @@ -120,6 +149,9 @@ defmodule NextLS.SymbolTable do
end

for {name, {:v1, type, _meta, clauses}} <- defs, {meta, _, _, _} <- clauses do
_ = foo()
_ = foo()

:dets.insert(
state.table,
{mod,
Expand All @@ -136,4 +168,6 @@ defmodule NextLS.SymbolTable do

{:noreply, state}
end

def foo(), do: :ok
end
38 changes: 37 additions & 1 deletion priv/monkey/_next_ls_private_compiler.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@
defmodule NextLSPrivate.Tracer do
def trace(:start, env) 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()

module =
case Macro.Env.lookup_import(env, {func, arity}) do
[{_, module}] -> module
[] -> env.module
end

Process.send(
parent,
{{:tracer, :local_function},
%{
meta: meta,
func: func,
arity: arity,
file: env.file,
module: module
}},
[]
)

:ok
end

def trace({:on_module, bytecode, _}, env) do
parent = "NEXTLS_PARENT_PID" |> System.get_env() |> Base.decode64!() |> :erlang.binary_to_term()

Expand All @@ -15,7 +44,14 @@ defmodule NextLSPrivate.Tracer do

Process.send(
parent,
{:tracer, %{file: env.file, module: env.module, module_line: line, struct: struct, defs: defs}},
{:tracer,
%{
file: env.file,
module: env.module,
module_line: line,
struct: struct,
defs: defs
}},
[]
)

Expand Down
1 change: 1 addition & 0 deletions test/next_ls/symbol_table_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ defmodule NextLS.SymbolTableTest do
alias NextLS.SymbolTable

setup %{tmp_dir: dir} do
File.mkdir_p!(dir)
pid = start_supervised!({SymbolTable, [path: dir]})

Process.link(pid)
Expand Down
Loading

0 comments on commit 57ccc2e

Please sign in to comment.