Implement workspace/symbol request

This commit is contained in:
Patrick Förster 2019-08-28 11:19:17 +02:00
parent 6689c59fe8
commit 9de957f5bf
2 changed files with 80 additions and 23 deletions

View file

@ -14,7 +14,7 @@ use crate::hover::HoverProvider;
use crate::link::LinkProvider;
use crate::reference::ReferenceProvider;
use crate::rename::{PrepareRenameProvider, RenameProvider};
use crate::symbol::{SymbolProvider, SymbolResponse};
use crate::symbol::{self, SymbolProvider, SymbolResponse};
use crate::syntax::*;
use crate::workspace::*;
use futures::lock::Mutex;
@ -109,7 +109,7 @@ impl<C: LspClient + Send + Sync + 'static> LatexLspServer<C> {
references_provider: Some(true),
document_highlight_provider: Some(true),
document_symbol_provider: Some(true),
workspace_symbol_provider: None,
workspace_symbol_provider: Some(true),
code_action_provider: None,
code_lens_provider: None,
document_formatting_provider: Some(true),
@ -295,6 +295,17 @@ impl<C: LspClient + Send + Sync + 'static> LatexLspServer<C> {
Ok(results)
}
#[jsonrpc_method("workspace/symbol", kind = "request")]
pub async fn workspace_symbol(
&self,
params: WorkspaceSymbolParams,
) -> Result<Vec<SymbolInformation>> {
let client_capabilities = Arc::clone(&self.client_capabilities.get().unwrap());
let workspace = self.workspace_manager.get();
let symbols = symbol::workspace_symbols(client_capabilities, workspace, &params).await;
Ok(symbols)
}
#[jsonrpc_method("textDocument/documentSymbol", kind = "request")]
pub async fn document_symbol(&self, params: DocumentSymbolParams) -> Result<SymbolResponse> {
let request = self.make_feature_request(params.text_document.as_uri(), params)?;

View file

@ -10,6 +10,7 @@ use crate::workspace::*;
use futures_boxed::boxed;
use lsp_types::*;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
pub struct SymbolProvider {
provider: ConcatProvider<DocumentSymbolParams, DocumentSymbol>,
@ -59,31 +60,76 @@ impl SymbolResponse {
if client_capabilities.has_hierarchical_document_symbol_support() {
Self::Hierarchical(symbols)
} else {
fn flatten(results: &mut Vec<SymbolInformation>, uri: &Uri, symbol: DocumentSymbol) {
if symbol.kind == SymbolKind::Field {
return;
}
let info = SymbolInformation {
name: symbol.name,
deprecated: Some(false),
kind: symbol.kind,
container_name: None,
location: Location::new(uri.clone().into(), symbol.range),
};
results.push(info);
if let Some(children) = symbol.children {
for child in children {
flatten(results, uri, child);
}
}
}
let mut results = Vec::new();
for symbol in symbols {
flatten(&mut results, uri, symbol);
Self::flatten(&mut results, uri, symbol);
}
Self::Flat(results)
}
}
fn flatten(results: &mut Vec<SymbolInformation>, uri: &Uri, symbol: DocumentSymbol) {
if symbol.kind == SymbolKind::Field {
return;
}
let info = SymbolInformation {
name: symbol.name,
deprecated: Some(false),
kind: symbol.kind,
container_name: None,
location: Location::new(uri.clone().into(), symbol.range),
};
results.push(info);
if let Some(children) = symbol.children {
for child in children {
Self::flatten(results, uri, child);
}
}
}
}
pub async fn workspace_symbols(
client_capabilities: Arc<ClientCapabilities>,
workspace: Arc<Workspace>,
params: &WorkspaceSymbolParams,
) -> Vec<SymbolInformation> {
let provider = SymbolProvider::new();
let mut all_symbols = Vec::new();
for document in &workspace.documents {
let uri: Uri = document.uri.clone();
let request = FeatureRequest {
client_capabilities: Arc::clone(&client_capabilities),
view: DocumentView::new(Arc::clone(&workspace), Arc::clone(&document)),
params: DocumentSymbolParams {
text_document: TextDocumentIdentifier::new(uri.clone().into()),
},
};
for symbol in provider.execute(&request).await {
SymbolResponse::flatten(&mut all_symbols, &uri, symbol);
}
}
let query_words: Vec<String> = params
.query
.split_whitespace()
.map(str::to_lowercase)
.collect();
let mut filtered_symbols = Vec::new();
for symbol in all_symbols {
let name = symbol.name.to_lowercase();
let mut included = true;
for word in &query_words {
if !name.contains(word) {
included = false;
break;
}
}
if included {
filtered_symbols.push(symbol);
}
}
filtered_symbols
}