diff --git a/Cargo.lock b/Cargo.lock index b482ca28f9..619f652024 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -654,6 +654,7 @@ dependencies = [ "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "flexi_logger 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "gen_lsp_server 0.1.0", "im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 2b32571171..e4fc40a3a5 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -8,6 +8,7 @@ authors = ["Aleksey Kladov "] rayon = "1.0.2" relative-path = "0.3.7" failure = "0.1.2" +failure_derive = "0.1.2" serde_json = "1.0.24" serde = "1.0.71" serde_derive = "1.0.71" diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index f1b17f2825..ce77b2a33d 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs @@ -12,6 +12,8 @@ extern crate rayon; extern crate log; extern crate cargo_metadata; extern crate drop_bomb; +#[macro_use] +extern crate failure_derive; extern crate im; extern crate relative_path; extern crate rustc_hash; @@ -34,4 +36,4 @@ pub mod thread_watcher; mod vfs; pub type Result = ::std::result::Result; -pub use crate::{caps::server_capabilities, main_loop::main_loop}; +pub use crate::{caps::server_capabilities, main_loop::main_loop, main_loop::LspError}; \ No newline at end of file diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index f5dff4c80a..baf82f3fcd 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -7,6 +7,7 @@ use languageserver_types::{ InsertTextFormat, Location, Position, SymbolInformation, TextDocumentIdentifier, TextEdit, RenameParams, WorkspaceEdit, PrepareRenameResponse }; +use gen_lsp_server::ErrorCode; use ra_analysis::{FileId, FoldKind, Query, RunnableKind}; use ra_syntax::text_utils::contains_offset_nonstrict; use serde_json::to_value; @@ -16,7 +17,7 @@ use crate::{ project_model::TargetKind, req::{self, Decoration}, server_world::ServerWorld, - Result, + Result, LspError }; pub fn handle_syntax_tree( @@ -476,7 +477,7 @@ pub fn handle_rename( let offset = params.position.conv_with(&line_index); if params.new_name.is_empty() { - return Ok(None); + return Err(LspError::new(ErrorCode::InvalidParams as i32, "New Name cannot be empty".into()).into()); } let refs = world.analysis().find_all_refs(file_id, offset)?; diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs index b35ebd38b6..aa3cf1dbd2 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop/mod.rs @@ -23,6 +23,19 @@ use crate::{ Result, }; +#[derive(Debug, Fail)] +#[fail(display = "Language Server request failed with {}. ({})", code, message)] +pub struct LspError { + pub code: i32, + pub message: String, +} + +impl LspError { + pub fn new(code: i32, message: String) -> LspError { + LspError {code, message} + } +} + #[derive(Debug)] enum Task { Respond(RawResponse), @@ -361,7 +374,10 @@ impl<'a> PoolDispatcher<'a> { let resp = match f(world, params) { Ok(resp) => RawResponse::ok::(id, &resp), Err(e) => { - RawResponse::err(id, ErrorCode::InternalError as i32, e.to_string()) + match e.downcast::() { + Ok(lsp_error) => RawResponse::err(id, lsp_error.code, lsp_error.message), + Err(e) => RawResponse::err(id, ErrorCode::InternalError as i32, e.to_string()) + } } }; let task = Task::Respond(resp);