Skip to content

Commit

Permalink
feat(definition): go to dependency (#171)
Browse files Browse the repository at this point in the history
Co-authored-by: Mitchell Hanberg <mitch@mitchellhanberg.com>
  • Loading branch information
dvic and mhanberg committed Aug 15, 2023
1 parent 9864fc4 commit ddd28de
Show file tree
Hide file tree
Showing 6 changed files with 426 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
run: rm -rf tmp

- name: Run Tests
run: elixir --erl '-kernel prevent_overlapping_partitions false' -S mix test
run: elixir --erl '-kernel prevent_overlapping_partitions false' -S mix test --max-cases 2

formatter:
runs-on: ubuntu-latest
Expand Down
36 changes: 30 additions & 6 deletions lib/next_ls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ defmodule NextLS do
WHERE refs.identifier = ?
AND refs.type = ?
AND refs.module = ?
AND NOT like('/home/runner/work/elixir/%', refs.file)
AND refs.source = 'user'
""",
[function, "function", module]
)
Expand All @@ -207,7 +207,7 @@ defmodule NextLS do
FROM "references" as refs
WHERE refs.module = ?
AND refs.type = ?
AND NOT like('/home/runner/work/elixir/%', refs.file)
AND refs.source = 'user'
""",
[module, "alias"]
)
Expand All @@ -216,12 +216,12 @@ defmodule NextLS do
[]
end

for [file, start_line, end_line, start_column, end_column] <- references do
for [file, startl, endl, startc, endc] <- references, match?({:ok, _}, File.stat(file)) do
%Location{
uri: "file://#{file}",
range: %Range{
start: %Position{line: clamp(start_line - 1), character: clamp(start_column - 1)},
end: %Position{line: clamp(end_line - 1), character: clamp(end_column - 1)}
start: %Position{line: clamp(startl - 1), character: clamp(startc - 1)},
end: %Position{line: clamp(endl - 1), character: clamp(endc - 1)}
}
}
end
Expand All @@ -241,9 +241,33 @@ defmodule NextLS do
end
end

symbols = fn pid ->
rows =
DB.query(
pid,
~Q"""
SELECT *
FROM symbols
WHERE source = 'user';
""",
[]
)

for [_pk, module, file, type, name, line, column | _] <- rows do
%{
module: module,
file: file,
type: type,
name: name,
line: line,
column: column
}
end
end

symbols =
dispatch(lsp.assigns.registry, :databases, fn entries ->
for {pid, _} <- entries, symbol <- DB.symbols(pid), filter.(symbol.name) do
for {pid, _} <- entries, symbol <- symbols.(pid), filter.(symbol.name) do
name =
if symbol.type != "defstruct" do
"#{symbol.type} #{symbol.name}"
Expand Down
61 changes: 16 additions & 45 deletions lib/next_ls/db.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ defmodule NextLS.DB do
@spec query(pid(), query(), list()) :: list()
def query(server, query, args \\ []), do: GenServer.call(server, {:query, query, args}, :infinity)

@spec symbols(pid()) :: list(map())
def symbols(server), do: GenServer.call(server, :symbols, :infinity)

@spec insert_symbol(pid(), map()) :: :ok
def insert_symbol(server, payload), do: GenServer.cast(server, {:insert_symbol, payload})

Expand Down Expand Up @@ -51,34 +48,6 @@ defmodule NextLS.DB do
{:reply, rows, s}
end

def handle_call(:symbols, _from, %{conn: conn} = s) do
rows =
__query__(
{conn, s.logger},
~Q"""
SELECT
*
FROM
symbols;
""",
[]
)

symbols =
for [_pk, module, file, type, name, line, column | _] <- rows do
%{
module: module,
file: file,
type: type,
name: name,
line: line,
column: column
}
end

{:reply, symbols, s}
end

def handle_cast({:insert_symbol, symbol}, %{conn: conn} = s) do
{:message_queue_len, count} = Process.info(self(), :message_queue_len)
NextLS.DB.Activity.update(s.activity, count)
Expand All @@ -88,7 +57,8 @@ defmodule NextLS.DB do
module_line: module_line,
struct: struct,
file: file,
defs: defs
defs: defs,
source: source
} = symbol

__query__(
Expand All @@ -103,10 +73,10 @@ defmodule NextLS.DB do
__query__(
{conn, s.logger},
~Q"""
INSERT INTO symbols (module, file, type, name, line, 'column')
VALUES (?, ?, ?, ?, ?, ?);
INSERT INTO symbols (module, file, type, name, line, 'column', source)
VALUES (?, ?, ?, ?, ?, ?, ?);
""",
[mod, file, "defmodule", mod, module_line, 1]
[mod, file, "defmodule", mod, module_line, 1, source]
)

if struct do
Expand All @@ -115,21 +85,21 @@ defmodule NextLS.DB do
__query__(
{conn, s.logger},
~Q"""
INSERT INTO symbols (module, file, type, name, line, 'column')
VALUES (?, ?, ?, ?, ?, ?);
INSERT INTO symbols (module, file, type, name, line, 'column', source)
VALUES (?, ?, ?, ?, ?, ?, ?);
""",
[mod, file, "defstruct", "%#{Macro.to_string(mod)}{}", meta[:line], 1]
[mod, file, "defstruct", "%#{Macro.to_string(mod)}{}", meta[:line], 1, source]
)
end

for {name, {:v1, type, _meta, clauses}} <- defs, {meta, _, _, _} <- clauses do
__query__(
{conn, s.logger},
~Q"""
INSERT INTO symbols (module, file, type, name, line, 'column')
VALUES (?, ?, ?, ?, ?, ?);
INSERT INTO symbols (module, file, type, name, line, 'column', source)
VALUES (?, ?, ?, ?, ?, ?, ?);
""",
[mod, file, type, name, meta[:line], meta[:column] || 1]
[mod, file, type, name, meta[:line], meta[:column] || 1, source]
)
end

Expand All @@ -145,7 +115,8 @@ defmodule NextLS.DB do
identifier: identifier,
file: file,
type: type,
module: module
module: module,
source: source
} = reference

