diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-05-18 20:20:51 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-05-18 20:20:51 +0100 |
commit | 49a5d6a8d4a5da296ead4c44ac43090b9b0e8034 (patch) | |
tree | ca54a00fe5e9a447ab100ad36905004f0629f655 /crates | |
parent | 16b03d21dcbac48133fa9be1051c78211e83bbe8 (diff) | |
parent | 1f7d2a6c2297de4dedfb42b739e880ad2dd7d5d5 (diff) |
Merge #7698
7698: Add new LSP extension for workspace symbol lookup r=matklad a=alcroito
As well as all symbol types (functions, modules).
Remove outdated documentation regarding symbol lookup filtering.
Closes #4881
Co-authored-by: alcroito <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ide_db/src/symbol_index.rs | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 63 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 48 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_ext.rs | 42 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 2 |
5 files changed, 153 insertions, 7 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 | ||
25 | use crate::{ | 25 | use 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)] | ||
320 | pub 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 | |||
312 | impl Config { | 327 | impl 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")] | ||
769 | enum WorskpaceSymbolSearchScopeDef { | ||
770 | Workspace, | ||
771 | WorkspaceAndDependencies, | ||
772 | } | ||
773 | |||
774 | #[derive(Deserialize, Debug, Clone)] | ||
775 | #[serde(rename_all = "snake_case")] | ||
776 | enum WorskpaceSymbolSearchKindDef { | ||
777 | OnlyTypes, | ||
778 | AllSymbols, | ||
779 | } | ||
780 | |||
736 | macro_rules! _config_data { | 781 | macro_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 | ||
381 | pub(crate) fn handle_workspace_symbol( | 381 | pub(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(¶ms, &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 | ||
5 | use lsp_types::request::Request; | 5 | use lsp_types::request::Request; |
6 | use lsp_types::{ | 6 | use lsp_types::{ |
7 | notification::Notification, CodeActionKind, Position, Range, TextDocumentIdentifier, | 7 | notification::Notification, CodeActionKind, PartialResultParams, Position, Range, |
8 | TextDocumentIdentifier, WorkDoneProgressParams, | ||
8 | }; | 9 | }; |
9 | use serde::{Deserialize, Serialize}; | 10 | use 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)] | ||
444 | pub enum WorkspaceSymbol {} | ||
445 | |||
446 | impl 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)] | ||
453 | pub 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")] | ||
470 | pub enum WorkspaceSymbolSearchScope { | ||
471 | Workspace, | ||
472 | WorkspaceAndDependencies, | ||
473 | } | ||
474 | |||
475 | #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] | ||
476 | #[serde(rename_all = "camelCase")] | ||
477 | pub 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) |