Skip to content

Commit

Permalink
DocumentSymbols provider handles compilation errors gracefully (#186)
Browse files Browse the repository at this point in the history
Rather than throwing an exception (which causes the spawned process to crash)
the DocumentSymbols provider will now simply return an error.

This is beneficial because this is very much an expected error and thus it is
confusing to show the exception in the logs. Possibly there are also performance
benefits to this as well.

Ideally the DocumentSymbols provider could still return valid symbols in this
case, but that is currently infeasible.
  • Loading branch information
axelson authored Apr 7, 2020
1 parent 9637725 commit b3f00a5
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,32 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
]

def symbols(uri, text, hierarchical) do
symbols = list_symbols(text)
case list_symbols(text) do
{:ok, symbols} ->
{:ok, build_symbols(symbols, uri, hierarchical)}

symbols =
if hierarchical do
Enum.map(symbols, &build_symbol_information_hierarchical(uri, &1))
else
symbols
|> Enum.map(&build_symbol_information_flat(uri, &1))
|> List.flatten()
end
{:error, :compilation_error} ->
{:error, :server_error, "[DocumentSymbols] Compilation error while parsing source file"}
end
end

{:ok, symbols}
defp build_symbols(symbols, uri, hierarchical)

defp build_symbols(symbols, uri, true) do
Enum.map(symbols, &build_symbol_information_hierarchical(uri, &1))
end

defp build_symbols(symbols, uri, false) do
symbols
|> Enum.map(&build_symbol_information_flat(uri, &1))
|> List.flatten()
end

defp list_symbols(src) do
Code.string_to_quoted!(src, columns: true, line: 0)
|> extract_modules()
case Code.string_to_quoted(src, columns: true, line: 0) do
{:ok, quoted_form} -> {:ok, extract_modules(quoted_form)}
{:error, _error} -> {:error, :compilation_error}
end
end

# Identify and extract the module symbol, and the symbols contained within the module
Expand Down
15 changes: 15 additions & 0 deletions apps/language_server/test/providers/document_symbols_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2395,4 +2395,19 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
}
]
end

test "handles a file with compilation errors by returning an empty list" do
uri = "file://project/test.exs"

text = """
defmodule A do
def hello do
Hello.hi(
end
end
"""

assert {:error, :server_error, message} = DocumentSymbols.symbols(uri, text, true)
assert String.contains?(message, "Compilation error")
end
end

0 comments on commit b3f00a5

Please sign in to comment.