@@ -3,8 +3,7 @@ defmodule ElixirLS.LanguageServer.Providers.References do
3
3
This module provides textDocument/references support. Currently its able to find references to
4
4
functions, macros, variables and module attributes
5
5
6
- Does not support configuring "includeDeclaration" and assumes it is always
7
- `true`
6
+ Supports configuring "includeDeclaration" as defined by the LSP.
8
7
9
8
https://microsoft.github.io//language-server-protocol/specifications/specification-3-14/#textDocument_references
10
9
"""
@@ -13,29 +12,59 @@ defmodule ElixirLS.LanguageServer.Providers.References do
13
12
alias ElixirLS.LanguageServer.Providers.References.Locator
14
13
require Logger
15
14
15
+ alias ElixirLS.LanguageServer.Providers . { Definition , Declaration }
16
+
16
17
def references (
17
- % Parser.Context { source_file: source_file , metadata: metadata } ,
18
+ parser_context = % Parser.Context { source_file: source_file , metadata: metadata } ,
18
19
uri ,
19
20
line ,
20
21
character ,
21
- _include_declaration ,
22
+ include_declaration ,
22
23
project_dir
23
24
) do
24
25
Build . with_build_lock ( fn ->
25
26
trace = ElixirLS.LanguageServer.Tracer . get_trace ( )
26
27
27
- Locator . references ( source_file . text , line , character , trace , metadata: metadata )
28
- |> Enum . map ( fn elixir_sense_reference ->
29
- elixir_sense_reference
30
- |> build_reference ( uri , source_file . text , project_dir )
31
- end )
32
- |> Enum . filter ( & ( not is_nil ( & 1 ) ) )
33
- # Returned references come from both compile tracer and current buffer
34
- # There may be duplicates
35
- |> Enum . uniq ( )
28
+ base_refs =
29
+ Locator . references ( source_file . text , line , character , trace , metadata: metadata )
30
+ |> Enum . map ( fn elixir_sense_reference ->
31
+ elixir_sense_reference
32
+ |> build_reference ( uri , source_file . text , project_dir )
33
+ end )
34
+ |> Enum . filter ( & ( not is_nil ( & 1 ) ) )
35
+
36
+ { definition_locations , declaration_locations } =
37
+ definition_and_declaration_locations ( uri , parser_context , line , character , project_dir )
38
+
39
+ references =
40
+ if include_declaration do
41
+ base_refs ++ definition_locations ++ declaration_locations
42
+ else
43
+ locations_to_exclude = MapSet . new ( definition_locations ++ declaration_locations )
44
+ Enum . reject ( base_refs , fn ref -> ref in locations_to_exclude end )
45
+ end
46
+ |> Enum . uniq ( )
47
+
48
+ references
36
49
end )
37
50
end
38
51
52
+ defp definition_and_declaration_locations ( uri , parser_context , line , character , project_dir ) do
53
+ definition_locations =
54
+ case Definition . definition ( uri , parser_context , line , character , project_dir ) do
55
+ { :ok , def_loc } -> List . wrap ( def_loc || [ ] )
56
+ _ -> [ ]
57
+ end
58
+
59
+ declaration_locations =
60
+ case Declaration . declaration ( uri , parser_context , line , character , project_dir ) do
61
+ { :ok , decl_loc } -> List . wrap ( decl_loc || [ ] )
62
+ _ -> [ ]
63
+ end
64
+
65
+ { definition_locations , declaration_locations }
66
+ end
67
+
39
68
defp build_reference ( ref , current_file_uri , current_file_text , project_dir ) do
40
69
case get_text ( ref , current_file_text ) do
41
70
{ :ok , text } ->
0 commit comments