workspace symbols

This commit is contained in:
Aleksey Kladov 2018-08-13 15:35:53 +03:00
parent 133d001d82
commit d19f3ac834
9 changed files with 75 additions and 43 deletions

View file

@ -61,9 +61,9 @@ export function deactivate(): Thenable<void> {
function startServer() { function startServer() {
let run: lc.Executable = { let run: lc.Executable = {
command: "cargo", // command: "cargo",
args: ["run", "--package", "m"], // args: ["run", "--package", "m"],
// command: "m", command: "m",
options: { cwd: "." } options: { cwd: "." }
} }
let serverOptions: lc.ServerOptions = { let serverOptions: lc.ServerOptions = {

View file

@ -89,14 +89,15 @@ impl World {
Ok(index.clone()) 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); let q = Query::new(query);
for (path, data) in self.data.file_map.iter() { self.data.file_map.iter()
let symbols = data.symbols(path.as_path()); .flat_map(move |(path, data)| {
if q.process(symbols, &mut |symbol| f(path, symbol)) == Search::Break { let path: &'a Path = path.as_path();
break; let symbols = data.symbols(path);
} q.process(symbols).map(move |s| (path, s))
} })
} }
fn file_data(&self, path: &Path) -> Result<Arc<FileData>> { fn file_data(&self, path: &Path) -> Result<Arc<FileData>> {
@ -107,11 +108,15 @@ impl World {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Search { pub type SearchResult = ::std::result::Result<Continue, Break>;
Continue,
Break, pub struct Continue;
}
pub struct Break;
pub const CONTINUE: SearchResult = Ok(Continue);
pub const BREAK: SearchResult = Err(Break);
#[derive(Default, Debug)] #[derive(Default, Debug)]

View file

@ -5,8 +5,6 @@ use libsyntax2::{
}; };
use fst::{self, IntoStreamer}; use fst::{self, IntoStreamer};
use Search;
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct FileSymbols { pub(crate) struct FileSymbols {
symbols: Vec<FileSymbol>, symbols: Vec<FileSymbol>,
@ -47,11 +45,10 @@ impl Query {
Query { query, all_symbols } Query { query, all_symbols }
} }
pub(crate) fn process( pub(crate) fn process<'a>(
&self, &self,
file: &FileSymbols, file: &'a FileSymbols,
acc: &mut FnMut(&FileSymbol) -> Search, ) -> impl Iterator<Item=&'a FileSymbol> + 'a {
) -> Search {
fn is_type(kind: SyntaxKind) -> bool { fn is_type(kind: SyntaxKind) -> bool {
match kind { match kind {
STRUCT | ENUM | TRAIT | TYPE_ITEM => true, STRUCT | ENUM | TRAIT | TYPE_ITEM => true,
@ -59,16 +56,15 @@ impl Query {
} }
} }
let automaton = fst::automaton::Subsequence::new(&self.query); let automaton = fst::automaton::Subsequence::new(&self.query);
for idx in file.map.search(automaton).into_stream().into_values() { let all_symbols = self.all_symbols;
let idx = idx as usize; file.map.search(automaton).into_stream()
let symbol = &file.symbols[idx]; .into_values()
if self.all_symbols || is_type(symbol.kind) { .into_iter()
if acc(&symbol) == Search::Break { .map(move |idx| {
return Search::Break; let idx = idx as usize;
} &file.symbols[idx]
} })
} .filter(move |s| all_symbols || is_type(s.kind))
Search::Continue
} }
} }

View file

@ -26,7 +26,7 @@ pub fn server_capabilities() -> ServerCapabilities {
references_provider: None, references_provider: None,
document_highlight_provider: None, document_highlight_provider: None,
document_symbol_provider: Some(true), document_symbol_provider: Some(true),
workspace_symbol_provider: None, workspace_symbol_provider: Some(true),
code_action_provider: Some(true), code_action_provider: Some(true),
code_lens_provider: None, code_lens_provider: None,
document_formatting_provider: None, document_formatting_provider: None,

View file

@ -30,8 +30,12 @@ impl<R: ClientRequest> Responder<R> {
error: serde_json::Value::Null, error: serde_json::Value::Null,
} }
} }
Err(_) => { Err(e) => {
error_response(self.id, ErrorCode::InternalError, "internal error")? error_response(
self.id,
ErrorCode::InternalError,
format!("internal error: {}", e),
)?
} }
}; };
Ok(res) Ok(res)
@ -115,21 +119,20 @@ pub fn send_notification<N>(params: N::Params) -> RawNotification
pub fn unknown_method(id: u64) -> Result<RawResponse> { pub fn unknown_method(id: u64) -> Result<RawResponse> {
error_response(id, ErrorCode::MethodNotFound, "unknown method") 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)] #[derive(Serialize)]
struct Error { struct Error {
code: i32, code: i32,
message: &'static str, message: String,
} }
let resp = RawResponse { let resp = RawResponse {
id, id,
result: serde_json::Value::Null, result: serde_json::Value::Null,
error: serde_json::to_value(Error { error: serde_json::to_value(Error {
code: code as i32, code: code as i32,
message, message: message.into(),
})?, })?,
}; };
Ok(resp) Ok(resp)

