diff --git a/src/actions/mod.rs b/src/actions/mod.rs index dd4feef2398..fc253ea6d94 100644 --- a/src/actions/mod.rs +++ b/src/actions/mod.rs @@ -20,9 +20,10 @@ use span; use Span; use actions::post_build::{BuildResults, PostBuildHandler}; +use actions::notifications::BeginBuild; use build::*; use lsp_data::*; -use server::Output; +use server::{Output, Notification, NoParams}; use std::collections::HashMap; use std::path::{Path, PathBuf}; @@ -194,7 +195,7 @@ impl InitActionContext { } }; - out.notify(NotificationMessage::new(NOTIFICATION_BUILD_BEGIN, None)); + out.notify(Notification::::new(NoParams {})); self.build_queue .request_build(project_path, priority, move |result| pbh.handle(result)); } diff --git a/src/actions/notifications.rs b/src/actions/notifications.rs index 66db9b86d7a..35e715ef618 100644 --- a/src/actions/notifications.rs +++ b/src/actions/notifications.rs @@ -369,3 +369,54 @@ impl<'a> BlockingNotificationAction<'a> for DidChangeWatchedFiles { Ok(()) } } + +/// Notification sent to client, used to publish file diagnostics +/// (warnings, errors) from the server. +#[derive(Debug)] +pub struct PublishDiagnostics; + +impl Action for PublishDiagnostics { + type Params = PublishDiagnosticsParams; + const METHOD: &'static str = NOTIFICATION__PublishDiagnostics; +} + +/// Notification sent to client, asking to show a specified message with a given type. +#[derive(Debug)] +pub struct ShowMessage; + +impl Action for ShowMessage { + type Params = ShowMessageParams; + const METHOD: &'static str = NOTIFICATION__ShowMessage; +} + +/// Custom LSP notification sent to client indicating that the server is currently +/// processing data and may publish new diagnostics on `rustDocument/diagnosticsEnd`. +#[derive(Debug)] +pub struct DiagnosticsBegin; + +impl Action for DiagnosticsBegin { + type Params = NoParams; + const METHOD: &'static str = "rustDocument/diagnosticsBegin"; +} + +/// Custom LSP notification sent to client indicating that data processing started +/// by a `rustDocument`/diagnosticsBegin` has ended. +/// For each `diagnosticsBegin` message, there is a single `diagnosticsEnd` message. +/// This means that for multiple active `diagnosticsBegin` messages, there will +/// be sent multiple `diagnosticsEnd` notifications. +#[derive(Debug)] +pub struct DiagnosticsEnd; + +impl Action for DiagnosticsEnd { + type Params = NoParams; + const METHOD: &'static str = "rustDocument/diagnosticsEnd"; +} + +/// Custom LSP notification sent to client indicating that a build process has begun. +#[derive(Debug)] +pub struct BeginBuild; + +impl Action for BeginBuild { + type Params = NoParams; + const METHOD: &'static str = "rustDocument/beginBuild"; +} diff --git a/src/actions/post_build.rs b/src/actions/post_build.rs index 3cf35644797..3269113c296 100644 --- a/src/actions/post_build.rs +++ b/src/actions/post_build.rs @@ -14,15 +14,15 @@ use std::sync::{Arc, Mutex}; use std::thread; use build::BuildResult; -use lsp_data::{ls_util, NotificationMessage, PublishDiagnosticsParams}; -use lsp_data::{NOTIFICATION_DIAGNOSTICS_BEGIN, NOTIFICATION_DIAGNOSTICS_END}; -use server::Output; +use lsp_data::{ls_util, PublishDiagnosticsParams}; +use actions::notifications::{DiagnosticsBegin, DiagnosticsEnd, PublishDiagnostics}; +use server::{Notification, Output, NoParams}; use CRATE_BLACKLIST; use Span; use analysis::AnalysisHost; use data::Analysis; -use ls_types::{self, Diagnostic, DiagnosticSeverity, NumberOrString, Range}; +use ls_types::{Diagnostic, DiagnosticSeverity, NumberOrString, Range}; use serde_json; use span::compiler::DiagnosticSpan; use url::Url; @@ -41,21 +41,17 @@ pub struct PostBuildHandler { impl PostBuildHandler { pub fn handle(self, result: BuildResult) { - // We use `rustDocument` document here since these notifications are - // custom to the RLS and not part of the LS protocol. - self.out.notify(NotificationMessage::new( - NOTIFICATION_DIAGNOSTICS_BEGIN, - None, - )); + self.out.notify(Notification::::new(NoParams {})); match result { BuildResult::Success(messages, new_analysis) => { thread::spawn(move || { trace!("build - Success"); + // Emit appropriate diagnostics using the ones from build. self.handle_messages(messages); - // Handle the analysis data. + // Reload the analysis data. debug!("reload analysis: {:?}", self.project_path); if new_analysis.is_empty() { self.reload_analysis_from_disk(); @@ -63,19 +59,16 @@ impl PostBuildHandler { self.reload_analysis_from_memory(new_analysis); } - self.out - .notify(NotificationMessage::new(NOTIFICATION_DIAGNOSTICS_END, None)); + self.out.notify(Notification::::new(NoParams{})); }); } BuildResult::Squashed => { trace!("build - Squashed"); - self.out - .notify(NotificationMessage::new(NOTIFICATION_DIAGNOSTICS_END, None)); + self.out.notify(Notification::::new(NoParams{})); } BuildResult::Err => { trace!("build - Error"); - self.out - .notify(NotificationMessage::new(NOTIFICATION_DIAGNOSTICS_END, None)); + self.out.notify(Notification::::new(NoParams{})); } } } @@ -252,9 +245,6 @@ fn emit_notifications(build_results: &BuildResults, show_warnings: bo .collect(), }; - out.notify(NotificationMessage::new( - ls_types::NOTIFICATION__PublishDiagnostics, - Some(params), - )); + out.notify(Notification::::new(params)); } } diff --git a/src/lsp_data.rs b/src/lsp_data.rs index 36f53f29f3a..f571754d0f6 100644 --- a/src/lsp_data.rs +++ b/src/lsp_data.rs @@ -23,14 +23,6 @@ use racer; use vfs::FileContents; pub use ls_types::*; -use jsonrpc_core::version; - -/// Notification string for beginning diagnostics. -pub const NOTIFICATION_DIAGNOSTICS_BEGIN: &'static str = "rustDocument/diagnosticsBegin"; -/// Notification string for ending diagnostics. -pub const NOTIFICATION_DIAGNOSTICS_END: &'static str = "rustDocument/diagnosticsEnd"; -/// Notification string for when a build begins. -pub const NOTIFICATION_BUILD_BEGIN: &'static str = "rustDocument/beginBuild"; /// Errors that can occur when parsing a file URI. #[derive(Debug)] @@ -270,27 +262,6 @@ impl Default for InitializationOptions { } } -/// An event-like (no response needed) notification message. -#[derive(Debug, Serialize)] -pub struct NotificationMessage { - jsonrpc: version::Version, - /// The well-known language server protocol notification method string. - pub method: &'static str, - /// Extra notification parameters. - pub params: Option, -} - -impl NotificationMessage { - /// Construct a new notification message. - pub fn new(method: &'static str, params: Option) -> Self { - NotificationMessage { - jsonrpc: version::Version::V2, - method, - params, - } - } -} - /// A JSON language server protocol request that will have a matching response. #[derive(Debug, Serialize)] pub struct RequestMessage diff --git a/src/server/io.rs b/src/server/io.rs index e053fe46104..912fc5ef519 100644 --- a/src/server/io.rs +++ b/src/server/io.rs @@ -10,7 +10,7 @@ use serde_json; -use lsp_data::*; +use super::{Action, Notification}; use std::fmt; use std::io::{self, Read, Write}; @@ -143,8 +143,8 @@ pub trait Output: Sync + Send + Clone + 'static { } /// Send a notification along the output. - fn notify(&self, notification: NotificationMessage) { - self.response(serde_json::to_string(¬ification).unwrap()); + fn notify(&self, notification: Notification) { + self.response(format!("{}", notification)); } } diff --git a/src/server/mod.rs b/src/server/mod.rs index 3bc37181861..30ecfcd3d38 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -153,6 +153,16 @@ pub struct Notification { pub _action: PhantomData, } +impl Notification { + /// Creates a `Notification` structure with given `params`. + pub fn new(params: A::Params) -> Notification { + Notification { + params, + _action: PhantomData + } + } +} + impl<'a, A: BlockingRequestAction<'a>> Request { fn blocking_dispatch( self, @@ -191,7 +201,7 @@ impl<'a, A: Action> fmt::Display for Request { } } -impl<'a, A: BlockingNotificationAction<'a>> fmt::Display for Notification { +impl<'a, A: Action> fmt::Display for Notification { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { json!({ "jsonrpc": "2.0", @@ -678,10 +688,7 @@ mod test { assert_eq!( notification, - Ok(Notification:: { - params: NoParams {}, - _action: PhantomData, - }) + Ok(Notification::::new(NoParams {})) ); } }