From b9f55cc5997a590aa97357f14bfc347871b0a1bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Samson?= <lukaszsamson@gmail.com>
Date: Mon, 9 Nov 2020 04:38:51 +0100
Subject: [PATCH] Remove support for query prefixes in WorkspaceSymbolsProvider
 (#396)

Closes #392
---
 README.md                                     |  20 +-
 .../providers/workspace_symbols.ex            |  36 +--
 .../test/providers/workspace_symbols_test.exs | 260 +++++++-----------
 3 files changed, 107 insertions(+), 209 deletions(-)

diff --git a/README.md b/README.md
index 6aaa9b3d..a4d72975 100644
--- a/README.md
+++ b/README.md
@@ -196,25 +196,7 @@ The completions include:
 
 ## Workspace Symbols
 
-With Dialyzer integration enabled ElixirLS will build an index of symbols (modules, functions, types and callbacks). The symbols are taken from the current workspace, all dependencies and stdlib (Elixir and erlang). This feature enables quick navigation to symbol definitions. However due to sheer number of different symbols and fuzzy search utilized by the provider, ElixirLS uses query prefixes to improve search results relevance.
-
-Use the following rules when navigating to workspace symbols:
-* no prefix - search for modules
-  * `:erl`
-  * `Enu`
-* `f ` prefix - search for functions
-  * `f inse`
-  * `f :ets.inse`
-  * `f Enum.cou`
-  * `f count/0`
-* `t ` prefix - search for types
-  * `t t/0`
-  * `t :erlang.time_u`
-  * `t DateTime.`
-* `c ` prefix - search for callbacks
-  * `c handle_info`
-  * `c GenServer.in`
-  * `c :gen_statem`
+With Dialyzer integration enabled ElixirLS will build an index of symbols (modules, functions, types and callbacks). The symbols are taken from the current workspace, all dependencies and stdlib (Elixir and erlang). This feature enables quick navigation to symbol definitions.
 
 ## Troubleshooting
 
diff --git a/apps/language_server/lib/language_server/providers/workspace_symbols.ex b/apps/language_server/lib/language_server/providers/workspace_symbols.ex
index e1001b7c..12d732ad 100644
--- a/apps/language_server/lib/language_server/providers/workspace_symbols.ex
+++ b/apps/language_server/lib/language_server/providers/workspace_symbols.ex
@@ -54,20 +54,7 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do
 
   @spec symbols(String.t()) :: {:ok, [symbol_information_t]}
   def symbols(query, server \\ __MODULE__) do
-    results =
-      case query do
-        "f " <> fun_query ->
-          query(:functions, fun_query, server)
-
-        "t " <> type_query ->
-          query(:types, type_query, server)
-
-        "c " <> callback_query ->
-          query(:callbacks, callback_query, server)
-
-        module_query ->
-          query(:modules, module_query, server)
-      end
+    results = query(query, server)
 
     {:ok, results}
   end
@@ -109,10 +96,10 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do
   end
 
   @impl GenServer
-  def handle_call({:query, key, query}, from, state) do
+  def handle_call({:query, query}, from, state) do
     {:ok, _pid} =
       Task.start_link(fn ->
-        results = get_results(state, key, query)
+        results = get_results(state, query)
         GenServer.reply(from, results)
       end)
 
@@ -356,13 +343,13 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do
     |> elem(0)
   end
 
-  defp query(kind, query, server) do
+  defp query(query, server) do
     case String.trim(query) do
       "" ->
         []
 
       trimmed ->
-        GenServer.call(server, {:query, kind, trimmed})
+        GenServer.call(server, {:query, trimmed})
     end
   end
 
@@ -446,14 +433,13 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do
     :ok
   end
 
-  @spec get_results(state_t, key_t, String.t()) :: [symbol_information_t]
-  defp get_results(state, key, query) do
+  @spec get_results(state_t, String.t()) :: [symbol_information_t]
+  defp get_results(state, query) do
     query_downcase = String.downcase(query)
     query_length = String.length(query)
     arity_suffix = Regex.run(@arity_suffix_regex, query)
 
-    state
-    |> Map.fetch!(key)
+    (state.modules ++ state.functions ++ state.types ++ state.callbacks)
     |> process_chunked(fn chunk ->
       chunk
       |> Enum.map(&{&1, get_score(&1.name, query, query_downcase, query_length, arity_suffix)})
@@ -509,15 +495,15 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do
   end
 
   defp symbol_name(:functions, {module, function, arity}) do
-    "f #{inspect(module)}.#{function}/#{arity}"
+    "#{inspect(module)}.#{function}/#{arity}"
   end
 
   defp symbol_name(:types, {module, type, arity}) do
-    "t #{inspect(module)}.#{type}/#{arity}"
+    "#{inspect(module)}.#{type}/#{arity}"
   end
 
   defp symbol_name(:callbacks, {module, callback, arity}) do
-    "c #{inspect(module)}.#{callback}/#{arity}"
+    "#{inspect(module)}.#{callback}/#{arity}"
   end
 
   @spec build_range(nil | non_neg_integer) :: range_t
diff --git a/apps/language_server/test/providers/workspace_symbols_test.exs b/apps/language_server/test/providers/workspace_symbols_test.exs
index acbe7892..dcf86a3a 100644
--- a/apps/language_server/test/providers/workspace_symbols_test.exs
+++ b/apps/language_server/test/providers/workspace_symbols_test.exs
@@ -44,180 +44,110 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbolsTest do
   end
 
   test "returns modules", %{server: server} do
-    assert {:ok,
-            [
-              %{
-                kind: 2,
-                location: %{
-                  range: %{end: %{character: 0, line: 1}, start: %{character: 0, line: 0}},
-                  uri: uri
-                },
-                name: "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols"
-              }
-            ]} = WorkspaceSymbols.symbols("ElixirLS.LanguageServer.Fixtures.", server)
-
-    assert uri |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
-
-    assert {:ok,
-            [
-              %{
-                kind: 2,
-                location: %{
-                  range: %{end: %{character: 0, line: 1}, start: %{character: 0, line: 0}},
-                  uri: uri
-                },
-                name: "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols"
-              }
-            ]} = WorkspaceSymbols.symbols("work", server)
-
-    assert uri |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
+    assert {:ok, list} = WorkspaceSymbols.symbols("ElixirLS.LanguageServer.Fixtures.", server)
+
+    assert module =
+             Enum.find(list, &(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols"))
+
+    assert module.kind == 2
+    assert module.location.uri |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
+
+    assert module.location.range == %{
+             end: %{character: 0, line: 1},
+             start: %{character: 0, line: 0}
+           }
+
+    assert WorkspaceSymbols.symbols("work", server)
+           |> elem(1)
+           |> Enum.any?(&(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols"))
   end
 
   test "returns functions", %{server: server} do
-    assert {
-             :ok,
-             [
-               %{
-                 kind: 12,
-                 location: %{
-                   range: %{end: %{character: 0, line: 1}, start: %{character: 0, line: 0}},
-                   uri: uri
-                 },
-                 name: "f ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.module_info/1"
-               },
-               %{
-                 kind: 12,
-                 location: %{
-                   range: %{end: %{character: 0, line: 1}, start: %{character: 0, line: 0}}
-                 },
-                 name: "f ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.module_info/0"
-               },
-               %{
-                 kind: 12,
-                 location: %{
-                   range: %{end: %{character: 0, line: 1}, start: %{character: 0, line: 0}}
-                 },
-                 name: "f ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.behaviour_info/1"
-               },
-               %{
-                 kind: 12,
-                 location: %{
-                   range: %{end: %{character: 0, line: 3}, start: %{character: 0, line: 2}}
-                 },
-                 name: "f ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_macro/1"
-               },
-               %{
-                 kind: 12,
-                 location: %{
-                   range: %{end: %{character: 0, line: 2}, start: %{character: 0, line: 1}}
-                 },
-                 name: "f ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_function/1"
-               },
-               %{
-                 kind: 12,
-                 location: %{
-                   range: %{end: %{character: 0, line: 1}, start: %{character: 0, line: 0}}
-                 },
-                 name: "f ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.__info__/1"
-               }
-             ]
-           } = WorkspaceSymbols.symbols("f ElixirLS.LanguageServer.Fixtures.", server)
-
-    assert uri |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
-
-    assert {:ok,
-            [
-              %{
-                kind: 12,
-                location: %{
-                  range: %{end: %{character: 0, line: 2}, start: %{character: 0, line: 1}},
-                  uri: uri
-                },
-                name: "f ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_function/1"
-              }
-            ]} = WorkspaceSymbols.symbols("f fun", server)
-
-    assert uri |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
+    assert {:ok, list} = WorkspaceSymbols.symbols("ElixirLS.LanguageServer.Fixtures.", server)
+
+    assert some_function =
+             Enum.find(
+               list,
+               &(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_function/1")
+             )
+
+    assert some_function.kind == 12
+
+    assert some_function.location.uri
+           |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
+
+    assert some_function.location.range == %{
+             end: %{character: 0, line: 2},
+             start: %{character: 0, line: 1}
+           }
+
+    assert WorkspaceSymbols.symbols("fun", server)
+           |> elem(1)
+           |> Enum.any?(
+             &(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_function/1")
+           )
   end
 
   test "returns types", %{server: server} do
-    assert {
-             :ok,
-             [
-               %{
-                 kind: 5,
-                 location: %{
-                   range: %{end: %{character: 0, line: 8}, start: %{character: 0, line: 7}},
-                   uri: uri
-                 },
-                 name: "t ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_type/0"
-               },
-               %{
-                 kind: 5,
-                 location: %{
-                   range: %{end: %{character: 0, line: 9}, start: %{character: 0, line: 8}}
-                 },
-                 name: "t ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_opaque_type/0"
-               }
-             ]
-           } = WorkspaceSymbols.symbols("t ElixirLS.LanguageServer.Fixtures.", server)
-
-    assert uri |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
-
-    assert {
-             :ok,
-             [
-               %{
-                 kind: 5,
-                 location: %{
-                   range: %{end: %{character: 0, line: 9}, start: %{character: 0, line: 8}},
-                   uri: uri
-                 },
-                 name: "t ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_opaque_type/0"
-               }
-             ]
-           } = WorkspaceSymbols.symbols("t opa", server)
-
-    assert uri |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
+    assert {:ok, list} = WorkspaceSymbols.symbols("ElixirLS.LanguageServer.Fixtures.", server)
+
+    assert some_type =
+             Enum.find(
+               list,
+               &(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_type/0")
+             )
+
+    assert some_type.kind == 5
+
+    assert some_type.location.uri
+           |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
+
+    assert some_type.location.range == %{
+             end: %{character: 0, line: 8},
+             start: %{character: 0, line: 7}
+           }
+
+    assert Enum.any?(
+             list,
+             &(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_opaque_type/0")
+           )
+
+    assert WorkspaceSymbols.symbols("opa", server)
+           |> elem(1)
+           |> Enum.any?(
+             &(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_opaque_type/0")
+           )
   end
 
   test "returns callbacks", %{server: server} do
-    assert {
-             :ok,
-             [
-               %{
-                 kind: 24,
-                 location: %{
-                   range: %{end: %{character: 0, line: 5}, start: %{character: 0, line: 4}},
-                   uri: uri
-                 },
-                 name: "c ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_callback/1"
-               },
-               %{
-                 kind: 24,
-                 location: %{
-                   range: %{end: %{character: 0, line: 6}, start: %{character: 0, line: 5}}
-                 },
-                 name: "c ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_macrocallback/1"
-               }
-             ]
-           } = WorkspaceSymbols.symbols("c ElixirLS.LanguageServer.Fixtures.", server)
-
-    assert uri |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
-
-    assert {:ok,
-            [
-              %{
-                kind: 24,
-                location: %{
-                  range: %{end: %{character: 0, line: 6}, start: %{character: 0, line: 5}},
-                  uri: uri
-                },
-                name: "c ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_macrocallback/1"
-              }
-            ]} = WorkspaceSymbols.symbols("c macr", server)
-
-    assert uri |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
+    assert {:ok, list} = WorkspaceSymbols.symbols("ElixirLS.LanguageServer.Fixtures.", server)
+
+    assert some_callback =
+             Enum.find(
+               list,
+               &(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_callback/1")
+             )
+
+    assert some_callback.kind == 24
+
+    assert some_callback.location.uri
+           |> String.ends_with?("test/support/fixtures/workspace_symbols.ex")
+
+    assert some_callback.location.range == %{
+             end: %{character: 0, line: 5},
+             start: %{character: 0, line: 4}
+           }
+
+    assert Enum.any?(
+             list,
+             &(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_macrocallback/1")
+           )
+
+    assert WorkspaceSymbols.symbols("macr", server)
+           |> elem(1)
+           |> Enum.any?(
+             &(&1.name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols.some_macrocallback/1")
+           )
   end
 
   defp wait_until_indexed(pid) do