Repository: sublimelsp/LSP

Issue:
Workspace Symbol command should accept an empty query string, since 3.15
The "LSP: Workspace Symbol" command currently requires you enter a query string before receiving any results and thus the command does not function similar to the built-in "Find Symbol in Project" command. 

It is my understanding of the LSP that Workspace Symbol is basically "Goto Symbol in Project" so it should (at least by way of option) allow an empty query string so that it can be implemented in this way.

The spec also allows this according to the comment below:

```
/**
 * The parameters of a Workspace Symbol Request.
 */
interface WorkspaceSymbolParams extends WorkDoneProgressParams, PartialResultParams {
	/**
	 * A query string to filter symbols by. Clients may send an empty
	 * string here to request all symbols.
	 */
	query: string;
}
```


Discussion:
Pretty much blocked on https://github.com/sublimehq/sublime_text/issues/3338
It's been so long I forget now, but completion panels now work with partial results so is there anything new that would allow symbols to be recalculated as you type? Workspace Symbols are basically dead in the water until that is possible. Sending empty strings is actually the smaller of the 2 issues.

Resolving patch:
diff --git a/plugin/core/protocol.py b/plugin/core/protocol.py
--- a/plugin/core/protocol.py
+++ b/plugin/core/protocol.py
@@ -5889,8 +5889,8 @@ def willSaveWaitUntil(cls, params: Mapping[str, Any], view: sublime.View) -> 'Re
         return Request("textDocument/willSaveWaitUntil", params, view)
 
     @classmethod
-    def documentSymbols(cls, params: Mapping[str, Any], view: sublime.View) -> 'Request':
-        return Request("textDocument/documentSymbol", params, view)
+    def documentSymbols(cls, params: DocumentSymbolParams, view: sublime.View) -> 'Request':
+        return Request("textDocument/documentSymbol", params, view, progress=True)
 
     @classmethod
     def documentHighlight(cls, params: Mapping[str, Any], view: sublime.View) -> 'Request':
@@ -5928,6 +5928,10 @@ def inlayHint(cls, params: InlayHintParams, view: sublime.View) -> 'Request':
     def resolveInlayHint(cls, params: InlayHint, view: sublime.View) -> 'Request':
         return Request('inlayHint/resolve', params, view)
 
+    @classmethod
+    def workspaceSymbol(cls, params: WorkspaceSymbolParams) -> 'Request':
+        return Request("workspace/symbol", params, None, progress=True)
+
     @classmethod
     def shutdown(cls) -> 'Request':
         return Request("shutdown")
diff --git a/plugin/symbols.py b/plugin/symbols.py
--- a/plugin/symbols.py
+++ b/plugin/symbols.py
@@ -100,9 +100,8 @@ def run(self, edit: sublime.Edit, event: Optional[Dict[str, Any]] = None) -> Non
         self.view.settings().set(SUPPRESS_INPUT_SETTING_KEY, True)
         session = self.best_session(self.capability)
         if session:
-            params = {"textDocument": text_document_identifier(self.view)}
             session.send_request(
-                Request("textDocument/documentSymbol", params, self.view, progress=True),
+                Request.documentSymbols({"textDocument": text_document_identifier(self.view)}, self.view),
                 lambda response: sublime.set_timeout(lambda: self.handle_response(response)),
                 lambda error: sublime.set_timeout(lambda: self.handle_response_error(error)))
 
@@ -221,11 +220,8 @@ class SymbolQueryInput(sublime_plugin.TextInputHandler):
     def want_event(self) -> bool:
         return False
 
-    def validate(self, txt: str) -> bool:
-        return txt != ""
-
     def placeholder(self) -> str:
-        return "Symbol"
+        return "Enter symbol name"
 
 
 class LspWorkspaceSymbolsCommand(LspTextCommand):
@@ -235,15 +231,14 @@ class LspWorkspaceSymbolsCommand(LspTextCommand):
     def input(self, _args: Any) -> sublime_plugin.TextInputHandler:
         return SymbolQueryInput()
 
-    def run(self, edit: sublime.Edit, symbol_query_input: str) -> None:
-        if symbol_query_input:
-            session = self.best_session(self.capability)
-            if session:
-                params = {"query": symbol_query_input}
-                request = Request("workspace/symbol", params, None, progress=True)
-                self.weaksession = weakref.ref(session)
-                session.send_request(request, lambda r: self._handle_response(
-                    symbol_query_input, r), self._handle_error)
+    def run(self, edit: sublime.Edit, symbol_query_input: str, event: Optional[Any] = None) -> None:
+        session = self.best_session(self.capability)
+        if session:
+            self.weaksession = weakref.ref(session)
+            session.send_request(
+                Request.workspaceSymbol({"query": symbol_query_input}),
+                lambda r: self._handle_response(symbol_query_input, r),
+                self._handle_error)
 
     def _open_file(self, symbols: List[SymbolInformation], index: int) -> None:
         if index != -1:
@@ -260,7 +255,7 @@ def _handle_response(self, query: str, response: Union[List[SymbolInformation],
                     list(map(symbol_information_to_quick_panel_item, matches)),
                     lambda i: self._open_file(matches, i))
         else:
-            sublime.message_dialog("No matches found for query string: '{}'".format(query))
+            sublime.message_dialog("No matches found for query: '{}'".format(query))
 
     def _handle_error(self, error: Dict[str, Any]) -> None:
         reason = error.get("message", "none provided by server :(")


Test patch: