mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
workspace symbols
This commit is contained in:
parent
133d001d82
commit
d19f3ac834
@ -61,9 +61,9 @@ export function deactivate(): Thenable<void> {
|
||||
|
||||
function startServer() {
|
||||
let run: lc.Executable = {
|
||||
command: "cargo",
|
||||
args: ["run", "--package", "m"],
|
||||
// command: "m",
|
||||
// command: "cargo",
|
||||
// args: ["run", "--package", "m"],
|
||||
command: "m",
|
||||
options: { cwd: "." }
|
||||
}
|
||||
let serverOptions: lc.ServerOptions = {
|
||||
|
@ -89,14 +89,15 @@ impl World {
|
||||
Ok(index.clone())
|
||||
}
|
||||
|
||||
pub fn world_symbols(&self, query: &str, f: &mut FnMut(&Path, &FileSymbol) -> Search) {
|
||||
pub fn world_symbols<'a>(&'a self, query: &str) -> impl Iterator<Item=(&'a Path, &'a FileSymbol)> + 'a
|
||||
{
|
||||
let q = Query::new(query);
|
||||
for (path, data) in self.data.file_map.iter() {
|
||||
let symbols = data.symbols(path.as_path());
|
||||
if q.process(symbols, &mut |symbol| f(path, symbol)) == Search::Break {
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.data.file_map.iter()
|
||||
.flat_map(move |(path, data)| {
|
||||
let path: &'a Path = path.as_path();
|
||||
let symbols = data.symbols(path);
|
||||
q.process(symbols).map(move |s| (path, s))
|
||||
})
|
||||
}
|
||||
|
||||
fn file_data(&self, path: &Path) -> Result<Arc<FileData>> {
|
||||
@ -107,11 +108,15 @@ impl World {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Search {
|
||||
Continue,
|
||||
Break,
|
||||
}
|
||||
|
||||
pub type SearchResult = ::std::result::Result<Continue, Break>;
|
||||
|
||||
pub struct Continue;
|
||||
|
||||
pub struct Break;
|
||||
|
||||
pub const CONTINUE: SearchResult = Ok(Continue);
|
||||
pub const BREAK: SearchResult = Err(Break);
|
||||
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
|
@ -5,8 +5,6 @@ use libsyntax2::{
|
||||
};
|
||||
use fst::{self, IntoStreamer};
|
||||
|
||||
use Search;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct FileSymbols {
|
||||
symbols: Vec<FileSymbol>,
|
||||
@ -47,11 +45,10 @@ impl Query {
|
||||
Query { query, all_symbols }
|
||||
}
|
||||
|
||||
pub(crate) fn process(
|
||||
pub(crate) fn process<'a>(
|
||||
&self,
|
||||
file: &FileSymbols,
|
||||
acc: &mut FnMut(&FileSymbol) -> Search,
|
||||
) -> Search {
|
||||
file: &'a FileSymbols,
|
||||
) -> impl Iterator<Item=&'a FileSymbol> + 'a {
|
||||
fn is_type(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
STRUCT | ENUM | TRAIT | TYPE_ITEM => true,
|
||||
@ -59,16 +56,15 @@ impl Query {
|
||||
}
|
||||
}
|
||||
let automaton = fst::automaton::Subsequence::new(&self.query);
|
||||
for idx in file.map.search(automaton).into_stream().into_values() {
|
||||
let idx = idx as usize;
|
||||
let symbol = &file.symbols[idx];
|
||||
if self.all_symbols || is_type(symbol.kind) {
|
||||
if acc(&symbol) == Search::Break {
|
||||
return Search::Break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Search::Continue
|
||||
let all_symbols = self.all_symbols;
|
||||
file.map.search(automaton).into_stream()
|
||||
.into_values()
|
||||
.into_iter()
|
||||
.map(move |idx| {
|
||||
let idx = idx as usize;
|
||||
&file.symbols[idx]
|
||||
})
|
||||
.filter(move |s| all_symbols || is_type(s.kind))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ pub fn server_capabilities() -> ServerCapabilities {
|
||||
references_provider: None,
|
||||
document_highlight_provider: None,
|
||||
document_symbol_provider: Some(true),
|
||||
workspace_symbol_provider: None,
|
||||
workspace_symbol_provider: Some(true),
|
||||
code_action_provider: Some(true),
|
||||
code_lens_provider: None,
|
||||
document_formatting_provider: None,
|
||||
|
@ -30,8 +30,12 @@ impl<R: ClientRequest> Responder<R> {
|
||||
error: serde_json::Value::Null,
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
error_response(self.id, ErrorCode::InternalError, "internal error")?
|
||||
Err(e) => {
|
||||
error_response(
|
||||
self.id,
|
||||
ErrorCode::InternalError,
|
||||
format!("internal error: {}", e),
|
||||
)?
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
@ -115,21 +119,20 @@ pub fn send_notification<N>(params: N::Params) -> RawNotification
|
||||
|
||||
pub fn unknown_method(id: u64) -> Result<RawResponse> {
|
||||
error_response(id, ErrorCode::MethodNotFound, "unknown method")
|
||||
|
||||
}
|
||||
|
||||
fn error_response(id: u64, code: ErrorCode, message: &'static str) -> Result<RawResponse> {
|
||||
fn error_response(id: u64, code: ErrorCode, message: impl Into<String>) -> Result<RawResponse> {
|
||||
#[derive(Serialize)]
|
||||
struct Error {
|
||||
code: i32,
|
||||
message: &'static str,
|
||||
message: String,
|
||||
}
|
||||
let resp = RawResponse {
|
||||
id,
|
||||
result: serde_json::Value::Null,
|
||||
error: serde_json::to_value(Error {
|
||||
code: code as i32,
|
||||
message,
|
||||
message: message.into(),
|
||||
})?,
|
||||
};
|
||||
Ok(resp)
|
||||
|
@ -27,8 +27,6 @@ mod conv;
|
||||
mod main_loop;
|
||||
mod vfs;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use threadpool::ThreadPool;
|
||||
use crossbeam_channel::bounded;
|
||||
use flexi_logger::{Logger, Duplicate};
|
||||
@ -120,7 +118,7 @@ fn initialized(io: &mut Io) -> Result<()> {
|
||||
let mut pool = ThreadPool::new(4);
|
||||
let (task_sender, task_receiver) = bounded::<Task>(16);
|
||||
let (fs_events_receiver, watcher) = vfs::watch(vec![
|
||||
PathBuf::from("./")
|
||||
::std::env::current_dir()?,
|
||||
]);
|
||||
info!("lifecycle: handshake finished, server ready to serve requests");
|
||||
let res = main_loop::main_loop(
|
||||
|
@ -2,9 +2,10 @@ use std::collections::HashMap;
|
||||
|
||||
use languageserver_types::{
|
||||
Diagnostic, DiagnosticSeverity, Url, DocumentSymbol,
|
||||
Command, TextDocumentIdentifier, WorkspaceEdit
|
||||
Command, TextDocumentIdentifier, WorkspaceEdit,
|
||||
SymbolInformation, Location,
|
||||
};
|
||||
use libanalysis::World;
|
||||
use libanalysis::{World};
|
||||
use libeditor;
|
||||
use libsyntax2::TextUnit;
|
||||
use serde_json::{to_value, from_value};
|
||||
@ -94,6 +95,30 @@ pub fn handle_code_action(
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn handle_workspace_symbol(
|
||||
world: World,
|
||||
params: req::WorkspaceSymbolParams,
|
||||
) -> Result<Option<Vec<SymbolInformation>>> {
|
||||
let mut acc = Vec::new();
|
||||
for (path, symbol) in world.world_symbols(¶ms.query).take(128) {
|
||||
let line_index = world.file_line_index(path)?;
|
||||
|
||||
let info = SymbolInformation {
|
||||
name: symbol.name.to_string(),
|
||||
kind: symbol.kind.conv(),
|
||||
location: Location::new(
|
||||
Url::from_file_path(path)
|
||||
.map_err(|()| format_err!("invalid url"))?,
|
||||
symbol.node_range.conv_with(&line_index),
|
||||
),
|
||||
container_name: None,
|
||||
};
|
||||
acc.push(info);
|
||||
};
|
||||
|
||||
Ok(Some(acc))
|
||||
}
|
||||
|
||||
pub fn handle_execute_command(
|
||||
world: World,
|
||||
mut params: req::ExecuteCommandParams,
|
||||
|
@ -25,6 +25,7 @@ use {
|
||||
handle_document_symbol,
|
||||
handle_code_action,
|
||||
handle_execute_command,
|
||||
handle_workspace_symbol,
|
||||
},
|
||||
};
|
||||
|
||||
@ -148,6 +149,9 @@ fn on_request(
|
||||
handle_request_on_threadpool::<req::CodeActionRequest>(
|
||||
&mut req, pool, world, sender, handle_code_action,
|
||||
)?;
|
||||
handle_request_on_threadpool::<req::WorkspaceSymbol>(
|
||||
&mut req, pool, world, sender, handle_workspace_symbol,
|
||||
)?;
|
||||
dispatch::handle_request::<req::ExecuteCommand, _>(&mut req, |params, resp| {
|
||||
io.send(RawMsg::Response(resp.into_response(Ok(None))?));
|
||||
|
||||
|
@ -8,6 +8,7 @@ pub use languageserver_types::{
|
||||
DocumentSymbolParams, DocumentSymbolResponse,
|
||||
CodeActionParams, ApplyWorkspaceEditParams,
|
||||
ExecuteCommandParams,
|
||||
WorkspaceSymbolParams,
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user