@@ -3,8 +3,7 @@ defmodule ElixirLS.LanguageServer.Providers.References do
33 This module provides textDocument/references support. Currently its able to find references to
44 functions, macros, variables and module attributes
55
6- Does not support configuring "includeDeclaration" and assumes it is always
7- `true`
6+ Supports configuring "includeDeclaration" as defined by the LSP.
87
98 https://microsoft.github.io//language-server-protocol/specifications/specification-3-14/#textDocument_references
109 """
@@ -13,29 +12,59 @@ defmodule ElixirLS.LanguageServer.Providers.References do
1312 alias ElixirLS.LanguageServer.Providers.References.Locator
1413 require Logger
1514
15+ alias ElixirLS.LanguageServer.Providers . { Definition , Declaration }
16+
1617 def references (
17- % Parser.Context { source_file: source_file , metadata: metadata } ,
18+ parser_context = % Parser.Context { source_file: source_file , metadata: metadata } ,
1819 uri ,
1920 line ,
2021 character ,
21- _include_declaration ,
22+ include_declaration ,
2223 project_dir
2324 ) do
2425 Build . with_build_lock ( fn ->
2526 trace = ElixirLS.LanguageServer.Tracer . get_trace ( )
2627
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
3649 end )
3750 end
3851
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+
3968 defp build_reference ( ref , current_file_uri , current_file_text , project_dir ) do
4069 case get_text ( ref , current_file_text ) do
4170 { :ok , text } ->
0 commit comments