Skip to content

Commit

Permalink
Introduce a compilation tracer (#724)
Browse files Browse the repository at this point in the history
* Initial implementation of tracer

migrated to tracer for references
added building of module and def database

* server test fixed

* fix dialyzer tests

* fix references tests

* add tracing of local calls

* fix and extend definition tests

* make suite synchronous

* add test coverage to tracer

* address todos

* fix warnings

* fix tests

* make tests more predictable
  • Loading branch information
lukaszsamson authored Sep 21, 2022
1 parent c3b73d8 commit e95dcc5
Show file tree
Hide file tree
Showing 19 changed files with 951 additions and 59 deletions.
3 changes: 2 additions & 1 deletion apps/language_server/lib/language_server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ defmodule ElixirLS.LanguageServer do
children = [
{ElixirLS.LanguageServer.Server, ElixirLS.LanguageServer.Server},
{ElixirLS.LanguageServer.JsonRpc, name: ElixirLS.LanguageServer.JsonRpc},
{ElixirLS.LanguageServer.Providers.WorkspaceSymbols, []}
{ElixirLS.LanguageServer.Providers.WorkspaceSymbols, []},
{ElixirLS.LanguageServer.Tracer, []}
]

opts = [strategy: :one_for_one, name: ElixirLS.LanguageServer.Supervisor, max_restarts: 0]
Expand Down
21 changes: 20 additions & 1 deletion apps/language_server/lib/language_server/build.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule ElixirLS.LanguageServer.Build do
alias ElixirLS.LanguageServer.{Server, JsonRpc, Diagnostics}
alias ElixirLS.LanguageServer.{Server, JsonRpc, Diagnostics, Tracer}
alias ElixirLS.Utils.MixfileHelpers

def build(parent, root_path, opts) when is_binary(root_path) do
Expand Down Expand Up @@ -40,6 +40,7 @@ defmodule ElixirLS.LanguageServer.Build do
end
end)

Tracer.save()
JsonRpc.log_message(:info, "Compile took #{div(us, 1000)} milliseconds")
end)
end)
Expand Down Expand Up @@ -213,4 +214,22 @@ defmodule ElixirLS.LanguageServer.Build do

:ok
end

def set_compiler_options(options \\ [], parser_options \\ []) do
parser_options =
parser_options
|> Keyword.merge(
columns: true,
token_metadata: true
)

options =
options
|> Keyword.merge(
tracers: [Tracer],
parser_options: parser_options
)

Code.compiler_options(options)
end
end
3 changes: 3 additions & 0 deletions apps/language_server/lib/language_server/cli.ex
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
defmodule ElixirLS.LanguageServer.CLI do
alias ElixirLS.Utils.{WireProtocol, Launch}
alias ElixirLS.LanguageServer.JsonRpc
alias ElixirLS.LanguageServer.Build

def main do
WireProtocol.intercept_output(&JsonRpc.print/1, &JsonRpc.print_err/1)
Launch.start_mix()

Build.set_compiler_options()

start_language_server()

IO.puts("Started ElixirLS v#{Launch.language_server_version()}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ defmodule ElixirLS.LanguageServer.Providers.References do
{line, character} = SourceFile.lsp_position_to_elixir(text, {line, character})

Build.with_build_lock(fn ->
ElixirSense.references(text, line, character)
trace = ElixirLS.LanguageServer.Tracer.get_trace()

ElixirSense.references(text, line, character, trace)
|> Enum.map(fn elixir_sense_reference ->
elixir_sense_reference
|> build_reference(uri, text)
Expand Down
22 changes: 20 additions & 2 deletions apps/language_server/lib/language_server/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ defmodule ElixirLS.LanguageServer.Server do
}

alias ElixirLS.Utils.Launch
alias ElixirLS.LanguageServer.Tracer

use Protocol

Expand All @@ -57,6 +58,7 @@ defmodule ElixirLS.LanguageServer.Server do
source_files: %{},
awaiting_contracts: [],
supports_dynamic: false,
mix_project?: false,
no_mixfile_warned?: false
]

Expand Down Expand Up @@ -415,6 +417,17 @@ defmodule ElixirLS.LanguageServer.Server do
state.source_files[uri].dirty?)
end)

# TODO remove uniq when duplicated subscriptions from vscode plugin are fixed
deleted_paths =
for change <- changes,
change["type"] == 3,
uniq: true,
do: SourceFile.path_from_uri(change["uri"])

for path <- deleted_paths do
Tracer.notify_file_deleted(path)
end

source_files =
changes
|> Enum.reduce(state.source_files, fn
Expand Down Expand Up @@ -447,6 +460,7 @@ defmodule ElixirLS.LanguageServer.Server do

state = %{state | source_files: source_files}

# TODO remove uniq when duplicated subscriptions from vscode plugin are fixed
changes
|> Enum.map(& &1["uri"])
|> Enum.uniq()
Expand Down Expand Up @@ -1043,7 +1057,10 @@ defmodule ElixirLS.LanguageServer.Server do
text

{:error, reason} ->
IO.warn("Couldn't read file #{file}: #{inspect(reason)}")
if reason != :enoent do
IO.warn("Couldn't read file #{file}: #{inspect(reason)}")
end

nil
end
end
Expand Down Expand Up @@ -1099,6 +1116,7 @@ defmodule ElixirLS.LanguageServer.Server do
|> add_watched_extensions(additional_watched_extensions)

state = create_gitignore(state)
Tracer.set_project_dir(state.project_dir)
trigger_build(%{state | settings: settings})
end

Expand Down Expand Up @@ -1211,7 +1229,7 @@ defmodule ElixirLS.LanguageServer.Server do

is_nil(prev_project_dir) ->
File.cd!(project_dir)
%{state | project_dir: File.cwd!()}
%{state | project_dir: File.cwd!(), mix_project?: File.exists?("mix.exs")}

prev_project_dir != project_dir ->
JsonRpc.show_message(
Expand Down
Loading

0 comments on commit e95dcc5

Please sign in to comment.