Skip to content

Commit f5a627c

Browse files
authored
DocumentSymbols: Return the macro used (#189)
e.g. `def`, or `defmacro`. This makes the document outline much more useful because you can see if the "function" (in LSP) is a macro, private function, guard, etc.
1 parent b3f00a5 commit f5a627c

File tree

2 files changed

+87
-61
lines changed

2 files changed

+87
-61
lines changed

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

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
88
alias ElixirLS.LanguageServer.Providers.SymbolUtils
99
alias ElixirLS.LanguageServer.Protocol
1010

11+
defmodule Info do
12+
defstruct [:type, :name, :location, :children]
13+
end
14+
1115
@defs [:def, :defp, :defmacro, :defmacrop, :defguard, :defguardp, :defdelegate]
1216

1317
@docs [
@@ -95,7 +99,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
9599
:defprotocol -> :interface
96100
end
97101

98-
%{type: type, name: module_name, location: location, children: module_symbols}
102+
%Info{type: type, name: module_name, location: location, children: module_symbols}
99103
end
100104

101105
# Protocol implementations
@@ -128,7 +132,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
128132
[]
129133
end
130134

131-
%{type: :struct, name: name, location: location, children: children}
135+
%Info{type: :struct, name: name, location: location, children: children}
132136
end
133137

134138
# Docs
@@ -148,7 +152,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
148152

149153
type = if type_kind in [:type, :typep, :opaque], do: :class, else: :event
150154

151-
%{
155+
%Info{
152156
type: type,
153157
name: type_name,
154158
location: location,
@@ -160,40 +164,42 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
160164
defp extract_symbol(_current_module, {:@, _, [{:behaviour, location, [behaviour_expression]}]}) do
161165
module_name = extract_module_name(behaviour_expression)
162166

163-
%{type: :constant, name: "@behaviour #{module_name}", location: location, children: []}
167+
%Info{type: :constant, name: "@behaviour #{module_name}", location: location, children: []}
164168
end
165169

166170
# @impl true
167171
defp extract_symbol(_current_module, {:@, _, [{:impl, location, [true]}]}) do
168-
%{type: :constant, name: "@impl true", location: location, children: []}
172+
%Info{type: :constant, name: "@impl true", location: location, children: []}
169173
end
170174

171175
# @impl BehaviourModule
172176
defp extract_symbol(_current_module, {:@, _, [{:impl, location, [impl_expression]}]}) do
173177
module_name = extract_module_name(impl_expression)
174178

175-
%{type: :constant, name: "@impl #{module_name}", location: location, children: []}
179+
%Info{type: :constant, name: "@impl #{module_name}", location: location, children: []}
176180
end
177181

178182
# Other attributes
179183
defp extract_symbol(_current_module, {:@, _, [{name, location, _}]}) do
180-
%{type: :constant, name: "@#{name}", location: location, children: []}
184+
%Info{type: :constant, name: "@#{name}", location: location, children: []}
181185
end
182186

183187
# Function, macro, guard, delegate
184188
defp extract_symbol(_current_module, {defname, _, [{_, location, _} = fn_head | _]})
185189
when defname in @defs do
186-
%{
190+
name = Macro.to_string(fn_head)
191+
192+
%Info{
187193
type: :function,
188-
name: Macro.to_string(fn_head),
194+
name: "#{defname} #{name}",
189195
location: location,
190196
children: []
191197
}
192198
end
193199

194200
# ExUnit test
195201
defp extract_symbol(_current_module, {:test, location, [name | _]}) do
196-
%{
202+
%Info{
197203
type: :function,
198204
name: ~s(test "#{name}"),
199205
location: location,
@@ -204,7 +210,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
204210
# ExUnit setup and setup_all callbacks
205211
defp extract_symbol(_current_module, {name, location, [_name | _]})
206212
when name in [:setup, :setup_all] do
207-
%{
213+
%Info{
208214
type: :function,
209215
name: "#{name}",
210216
location: location,
@@ -227,7 +233,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
227233
|> Enum.map(&extract_symbol(current_module, &1))
228234
|> Enum.reject(&is_nil/1)
229235

230-
%{
236+
%Info{
231237
type: :function,
232238
name: ~s(describe "#{name}"),
233239
location: location,
@@ -249,7 +255,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
249255
end
250256

251257
for key <- keys do
252-
%{
258+
%Info{
253259
type: :key,
254260
name: "config :#{app} #{key}",
255261
location: location,
@@ -263,7 +269,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
263269
defp build_symbol_information_hierarchical(uri, info) when is_list(info),
264270
do: Enum.map(info, &build_symbol_information_hierarchical(uri, &1))
265271

266-
defp build_symbol_information_hierarchical(uri, info) do
272+
defp build_symbol_information_hierarchical(uri, %Info{} = info) do
267273
%Protocol.DocumentSymbol{
268274
name: info.name,
269275
kind: SymbolUtils.symbol_kind_to_code(info.type),
@@ -278,7 +284,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
278284
defp build_symbol_information_flat(uri, info, parent_name) when is_list(info),
279285
do: Enum.map(info, &build_symbol_information_flat(uri, &1, parent_name))
280286

281-
defp build_symbol_information_flat(uri, info, parent_name) do
287+
defp build_symbol_information_flat(uri, %Info{} = info, parent_name) do
282288
case info.children do
283289
[_ | _] ->
284290
[
@@ -346,7 +352,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
346352
defp extract_module_name(_), do: "# unknown"
347353

348354
defp extract_property(property_name, location) when is_atom(property_name) do
349-
%{
355+
%Info{
350356
type: :property,
351357
name: "#{property_name}",
352358
location: location,

0 commit comments

Comments
 (0)