Skip to content

Commit c2feeb3

Browse files
committed
fix a common crash with malformad module ast
1 parent 37e3143 commit c2feeb3

File tree

1 file changed

+33
-28
lines changed

1 file changed

+33
-28
lines changed

apps/language_server/lib/language_server/providers/document_symbols.ex

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
5050

5151
defp list_symbols(src) do
5252
case ElixirSense.string_to_quoted(src, 1, @max_parser_errors, line: 1, token_metadata: true) do
53-
{:ok, quoted_form} -> {:ok, extract_modules(quoted_form)}
53+
{:ok, quoted_form} -> {:ok, extract_modules(quoted_form) |> Enum.reject(&is_nil/1)}
5454
{:error, _error} -> {:error, :compilation_error}
5555
end
5656
end
@@ -81,7 +81,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
8181

8282
defp extract_symbol(_module_name, {defname, location, arguments})
8383
when defname in [:defmodule, :defprotocol] do
84-
{module_name, module_name_location, module_body} =
84+
module_info =
8585
case arguments do
8686
# Handles `defmodule do\nend` type compile errors
8787
[[do: module_body]] ->
@@ -101,36 +101,41 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
101101
# TODO extract module name location from Code.Fragment.surround_context?
102102
# TODO better selection ranges for defimpl?
103103
{extract_module_name(module_expression), module_name_location, module_body}
104+
_ -> nil
104105
end
105106

106-
mod_defns =
107-
case module_body do
108-
{:__block__, [], mod_defns} -> mod_defns
109-
stmt -> [stmt]
110-
end
107+
if module_info do
108+
{module_name, module_name_location, module_body} = module_info
111109

112-
module_symbols =
113-
mod_defns
114-
|> Enum.map(&extract_symbol(module_name, &1))
115-
|> Enum.reject(&is_nil/1)
116-
|> Enum.map(fn info ->
117-
%{info | location: Keyword.put(info.location, :parent_location, location)}
118-
end)
119-
120-
type =
121-
case defname do
122-
:defmodule -> :module
123-
:defprotocol -> :interface
124-
end
110+
mod_defns =
111+
case module_body do
112+
{:__block__, [], mod_defns} -> mod_defns
113+
stmt -> [stmt]
114+
end
125115

126-
%Info{
127-
type: type,
128-
name: module_name,
129-
location: location,
130-
selection_location: module_name_location,
131-
children: module_symbols,
132-
symbol: module_name
133-
}
116+
module_symbols =
117+
mod_defns
118+
|> Enum.map(&extract_symbol(module_name, &1))
119+
|> Enum.reject(&is_nil/1)
120+
|> Enum.map(fn info ->
121+
%{info | location: Keyword.put(info.location, :parent_location, location)}
122+
end)
123+
124+
type =
125+
case defname do
126+
:defmodule -> :module
127+
:defprotocol -> :interface
128+
end
129+
130+
%Info{
131+
type: type,
132+
name: module_name,
133+
location: location,
134+
selection_location: module_name_location,
135+
children: module_symbols,
136+
symbol: module_name
137+
}
138+
end
134139
end
135140

136141
# Protocol implementations

0 commit comments

Comments
 (0)