Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new LSP extension for workspace symbol lookup #7698

Merged
merged 1 commit into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/ide_db/src/symbol_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> {
// That is, `#` switches from "types" to all symbols, `*` switches from the current
// workspace to dependencies.
//
// Note that filtering does not currently work in VSCode due to the editor never
// sending the special symbols to the language server. Instead, you can configure
// the filtering via the `rust-analyzer.workspace.symbol.search.scope` and
// `rust-analyzer.workspace.symbol.search.kind` settings.
//
// |===
// | Editor | Shortcut
//
Expand Down
63 changes: 62 additions & 1 deletion crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use vfs::AbsPathBuf;

use crate::{
caps::completion_item_edit_resolve, diagnostics::DiagnosticsMapConfig,
line_index::OffsetEncoding, lsp_ext::supports_utf8,
line_index::OffsetEncoding, lsp_ext::supports_utf8, lsp_ext::WorkspaceSymbolSearchKind,
lsp_ext::WorkspaceSymbolSearchScope,
};

// Defines the server-side configuration of the rust-analyzer. We generate
Expand Down Expand Up @@ -215,6 +216,11 @@ config_data! {
/// Advanced option, fully override the command rust-analyzer uses for
/// formatting.
rustfmt_overrideCommand: Option<Vec<String>> = "null",

/// Workspace symbol search scope.
workspace_symbol_search_scope: WorskpaceSymbolSearchScopeDef = "\"workspace\"",
/// Workspace symbol search kind.
workspace_symbol_search_kind: WorskpaceSymbolSearchKindDef = "\"only_types\"",
}
}

Expand Down Expand Up @@ -309,6 +315,15 @@ pub struct RunnablesConfig {
pub cargo_extra_args: Vec<String>,
}

/// Configuration for workspace symbol search requests.
#[derive(Debug, Clone)]
pub struct WorkspaceSymbolConfig {
/// In what scope should the symbol be searched in.
pub search_scope: WorkspaceSymbolSearchScope,
/// What kind of symbol is being search for.
pub search_kind: WorkspaceSymbolSearchKind,
}

impl Config {
pub fn new(root_path: AbsPathBuf, caps: ClientCapabilities) -> Self {
Config { caps, data: ConfigData::default(), discovered_projects: None, root_path }
Expand Down Expand Up @@ -687,6 +702,22 @@ impl Config {
.contains(&MarkupKind::Markdown),
}
}

pub fn workspace_symbol(&self) -> WorkspaceSymbolConfig {
WorkspaceSymbolConfig {
search_scope: match self.data.workspace_symbol_search_scope {
WorskpaceSymbolSearchScopeDef::Workspace => WorkspaceSymbolSearchScope::Workspace,
WorskpaceSymbolSearchScopeDef::WorkspaceAndDependencies => {
WorkspaceSymbolSearchScope::WorkspaceAndDependencies
}
},
search_kind: match self.data.workspace_symbol_search_kind {
WorskpaceSymbolSearchKindDef::OnlyTypes => WorkspaceSymbolSearchKind::OnlyTypes,
WorskpaceSymbolSearchKindDef::AllSymbols => WorkspaceSymbolSearchKind::AllSymbols,
},
}
}

pub fn semantic_tokens_refresh(&self) -> bool {
try_or!(self.caps.workspace.as_ref()?.semantic_tokens.as_ref()?.refresh_support?, false)
}
Expand Down Expand Up @@ -733,6 +764,20 @@ enum ImportPrefixDef {
ByCrate,
}

#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
enum WorskpaceSymbolSearchScopeDef {
Workspace,
WorkspaceAndDependencies,
}

#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
enum WorskpaceSymbolSearchKindDef {
OnlyTypes,
AllSymbols,
}

macro_rules! _config_data {
(struct $name:ident {
$(
Expand Down Expand Up @@ -903,6 +948,22 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
"type": "array",
"items": { "type": ["string", "object"] },
},
"WorskpaceSymbolSearchScopeDef" => set! {
"type": "string",
"enum": ["workspace", "workspace_and_dependencies"],
"enumDescriptions": [
"Search in current workspace only",
"Search in current workspace and dependencies"
],
},
"WorskpaceSymbolSearchKindDef" => set! {
"type": "string",
"enum": ["only_types", "all_symbols"],
"enumDescriptions": [
"Search for types only",
"Search for all symbols kinds"
],
},
_ => panic!("{}: {}", ty, default),
}

Expand Down
48 changes: 44 additions & 4 deletions crates/rust-analyzer/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use crate::{
from_proto,
global_state::{GlobalState, GlobalStateSnapshot},
line_index::LineEndings,
lsp_ext::{self, InlayHint, InlayHintsParams},
lsp_ext::{self, InlayHint, InlayHintsParams, WorkspaceSymbolParams},
lsp_utils::all_edits_are_disjoint,
to_proto, LspError, Result,
};
Expand Down Expand Up @@ -380,11 +380,12 @@ pub(crate) fn handle_document_symbol(

pub(crate) fn handle_workspace_symbol(
snap: GlobalStateSnapshot,
params: lsp_types::WorkspaceSymbolParams,
params: WorkspaceSymbolParams,
) -> Result<Option<Vec<SymbolInformation>>> {
let _p = profile::span("handle_workspace_symbol");
let all_symbols = params.query.contains('#');
let libs = params.query.contains('*');

let (all_symbols, libs) = decide_search_scope_and_kind(&params, &snap);

let query = {
let query: String = params.query.chars().filter(|&c| c != '#' && c != '*').collect();
let mut q = Query::new(query);
Expand All @@ -406,6 +407,45 @@ pub(crate) fn handle_workspace_symbol(

return Ok(Some(res));

fn decide_search_scope_and_kind(
params: &WorkspaceSymbolParams,
snap: &GlobalStateSnapshot,
) -> (bool, bool) {
// Support old-style parsing of markers in the query.
let mut all_symbols = params.query.contains('#');
let mut libs = params.query.contains('*');

let config = snap.config.workspace_symbol();

// If no explicit marker was set, check request params. If that's also empty
// use global config.
if !all_symbols {
let search_kind = if let Some(ref search_kind) = params.search_kind {
search_kind
} else {
&config.search_kind
};
all_symbols = match search_kind {
lsp_ext::WorkspaceSymbolSearchKind::OnlyTypes => false,
lsp_ext::WorkspaceSymbolSearchKind::AllSymbols => true,
}
}

if !libs {
let search_scope = if let Some(ref search_scope) = params.search_scope {
search_scope
} else {
&config.search_scope
};
libs = match search_scope {
lsp_ext::WorkspaceSymbolSearchScope::Workspace => false,
lsp_ext::WorkspaceSymbolSearchScope::WorkspaceAndDependencies => true,
}
}

(all_symbols, libs)
}

fn exec_query(snap: &GlobalStateSnapshot, query: Query) -> Result<Vec<SymbolInformation>> {
let mut res = Vec::new();
for nav in snap.analysis.symbol_search(query)? {
Expand Down
42 changes: 41 additions & 1 deletion crates/rust-analyzer/src/lsp_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::{collections::HashMap, path::PathBuf};

use lsp_types::request::Request;
use lsp_types::{
notification::Notification, CodeActionKind, Position, Range, TextDocumentIdentifier,
notification::Notification, CodeActionKind, PartialResultParams, Position, Range,
TextDocumentIdentifier, WorkDoneProgressParams,
};
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -438,3 +439,42 @@ pub enum MoveItemDirection {
Up,
Down,
}

#[derive(Debug)]
pub enum WorkspaceSymbol {}

impl Request for WorkspaceSymbol {
type Params = WorkspaceSymbolParams;
type Result = Option<Vec<lsp_types::SymbolInformation>>;
const METHOD: &'static str = "workspace/symbol";
}

#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
pub struct WorkspaceSymbolParams {
#[serde(flatten)]
pub partial_result_params: PartialResultParams,

#[serde(flatten)]
pub work_done_progress_params: WorkDoneProgressParams,

/// A non-empty query string
pub query: String,

pub search_scope: Option<WorkspaceSymbolSearchScope>,

pub search_kind: Option<WorkspaceSymbolSearchKind>,
}

#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum WorkspaceSymbolSearchScope {
Workspace,
WorkspaceAndDependencies,
}

#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum WorkspaceSymbolSearchKind {
OnlyTypes,
AllSymbols,
}
2 changes: 1 addition & 1 deletion crates/rust-analyzer/src/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,9 @@ impl GlobalState {
.on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs)
.on::<lsp_ext::OpenCargoToml>(handlers::handle_open_cargo_toml)
.on::<lsp_ext::MoveItem>(handlers::handle_move_item)
.on::<lsp_ext::WorkspaceSymbol>(handlers::handle_workspace_symbol)
.on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting)
.on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol)
.on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol)
.on::<lsp_types::request::GotoDefinition>(handlers::handle_goto_definition)
.on::<lsp_types::request::GotoImplementation>(handlers::handle_goto_implementation)
.on::<lsp_types::request::GotoTypeDefinition>(handlers::handle_goto_type_definition)
Expand Down
32 changes: 31 additions & 1 deletion docs/dev/lsp-extensions.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!---
lsp_ext.rs hash: 6e57fc1b345b00e9
lsp_ext.rs hash: 10a8988e6893e6b2

If you need to change the above hash to make the test pass, please check if you
need to adjust this doc as well and ping this issue:
Expand Down Expand Up @@ -650,3 +650,33 @@ export const enum Direction {
Down = "Down"
}
```

## Lookup workspace symbol search scope and kind

**Issue:** https://github.com/rust-analyzer/rust-analyzer/pull/7698

This request is sent from client to server to search for workspace symbols filtered by an
optional search scope and / or an optional symbol kind.

**Method:** `workspace/symbol`

**Request:** `WorkspaceSymbolParams`

**Response:** `SymbolInformation[] | null`

```typescript
interface lsp_ext.WorkspaceSymbolParams extends WorkspaceSymbolParams {
searchScope?: WorkspaceSymbolSearchScope;
searchKind?: WorkspaceSymbolSearchKind;
}

const enum WorkspaceSymbolSearchScope {
Workspace = "Workspace",
WorkspaceAndDependencies = "WorkspaceAndDependencies"
}

const enum WorkspaceSymbolSearchKind {
OnlyTypes = "OnlyTypes",
AllSymbols = "AllSymbols"
}
```
10 changes: 10 additions & 0 deletions docs/user/generated_config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,13 @@ Additional arguments to `rustfmt`.
Advanced option, fully override the command rust-analyzer uses for
formatting.
--
[[rust-analyzer.workspace.symbol.search.scope]]rust-analyzer.workspace.symbol.search.scope (default: `"workspace"`)::
+
--
Workspace symbol search scope.
--
[[rust-analyzer.workspace.symbol.search.kind]]rust-analyzer.workspace.symbol.search.kind (default: `"only_types"`)::
+
--
Workspace symbol search kind.
--
26 changes: 26 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,32 @@
"type": "string"
}
},
"rust-analyzer.workspace.symbol.search.scope": {
"markdownDescription": "Workspace symbol search scope.",
"default": "workspace",
"type": "string",
"enum": [
"workspace",
"workspace_and_dependencies"
],
"enumDescriptions": [
"Search in current workspace only",
"Search in current workspace and dependencies"
]
},
"rust-analyzer.workspace.symbol.search.kind": {
"markdownDescription": "Workspace symbol search kind.",
"default": "only_types",
"type": "string",
"enum": [
"only_types",
"all_symbols"
],
"enumDescriptions": [
"Search for types only",
"Search for all symbols kinds"
]
},
"$generated-end": false
}
},
Expand Down