aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralcroito <[email protected]>2021-02-23 12:03:31 +0000
committeralcroito <[email protected]>2021-05-17 23:40:30 +0100
commit1f7d2a6c2297de4dedfb42b739e880ad2dd7d5d5 (patch)
tree46f7897cceaac302c0930dcdae99593e795b1351
parentc04eaa1f37f31d7125372ba14da3d5059297e8b2 (diff)
Add new LSP extension for workspace symbol lookup
The new extension allows filtering of workspace symbool lookup results by search scope or search kind. Filtering can be configured in 3 different ways: - The '#' or '*' markers can be added inline with the symbol lookup query. The '#' marker means symbols should be looked up in the current workspace and any dependencies. If not specified, only current workspace is considered. The '*' marker means all kinds of symbols should be looked up (types, functions, etc). If not specified, only type symbols are returned. - Each LSP request can take an optional search_scope or search_kind argument query parameter. - Finally there are 2 global config options that can be set for all requests served by the active RA instance. Add support for setting the global config options to the VSCode extension. The extension does not use the per-request way, but it's useful for other IDEs. The latest version of VSCode filters out the inline markers, so currently the only reasonable way to use the new functionality is via the global config.
-rw-r--r--crates/ide_db/src/symbol_index.rs5
-rw-r--r--crates/rust-analyzer/src/config.rs63
-rw-r--r--crates/rust-analyzer/src/handlers.rs48
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs42
-rw-r--r--crates/rust-analyzer/src/main_loop.rs2
-rw-r--r--docs/dev/lsp-extensions.md32
-rw-r--r--docs/user/generated_config.adoc10
-rw-r--r--editors/code/package.json26
8 files changed, 220 insertions, 8 deletions
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index da427d686..0f5c4abc4 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -161,6 +161,11 @@ impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> {
161// That is, `#` switches from "types" to all symbols, `*` switches from the current 161// That is, `#` switches from "types" to all symbols, `*` switches from the current
162// workspace to dependencies. 162// workspace to dependencies.
163// 163//
164// Note that filtering does not currently work in VSCode due to the editor never
165// sending the special symbols to the language server. Instead, you can configure
166// the filtering via the `rust-analyzer.workspace.symbol.search.scope` and
167// `rust-analyzer.workspace.symbol.search.kind` settings.
168//
164// |=== 169// |===
165// | Editor | Shortcut 170// | Editor | Shortcut
166// 171//
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index a3866c1ba..339014fd3 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -24,7 +24,8 @@ use vfs::AbsPathBuf;
24 24
25use crate::{ 25use crate::{
26 caps::completion_item_edit_resolve, diagnostics::DiagnosticsMapConfig, 26 caps::completion_item_edit_resolve, diagnostics::DiagnosticsMapConfig,
27 line_index::OffsetEncoding, lsp_ext::supports_utf8, 27 line_index::OffsetEncoding, lsp_ext::supports_utf8, lsp_ext::WorkspaceSymbolSearchKind,
28 lsp_ext::WorkspaceSymbolSearchScope,
28}; 29};
29 30
30// Defines the server-side configuration of the rust-analyzer. We generate 31// Defines the server-side configuration of the rust-analyzer. We generate
@@ -215,6 +216,11 @@ config_data! {
215 /// Advanced option, fully override the command rust-analyzer uses for 216 /// Advanced option, fully override the command rust-analyzer uses for
216 /// formatting. 217 /// formatting.
217 rustfmt_overrideCommand: Option<Vec<String>> = "null", 218 rustfmt_overrideCommand: Option<Vec<String>> = "null",
219
220 /// Workspace symbol search scope.
221 workspace_symbol_search_scope: WorskpaceSymbolSearchScopeDef = "\"workspace\"",
222 /// Workspace symbol search kind.
223 workspace_symbol_search_kind: WorskpaceSymbolSearchKindDef = "\"only_types\"",
218 } 224 }
219} 225}
220 226
@@ -309,6 +315,15 @@ pub struct RunnablesConfig {
309 pub cargo_extra_args: Vec<String>, 315 pub cargo_extra_args: Vec<String>,
310} 316}
311 317
318/// Configuration for workspace symbol search requests.
319#[derive(Debug, Clone)]
320pub struct WorkspaceSymbolConfig {
321 /// In what scope should the symbol be searched in.
322 pub search_scope: WorkspaceSymbolSearchScope,
323 /// What kind of symbol is being search for.
324 pub search_kind: WorkspaceSymbolSearchKind,
325}
326
312impl Config { 327impl Config {
313 pub fn new(root_path: AbsPathBuf, caps: ClientCapabilities) -> Self { 328 pub fn new(root_path: AbsPathBuf, caps: ClientCapabilities) -> Self {
314 Config { caps, data: ConfigData::default(), discovered_projects: None, root_path } 329 Config { caps, data: ConfigData::default(), discovered_projects: None, root_path }
@@ -687,6 +702,22 @@ impl Config {
687 .contains(&MarkupKind::Markdown), 702 .contains(&MarkupKind::Markdown),
688 } 703 }
689 } 704 }
705
706 pub fn workspace_symbol(&self) -> WorkspaceSymbolConfig {
707 WorkspaceSymbolConfig {
708 search_scope: match self.data.workspace_symbol_search_scope {
709 WorskpaceSymbolSearchScopeDef::Workspace => WorkspaceSymbolSearchScope::Workspace,
710 WorskpaceSymbolSearchScopeDef::WorkspaceAndDependencies => {
711 WorkspaceSymbolSearchScope::WorkspaceAndDependencies
712 }
713 },
714 search_kind: match self.data.workspace_symbol_search_kind {
715 WorskpaceSymbolSearchKindDef::OnlyTypes => WorkspaceSymbolSearchKind::OnlyTypes,
716 WorskpaceSymbolSearchKindDef::AllSymbols => WorkspaceSymbolSearchKind::AllSymbols,
717 },
718 }
719 }
720
690 pub fn semantic_tokens_refresh(&self) -> bool { 721 pub fn semantic_tokens_refresh(&self) -> bool {
691 try_or!(self.caps.workspace.as_ref()?.semantic_tokens.as_ref()?.refresh_support?, false) 722 try_or!(self.caps.workspace.as_ref()?.semantic_tokens.as_ref()?.refresh_support?, false)
692 } 723 }
@@ -733,6 +764,20 @@ enum ImportPrefixDef {
733 ByCrate, 764 ByCrate,
734} 765}
735 766
767#[derive(Deserialize, Debug, Clone)]
768#[serde(rename_all = "snake_case")]
769enum WorskpaceSymbolSearchScopeDef {
770 Workspace,
771 WorkspaceAndDependencies,
772}
773
774#[derive(Deserialize, Debug, Clone)]
775#[serde(rename_all = "snake_case")]
776enum WorskpaceSymbolSearchKindDef {
777 OnlyTypes,
778 AllSymbols,
779}
780
736macro_rules! _config_data { 781macro_rules! _config_data {
737 (struct $name:ident { 782 (struct $name:ident {
738 $( 783 $(
@@ -903,6 +948,22 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
903 "type": "array", 948 "type": "array",
904 "items": { "type": ["string", "object"] }, 949 "items": { "type": ["string", "object"] },
905 }, 950 },
951 "WorskpaceSymbolSearchScopeDef" => set! {
952 "type": "string",
953 "enum": ["workspace", "workspace_and_dependencies"],
954 "enumDescriptions": [
955 "Search in current workspace only",
956 "Search in current workspace and dependencies"
957 ],
958 },
959 "WorskpaceSymbolSearchKindDef" => set! {
960 "type": "string",
961 "enum": ["only_types", "all_symbols"],
962 "enumDescriptions": [
963 "Search for types only",
964 "Search for all symbols kinds"
965 ],
966 },
906 _ => panic!("{}: {}", ty, default), 967 _ => panic!("{}: {}", ty, default),
907 } 968 }
908 969
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 8fe97fd7c..51041d7a0 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -38,7 +38,7 @@ use crate::{
38 from_proto, 38 from_proto,
39 global_state::{GlobalState, GlobalStateSnapshot}, 39 global_state::{GlobalState, GlobalStateSnapshot},
40 line_index::LineEndings, 40 line_index::LineEndings,
41 lsp_ext::{self, InlayHint, InlayHintsParams}, 41 lsp_ext::{self, InlayHint, InlayHintsParams, WorkspaceSymbolParams},
42 lsp_utils::all_edits_are_disjoint, 42 lsp_utils::all_edits_are_disjoint,
43 to_proto, LspError, Result, 43 to_proto, LspError, Result,
44}; 44};
@@ -380,11 +380,12 @@ pub(crate) fn handle_document_symbol(
380 380
381pub(crate) fn handle_workspace_symbol( 381pub(crate) fn handle_workspace_symbol(
382 snap: GlobalStateSnapshot, 382 snap: GlobalStateSnapshot,
383 params: lsp_types::WorkspaceSymbolParams, 383 params: WorkspaceSymbolParams,
384) -> Result<Option<Vec<SymbolInformation>>> { 384) -> Result<Option<Vec<SymbolInformation>>> {
385 let _p = profile::span("handle_workspace_symbol"); 385 let _p = profile::span("handle_workspace_symbol");
386 let all_symbols = params.query.contains('#'); 386
387 let libs = params.query.contains('*'); 387 let (all_symbols, libs) = decide_search_scope_and_kind(&params, &snap);
388
388 let query = { 389 let query = {
389 let query: String = params.query.chars().filter(|&c| c != '#' && c != '*').collect(); 390 let query: String = params.query.chars().filter(|&c| c != '#' && c != '*').collect();
390 let mut q = Query::new(query); 391 let mut q = Query::new(query);
@@ -406,6 +407,45 @@ pub(crate) fn handle_workspace_symbol(
406 407
407 return Ok(Some(res)); 408 return Ok(Some(res));
408 409
410 fn decide_search_scope_and_kind(
411 params: &WorkspaceSymbolParams,
412 snap: &GlobalStateSnapshot,
413 ) -> (bool, bool) {
414 // Support old-style parsing of markers in the query.
415 let mut all_symbols = params.query.contains('#');
416 let mut libs = params.query.contains('*');
417
418 let config = snap.config.workspace_symbol();
419
420 // If no explicit marker was set, check request params. If that's also empty
421 // use global config.
422 if !all_symbols {
423 let search_kind = if let Some(ref search_kind) = params.search_kind {
424 search_kind
425 } else {
426 &config.search_kind
427 };
428 all_symbols = match search_kind {
429 lsp_ext::WorkspaceSymbolSearchKind::OnlyTypes => false,
430 lsp_ext::WorkspaceSymbolSearchKind::AllSymbols => true,
431 }
432 }
433
434 if !libs {
435 let search_scope = if let Some(ref search_scope) = params.search_scope {
436 search_scope
437 } else {
438 &config.search_scope
439 };
440 libs = match search_scope {
441 lsp_ext::WorkspaceSymbolSearchScope::Workspace => false,
442 lsp_ext::WorkspaceSymbolSearchScope::WorkspaceAndDependencies => true,
443 }
444 }
445
446 (all_symbols, libs)
447 }
448
409 fn exec_query(snap: &GlobalStateSnapshot, query: Query) -> Result<Vec<SymbolInformation>> { 449 fn exec_query(snap: &GlobalStateSnapshot, query: Query) -> Result<Vec<SymbolInformation>> {
410 let mut res = Vec::new(); 450 let mut res = Vec::new();
411 for nav in snap.analysis.symbol_search(query)? { 451 for nav in snap.analysis.symbol_search(query)? {
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 3bd098058..34b53a7a8 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -4,7 +4,8 @@ use std::{collections::HashMap, path::PathBuf};
4 4
5use lsp_types::request::Request; 5use lsp_types::request::Request;
6use lsp_types::{ 6use lsp_types::{
7 notification::Notification, CodeActionKind, Position, Range, TextDocumentIdentifier, 7 notification::Notification, CodeActionKind, PartialResultParams, Position, Range,
8 TextDocumentIdentifier, WorkDoneProgressParams,
8}; 9};
9use serde::{Deserialize, Serialize}; 10use serde::{Deserialize, Serialize};
10 11
@@ -438,3 +439,42 @@ pub enum MoveItemDirection {
438 Up, 439 Up,
439 Down, 440 Down,
440} 441}
442
443#[derive(Debug)]
444pub enum WorkspaceSymbol {}
445
446impl Request for WorkspaceSymbol {
447 type Params = WorkspaceSymbolParams;
448 type Result = Option<Vec<lsp_types::SymbolInformation>>;
449 const METHOD: &'static str = "workspace/symbol";
450}
451
452#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
453pub struct WorkspaceSymbolParams {
454 #[serde(flatten)]
455 pub partial_result_params: PartialResultParams,
456
457 #[serde(flatten)]
458 pub work_done_progress_params: WorkDoneProgressParams,
459
460 /// A non-empty query string
461 pub query: String,
462
463 pub search_scope: Option<WorkspaceSymbolSearchScope>,
464
465 pub search_kind: Option<WorkspaceSymbolSearchKind>,
466}
467
468#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
469#[serde(rename_all = "camelCase")]
470pub enum WorkspaceSymbolSearchScope {
471 Workspace,
472 WorkspaceAndDependencies,
473}
474
475#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
476#[serde(rename_all = "camelCase")]
477pub enum WorkspaceSymbolSearchKind {
478 OnlyTypes,
479 AllSymbols,
480}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index c7bd7eee1..4e0791611 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -525,9 +525,9 @@ impl GlobalState {
525 .on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs) 525 .on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs)
526 .on::<lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml) 526 .on::<lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml)
527 .on::<lsp_ext::MoveItem>(handlers::handle_move_item) 527 .on::<lsp_ext::MoveItem>(handlers::handle_move_item)
528 .on::<lsp_ext::WorkspaceSymbol>(handlers::handle_workspace_symbol)
528 .on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting) 529 .on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting)
529 .on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol) 530 .on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol)
530 .on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol)
531 .on::<lsp_types::request::GotoDefinition>(handlers::handle_goto_definition) 531 .on::<lsp_types::request::GotoDefinition>(handlers::handle_goto_definition)
532 .on::<lsp_types::request::GotoImplementation>(handlers::handle_goto_implementation) 532 .on::<lsp_types::request::GotoImplementation>(handlers::handle_goto_implementation)
533 .on::<lsp_types::request::GotoTypeDefinition>(handlers::handle_goto_type_definition) 533 .on::<lsp_types::request::GotoTypeDefinition>(handlers::handle_goto_type_definition)
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 8fcd72d5d..2d3787d0f 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
1<!--- 1<!---
2lsp_ext.rs hash: 6e57fc1b345b00e9 2lsp_ext.rs hash: 10a8988e6893e6b2
3 3
4If you need to change the above hash to make the test pass, please check if you 4If you need to change the above hash to make the test pass, please check if you
5need to adjust this doc as well and ping this issue: 5need to adjust this doc as well and ping this issue:
@@ -650,3 +650,33 @@ export const enum Direction {
650 Down = "Down" 650 Down = "Down"
651} 651}
652``` 652```
653
654## Lookup workspace symbol search scope and kind
655
656**Issue:** https://github.com/rust-analyzer/rust-analyzer/pull/7698
657
658This request is sent from client to server to search for workspace symbols filtered by an
659optional search scope and / or an optional symbol kind.
660
661**Method:** `workspace/symbol`
662
663**Request:** `WorkspaceSymbolParams`
664
665**Response:** `SymbolInformation[] | null`
666
667```typescript
668interface lsp_ext.WorkspaceSymbolParams extends WorkspaceSymbolParams {
669 searchScope?: WorkspaceSymbolSearchScope;
670 searchKind?: WorkspaceSymbolSearchKind;
671}
672
673const enum WorkspaceSymbolSearchScope {
674 Workspace = "Workspace",
675 WorkspaceAndDependencies = "WorkspaceAndDependencies"
676}
677
678const enum WorkspaceSymbolSearchKind {
679 OnlyTypes = "OnlyTypes",
680 AllSymbols = "AllSymbols"
681}
682```
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index feba43ff1..b32411887 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -341,3 +341,13 @@ Additional arguments to `rustfmt`.
341Advanced option, fully override the command rust-analyzer uses for 341Advanced option, fully override the command rust-analyzer uses for
342formatting. 342formatting.
343-- 343--
344[[rust-analyzer.workspace.symbol.search.scope]]rust-analyzer.workspace.symbol.search.scope (default: `"workspace"`)::
345+
346--
347Workspace symbol search scope.
348--
349[[rust-analyzer.workspace.symbol.search.kind]]rust-analyzer.workspace.symbol.search.kind (default: `"only_types"`)::
350+
351--
352Workspace symbol search kind.
353--
diff --git a/editors/code/package.json b/editors/code/package.json
index 2e67b6775..99223c4e8 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -783,6 +783,32 @@
783 "type": "string" 783 "type": "string"
784 } 784 }
785 }, 785 },
786 "rust-analyzer.workspace.symbol.search.scope": {
787 "markdownDescription": "Workspace symbol search scope.",
788 "default": "workspace",
789 "type": "string",
790 "enum": [
791 "workspace",
792 "workspace_and_dependencies"
793 ],
794 "enumDescriptions": [
795 "Search in current workspace only",
796 "Search in current workspace and dependencies"
797 ]
798 },
799 "rust-analyzer.workspace.symbol.search.kind": {
800 "markdownDescription": "Workspace symbol search kind.",
801 "default": "only_types",
802 "type": "string",
803 "enum": [
804 "only_types",
805 "all_symbols"
806 ],
807 "enumDescriptions": [
808 "Search for types only",
809 "Search for all symbols kinds"
810 ]
811 },
786 "$generated-end": false 812 "$generated-end": false
787 } 813 }
788 }, 814 },