From 28df377759ee5625b0dad4c797be306c8d2624e3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 6 Sep 2019 16:25:24 +0300 Subject: add option to disable notify --- crates/ra_lsp_server/src/config.rs | 3 + crates/ra_lsp_server/src/main_loop.rs | 174 +++++++++++++++++++++++----------- crates/ra_lsp_server/src/req.rs | 9 +- crates/ra_lsp_server/src/world.rs | 5 +- 4 files changed, 129 insertions(+), 62 deletions(-) (limited to 'crates/ra_lsp_server/src') diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs index 5c5ae3e18..cf53e7c4c 100644 --- a/crates/ra_lsp_server/src/config.rs +++ b/crates/ra_lsp_server/src/config.rs @@ -15,6 +15,8 @@ pub struct ServerConfig { pub publish_decorations: bool, pub exclude_globs: Vec, + #[serde(deserialize_with = "nullable_bool_false")] + pub use_client_watching: bool, pub lru_capacity: Option, @@ -31,6 +33,7 @@ impl Default for ServerConfig { ServerConfig { publish_decorations: false, exclude_globs: Vec::new(), + use_client_watching: false, lru_capacity: None, with_sysroot: true, feature_flags: FxHashMap::default(), diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 80f0216e8..25fa51b8a 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -9,8 +9,9 @@ use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestI use lsp_types::{ClientCapabilities, NumberOrString}; use ra_ide_api::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId}; use ra_prof::profile; -use ra_vfs::VfsTask; +use ra_vfs::{VfsTask, Watch}; use relative_path::RelativePathBuf; +use rustc_hash::FxHashSet; use serde::{de::DeserializeOwned, Serialize}; use threadpool::ThreadPool; @@ -55,72 +56,96 @@ pub fn main_loop( ) -> Result<()> { log::info!("server_config: {:#?}", config); - // FIXME: support dynamic workspace loading. - let workspaces = { - let mut loaded_workspaces = Vec::new(); - for ws_root in &ws_roots { - let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot( - ws_root.as_path(), - config.with_sysroot, - ); - match workspace { - Ok(workspace) => loaded_workspaces.push(workspace), - Err(e) => { - log::error!("loading workspace failed: {}", e); + let mut loop_state = LoopState::default(); + let mut world_state = { + // FIXME: support dynamic workspace loading. + let workspaces = { + let mut loaded_workspaces = Vec::new(); + for ws_root in &ws_roots { + let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot( + ws_root.as_path(), + config.with_sysroot, + ); + match workspace { + Ok(workspace) => loaded_workspaces.push(workspace), + Err(e) => { + log::error!("loading workspace failed: {}", e); + + show_message( + req::MessageType::Error, + format!("rust-analyzer failed to load workspace: {}", e), + &connection.sender, + ); + } + } + } + loaded_workspaces + }; + let globs = config + .exclude_globs + .iter() + .map(|glob| ra_vfs_glob::Glob::new(glob)) + .collect::, _>>()?; + + if config.use_client_watching { + let registration_options = req::DidChangeWatchedFilesRegistrationOptions { + watchers: workspaces + .iter() + .flat_map(|ws| ws.to_roots()) + .filter(|root| root.is_member()) + .map(|root| format!("{}/**/*.rs", root.path().display())) + .map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None }) + .collect(), + }; + let registration = req::Registration { + id: "file-watcher".to_string(), + method: "workspace/didChangeWatchedFiles".to_string(), + register_options: Some(serde_json::to_value(registration_options).unwrap()), + }; + let params = req::RegistrationParams { registrations: vec![registration] }; + let request = + request_new::(loop_state.next_request_id(), params); + connection.sender.send(request.into()).unwrap(); + } + + let feature_flags = { + let mut ff = FeatureFlags::default(); + for (flag, value) in config.feature_flags { + if let Err(_) = ff.set(flag.as_str(), value) { + log::error!("unknown feature flag: {:?}", flag); show_message( req::MessageType::Error, - format!("rust-analyzer failed to load workspace: {}", e), + format!("unknown feature flag: {:?}", flag), &connection.sender, ); } } - } - loaded_workspaces - }; - - let globs = config - .exclude_globs - .iter() - .map(|glob| ra_vfs_glob::Glob::new(glob)) - .collect::, _>>()?; - - let feature_flags = { - let mut ff = FeatureFlags::default(); - for (flag, value) in config.feature_flags { - if let Err(_) = ff.set(flag.as_str(), value) { - log::error!("unknown feature flag: {:?}", flag); - show_message( - req::MessageType::Error, - format!("unknown feature flag: {:?}", flag), - &connection.sender, - ); - } - } - ff + ff + }; + log::info!("feature_flags: {:#?}", feature_flags); + + WorldState::new( + ws_roots, + workspaces, + config.lru_capacity, + &globs, + Watch(!config.use_client_watching), + Options { + publish_decorations: config.publish_decorations, + supports_location_link: client_caps + .text_document + .and_then(|it| it.definition) + .and_then(|it| it.link_support) + .unwrap_or(false), + }, + feature_flags, + ) }; - log::info!("feature_flags: {:#?}", feature_flags); - - let mut world_state = WorldState::new( - ws_roots, - workspaces, - config.lru_capacity, - &globs, - Options { - publish_decorations: config.publish_decorations, - supports_location_link: client_caps - .text_document - .and_then(|it| it.definition) - .and_then(|it| it.link_support) - .unwrap_or(false), - }, - feature_flags, - ); let pool = ThreadPool::new(THREADPOOL_SIZE); let (task_sender, task_receiver) = unbounded::(); let (libdata_sender, libdata_receiver) = unbounded::(); - let mut loop_state = LoopState::default(); log::info!("server initialized, serving requests"); { @@ -227,6 +252,8 @@ impl fmt::Debug for Event { #[derive(Debug, Default)] struct LoopState { + next_request_id: u64, + pending_responses: FxHashSet, pending_requests: PendingRequests, subscriptions: Subscriptions, // We try not to index more than MAX_IN_FLIGHT_LIBS libraries at the same @@ -236,6 +263,16 @@ struct LoopState { workspace_loaded: bool, } +impl LoopState { + fn next_request_id(&mut self) -> RequestId { + self.next_request_id += 1; + let res: RequestId = self.next_request_id.into(); + let inserted = self.pending_responses.insert(res.clone()); + assert!(inserted); + res + } +} + fn loop_turn( pool: &ThreadPool, task_sender: &Sender, @@ -290,7 +327,12 @@ fn loop_turn( )?; state_changed = true; } - Message::Response(resp) => log::error!("unexpected response: {:?}", resp), + Message::Response(resp) => { + let removed = loop_state.pending_responses.remove(&resp.id); + if !removed { + log::error!("unexpected response: {:?}", resp) + } + } }, }; @@ -479,6 +521,18 @@ fn on_notification( } Err(not) => not, }; + let not = match notification_cast::(not) { + Ok(params) => { + let mut vfs = state.vfs.write(); + for change in params.changes { + let uri = change.uri; + let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?; + vfs.notify_changed(path) + } + return Ok(()); + } + Err(not) => not, + }; log::error!("unhandled notification: {:?}", not); Ok(()) } @@ -682,3 +736,11 @@ where { Notification::new(N::METHOD.to_string(), params) } + +fn request_new(id: RequestId, params: R::Params) -> Request +where + R: lsp_types::request::Request, + R::Params: Serialize, +{ + Request::new(id, R::METHOD.to_string(), params) +} diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 1b23f0c3d..0540f166e 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs @@ -5,10 +5,11 @@ use serde::{Deserialize, Serialize}; pub use lsp_types::{ notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens, CodeLensParams, CompletionParams, CompletionResponse, DidChangeConfigurationParams, - DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse, Hover, - InitializeResult, MessageType, PublishDiagnosticsParams, ReferenceParams, ShowMessageParams, - SignatureHelp, TextDocumentEdit, TextDocumentPositionParams, TextEdit, WorkspaceEdit, - WorkspaceSymbolParams, + DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions, + DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse, + FileSystemWatcher, Hover, InitializeResult, MessageType, PublishDiagnosticsParams, + ReferenceParams, Registration, RegistrationParams, ShowMessageParams, SignatureHelp, + TextDocumentEdit, TextDocumentPositionParams, TextEdit, WorkspaceEdit, WorkspaceSymbolParams, }; pub enum AnalyzerStatus {} diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index e1c5c3343..086ecd587 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -12,7 +12,7 @@ use ra_ide_api::{ SourceRootId, }; use ra_project_model::ProjectWorkspace; -use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask}; +use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; use relative_path::RelativePathBuf; @@ -60,6 +60,7 @@ impl WorldState { workspaces: Vec, lru_capacity: Option, exclude_globs: &[Glob], + watch: Watch, options: Options, feature_flags: FeatureFlags, ) -> WorldState { @@ -85,7 +86,7 @@ impl WorldState { } let (task_sender, task_receiver) = unbounded(); let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); - let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender); + let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); let roots_to_scan = vfs_roots.len(); for r in vfs_roots { let vfs_root_path = vfs.root2path(r); -- cgit v1.2.3