line = meta[:line] || 1
Expand All @@ -157,10 +128,10 @@ defmodule NextLS.DB do
__query__(
{conn, s.logger},
~Q"""
INSERT INTO 'references' (identifier, arity, file, type, module, start_line, start_column, end_line, end_column)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);
INSERT INTO 'references' (identifier, arity, file, type, module, start_line, start_column, end_line, end_column, source)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
""",
[identifier, reference[:arity], file, type, module, start_line, start_column, end_line, end_column]
[identifier, reference[:arity], file, type, module, start_line, start_column, end_line, end_column, source]
)

{:noreply, s}
Expand Down
3 changes: 2 additions & 1 deletion lib/next_ls/db/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule NextLS.DB.Schema do

alias NextLS.DB

@version 3
@version 4

def init(conn) do
# FIXME: this is odd tech debt. not a big deal but is confusing
Expand Down Expand Up @@ -95,6 +95,7 @@ defmodule NextLS.DB.Schema do
start_column integer NOT NULL,
end_line integer NOT NULL,
end_column integer NOT NULL,
source text NOT NULL DEFAULT 'user',
inserted_at text NOT NULL DEFAULT CURRENT_TIMESTAMP
)
""",
Expand Down
74 changes: 67 additions & 7 deletions priv/monkey/_next_ls_private_compiler.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,57 @@
defmodule NextLSPrivate.DepTracer do
@moduledoc false

@source "dep"

def trace(:start, _env) do
:ok
end

def trace({:on_module, bytecode, _}, env) do
parent = parent_pid()

defs = Module.definitions_in(env.module)

defs =
for {name, arity} = _def <- defs do
{name, Module.get_definition(env.module, {name, arity})}
end

{:ok, {_, [{~c"Dbgi", bin}]}} = :beam_lib.chunks(bytecode, [~c"Dbgi"])

{:debug_info_v1, _, {_, %{line: line, struct: struct}, _}} = :erlang.binary_to_term(bin)

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

:ok
end

def trace(_event, _env) do
:ok
end

defp parent_pid do
"NEXTLS_PARENT_PID" |> System.get_env() |> Base.decode64!() |> :erlang.binary_to_term()
end
end

defmodule NextLSPrivate.Tracer do
@moduledoc false

@source "user"

def trace(:start, _env) do
:ok
end
Expand All @@ -17,7 +69,8 @@ defmodule NextLSPrivate.Tracer do
identifier: Map.get(alias_map, module, module),
file: env.file,
type: :alias,
module: module
module: module,
source: @source
}},
[]
)
Expand All @@ -42,7 +95,8 @@ defmodule NextLSPrivate.Tracer do
arity: arity,
file: env.file,
type: :function,
module: module
module: module,
source: @source
}},
[]
)
Expand All @@ -63,7 +117,8 @@ defmodule NextLSPrivate.Tracer do
arity: arity,
file: env.file,
type: :function,
module: env.module
module: env.module,
source: @source
}},
[]
)
Expand Down Expand Up @@ -93,7 +148,8 @@ defmodule NextLSPrivate.Tracer do
module: env.module,
module_line: line,
struct: struct,
defs: defs
defs: defs,
source: @source
}},
[]
)
Expand All @@ -113,11 +169,15 @@ end
defmodule :_next_ls_private_compiler do
@moduledoc false

@tracers Code.get_compiler_option(:tracers)

def compile do
# keep stdout on this node
Process.group_leader(self(), Process.whereis(:user))
Code.put_compiler_option(:parser_options, columns: true, token_metadata: true)

Code.put_compiler_option(:tracers, [NextLSPrivate.DepTracer | @tracers])

Mix.Task.clear()

# load the paths for deps and compile them
Expand All @@ -129,12 +189,12 @@ defmodule :_next_ls_private_compiler do
# task was not re-enabled it seems
Mix.Task.rerun("deps.loadpaths")

Code.put_compiler_option(:tracers, [NextLSPrivate.Tracer | @tracers])

Mix.Task.rerun("compile", [
"--ignore-module-conflict",
"--no-protocol-consolidation",
"--return-errors",
"--tracer",
"NextLSPrivate.Tracer"
"--return-errors"
])
rescue
e -> {:error, e}
Expand Down

0 comments on commit ddd28de

Please sign in to comment.