View file

@ -27,8 +27,6 @@ mod conv;
mod main_loop; mod main_loop;
mod vfs; mod vfs;
use std::path::PathBuf;
use threadpool::ThreadPool; use threadpool::ThreadPool;
use crossbeam_channel::bounded; use crossbeam_channel::bounded;
use flexi_logger::{Logger, Duplicate}; use flexi_logger::{Logger, Duplicate};
@ -120,7 +118,7 @@ fn initialized(io: &mut Io) -> Result<()> {
let mut pool = ThreadPool::new(4); let mut pool = ThreadPool::new(4);
let (task_sender, task_receiver) = bounded::<Task>(16); let (task_sender, task_receiver) = bounded::<Task>(16);
let (fs_events_receiver, watcher) = vfs::watch(vec![ let (fs_events_receiver, watcher) = vfs::watch(vec![
PathBuf::from("./") ::std::env::current_dir()?,
]); ]);
info!("lifecycle: handshake finished, server ready to serve requests"); info!("lifecycle: handshake finished, server ready to serve requests");
let res = main_loop::main_loop( let res = main_loop::main_loop(

View file

@ -2,9 +2,10 @@ use std::collections::HashMap;
use languageserver_types::{ use languageserver_types::{
Diagnostic, DiagnosticSeverity, Url, DocumentSymbol, Diagnostic, DiagnosticSeverity, Url, DocumentSymbol,
Command, TextDocumentIdentifier, WorkspaceEdit Command, TextDocumentIdentifier, WorkspaceEdit,
SymbolInformation, Location,
}; };
use libanalysis::World; use libanalysis::{World};
use libeditor; use libeditor;
use libsyntax2::TextUnit; use libsyntax2::TextUnit;
use serde_json::{to_value, from_value}; use serde_json::{to_value, from_value};
@ -94,6 +95,30 @@ pub fn handle_code_action(
Ok(ret) 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(&params.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( pub fn handle_execute_command(
world: World, world: World,
mut params: req::ExecuteCommandParams, mut params: req::ExecuteCommandParams,

View file

@ -25,6 +25,7 @@ use {
handle_document_symbol, handle_document_symbol,
handle_code_action, handle_code_action,
handle_execute_command, handle_execute_command,
handle_workspace_symbol,
}, },
}; };
@ -148,6 +149,9 @@ fn on_request(
handle_request_on_threadpool::<req::CodeActionRequest>( handle_request_on_threadpool::<req::CodeActionRequest>(
&mut req, pool, world, sender, handle_code_action, &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| { dispatch::handle_request::<req::ExecuteCommand, _>(&mut req, |params, resp| {
io.send(RawMsg::Response(resp.into_response(Ok(None))?)); io.send(RawMsg::Response(resp.into_response(Ok(None))?));

View file

@ -8,6 +8,7 @@ pub use languageserver_types::{
DocumentSymbolParams, DocumentSymbolResponse, DocumentSymbolParams, DocumentSymbolResponse,
CodeActionParams, ApplyWorkspaceEditParams, CodeActionParams, ApplyWorkspaceEditParams,
ExecuteCommandParams, ExecuteCommandParams,
WorkspaceSymbolParams,
}; };