diff options
Diffstat (limited to 'crates/ra_lsp_server/src')
-rw-r--r-- | crates/ra_lsp_server/src/config.rs | 13 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main.rs | 19 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 48 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/world.rs | 15 |
5 files changed, 70 insertions, 30 deletions
diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs index 71838b89c..5c5ae3e18 100644 --- a/crates/ra_lsp_server/src/config.rs +++ b/crates/ra_lsp_server/src/config.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use rustc_hash::FxHashMap; | ||
2 | |||
1 | use serde::{Deserialize, Deserializer}; | 3 | use serde::{Deserialize, Deserializer}; |
2 | 4 | ||
3 | /// Client provided initialization options | 5 | /// Client provided initialization options |
@@ -12,12 +14,6 @@ pub struct ServerConfig { | |||
12 | #[serde(deserialize_with = "nullable_bool_false")] | 14 | #[serde(deserialize_with = "nullable_bool_false")] |
13 | pub publish_decorations: bool, | 15 | pub publish_decorations: bool, |
14 | 16 | ||
15 | /// Whether or not the workspace loaded notification should be sent | ||
16 | /// | ||
17 | /// Defaults to `true` | ||
18 | #[serde(deserialize_with = "nullable_bool_true")] | ||
19 | pub show_workspace_loaded: bool, | ||
20 | |||
21 | pub exclude_globs: Vec<String>, | 17 | pub exclude_globs: Vec<String>, |
22 | 18 | ||
23 | pub lru_capacity: Option<usize>, | 19 | pub lru_capacity: Option<usize>, |
@@ -25,16 +21,19 @@ pub struct ServerConfig { | |||
25 | /// For internal usage to make integrated tests faster. | 21 | /// For internal usage to make integrated tests faster. |
26 | #[serde(deserialize_with = "nullable_bool_true")] | 22 | #[serde(deserialize_with = "nullable_bool_true")] |
27 | pub with_sysroot: bool, | 23 | pub with_sysroot: bool, |
24 | |||
25 | /// Fine grained feature flags to disable specific features. | ||
26 | pub feature_flags: FxHashMap<String, bool>, | ||
28 | } | 27 | } |
29 | 28 | ||
30 | impl Default for ServerConfig { | 29 | impl Default for ServerConfig { |
31 | fn default() -> ServerConfig { | 30 | fn default() -> ServerConfig { |
32 | ServerConfig { | 31 | ServerConfig { |
33 | publish_decorations: false, | 32 | publish_decorations: false, |
34 | show_workspace_loaded: true, | ||
35 | exclude_globs: Vec::new(), | 33 | exclude_globs: Vec::new(), |
36 | lru_capacity: None, | 34 | lru_capacity: None, |
37 | with_sysroot: true, | 35 | with_sysroot: true, |
36 | feature_flags: FxHashMap::default(), | ||
38 | } | 37 | } |
39 | } | 38 | } |
40 | } | 39 | } |
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index ca388e472..2c5d7c72d 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs | |||
@@ -11,5 +11,8 @@ mod world; | |||
11 | 11 | ||
12 | pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>; | 12 | pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>; |
13 | pub use crate::{ | 13 | pub use crate::{ |
14 | caps::server_capabilities, config::ServerConfig, main_loop::main_loop, main_loop::LspError, | 14 | caps::server_capabilities, |
15 | config::ServerConfig, | ||
16 | main_loop::LspError, | ||
17 | main_loop::{main_loop, show_message}, | ||
15 | }; | 18 | }; |
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index 36d4898bd..ae1392cb5 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs | |||
@@ -1,8 +1,7 @@ | |||
1 | use flexi_logger::{Duplicate, Logger}; | 1 | use flexi_logger::{Duplicate, Logger}; |
2 | use gen_lsp_server::{run_server, stdio_transport}; | 2 | use gen_lsp_server::{run_server, stdio_transport}; |
3 | use serde::Deserialize; | ||
4 | 3 | ||
5 | use ra_lsp_server::{Result, ServerConfig}; | 4 | use ra_lsp_server::{show_message, Result, ServerConfig}; |
6 | use ra_prof; | 5 | use ra_prof; |
7 | 6 | ||
8 | fn main() -> Result<()> { | 7 | fn main() -> Result<()> { |
@@ -46,15 +45,23 @@ fn main_inner() -> Result<()> { | |||
46 | .filter(|workspaces| !workspaces.is_empty()) | 45 | .filter(|workspaces| !workspaces.is_empty()) |
47 | .unwrap_or_else(|| vec![root]); | 46 | .unwrap_or_else(|| vec![root]); |
48 | 47 | ||
49 | let opts = params | 48 | let server_config: ServerConfig = params |
50 | .initialization_options | 49 | .initialization_options |
51 | .and_then(|v| { | 50 | .and_then(|v| { |
52 | ServerConfig::deserialize(v) | 51 | serde_json::from_value(v) |
53 | .map_err(|e| log::error!("failed to deserialize config: {}", e)) | 52 | .map_err(|e| { |
53 | log::error!("failed to deserialize config: {}", e); | ||
54 | show_message( | ||
55 | lsp_types::MessageType::Error, | ||
56 | format!("failed to deserialize config: {}", e), | ||
57 | s, | ||
58 | ); | ||
59 | }) | ||
54 | .ok() | 60 | .ok() |
55 | }) | 61 | }) |
56 | .unwrap_or_default(); | 62 | .unwrap_or_default(); |
57 | ra_lsp_server::main_loop(workspace_roots, params.capabilities, opts, r, s) | 63 | |
64 | ra_lsp_server::main_loop(workspace_roots, params.capabilities, server_config, r, s) | ||
58 | })?; | 65 | })?; |
59 | log::info!("shutting down IO..."); | 66 | log::info!("shutting down IO..."); |
60 | threads.join()?; | 67 | threads.join()?; |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index fcb782386..ce25ff162 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -9,7 +9,7 @@ use gen_lsp_server::{ | |||
9 | handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, | 9 | handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, |
10 | }; | 10 | }; |
11 | use lsp_types::{ClientCapabilities, NumberOrString}; | 11 | use lsp_types::{ClientCapabilities, NumberOrString}; |
12 | use ra_ide_api::{Canceled, FileId, LibraryData}; | 12 | use ra_ide_api::{Canceled, FeatureFlags, FileId, LibraryData}; |
13 | use ra_prof::profile; | 13 | use ra_prof::profile; |
14 | use ra_vfs::VfsTask; | 14 | use ra_vfs::VfsTask; |
15 | use serde::{de::DeserializeOwned, Serialize}; | 15 | use serde::{de::DeserializeOwned, Serialize}; |
@@ -56,7 +56,7 @@ pub fn main_loop( | |||
56 | msg_receiver: &Receiver<RawMessage>, | 56 | msg_receiver: &Receiver<RawMessage>, |
57 | msg_sender: &Sender<RawMessage>, | 57 | msg_sender: &Sender<RawMessage>, |
58 | ) -> Result<()> { | 58 | ) -> Result<()> { |
59 | log::debug!("server_config: {:?}", config); | 59 | log::info!("server_config: {:#?}", config); |
60 | // FIXME: support dynamic workspace loading. | 60 | // FIXME: support dynamic workspace loading. |
61 | let workspaces = { | 61 | let workspaces = { |
62 | let ws_worker = workspace_loader(config.with_sysroot); | 62 | let ws_worker = workspace_loader(config.with_sysroot); |
@@ -83,6 +83,21 @@ pub fn main_loop( | |||
83 | .iter() | 83 | .iter() |
84 | .map(|glob| ra_vfs_glob::Glob::new(glob)) | 84 | .map(|glob| ra_vfs_glob::Glob::new(glob)) |
85 | .collect::<std::result::Result<Vec<_>, _>>()?; | 85 | .collect::<std::result::Result<Vec<_>, _>>()?; |
86 | let feature_flags = { | ||
87 | let mut ff = FeatureFlags::default(); | ||
88 | for (flag, value) in config.feature_flags { | ||
89 | if let Err(_) = ff.set(flag.as_str(), value) { | ||
90 | log::error!("unknown feature flag: {:?}", flag); | ||
91 | show_message( | ||
92 | req::MessageType::Error, | ||
93 | format!("unknown feature flag: {:?}", flag), | ||
94 | msg_sender, | ||
95 | ); | ||
96 | } | ||
97 | } | ||
98 | ff | ||
99 | }; | ||
100 | log::info!("feature_flags: {:#?}", feature_flags); | ||
86 | let mut state = WorldState::new( | 101 | let mut state = WorldState::new( |
87 | ws_roots, | 102 | ws_roots, |
88 | workspaces, | 103 | workspaces, |
@@ -90,13 +105,13 @@ pub fn main_loop( | |||
90 | &globs, | 105 | &globs, |
91 | Options { | 106 | Options { |
92 | publish_decorations: config.publish_decorations, | 107 | publish_decorations: config.publish_decorations, |
93 | show_workspace_loaded: config.show_workspace_loaded, | ||
94 | supports_location_link: client_caps | 108 | supports_location_link: client_caps |
95 | .text_document | 109 | .text_document |
96 | .and_then(|it| it.definition) | 110 | .and_then(|it| it.definition) |
97 | .and_then(|it| it.link_support) | 111 | .and_then(|it| it.link_support) |
98 | .unwrap_or(false), | 112 | .unwrap_or(false), |
99 | }, | 113 | }, |
114 | feature_flags, | ||
100 | ); | 115 | ); |
101 | 116 | ||
102 | let pool = ThreadPool::new(THREADPOOL_SIZE); | 117 | let pool = ThreadPool::new(THREADPOOL_SIZE); |
@@ -276,7 +291,7 @@ fn main_loop_inner( | |||
276 | && in_flight_libraries == 0 | 291 | && in_flight_libraries == 0 |
277 | { | 292 | { |
278 | let n_packages: usize = state.workspaces.iter().map(|it| it.n_packages()).sum(); | 293 | let n_packages: usize = state.workspaces.iter().map(|it| it.n_packages()).sum(); |
279 | if state.options.show_workspace_loaded { | 294 | if state.feature_flags().get("notifications.workspace-loaded") { |
280 | let msg = format!("workspace loaded, {} rust packages", n_packages); | 295 | let msg = format!("workspace loaded, {} rust packages", n_packages); |
281 | show_message(req::MessageType::Info, msg, msg_sender); | 296 | show_message(req::MessageType::Info, msg, msg_sender); |
282 | } | 297 | } |
@@ -587,17 +602,20 @@ fn update_file_notifications_on_threadpool( | |||
587 | subscriptions: Vec<FileId>, | 602 | subscriptions: Vec<FileId>, |
588 | ) { | 603 | ) { |
589 | log::trace!("updating notifications for {:?}", subscriptions); | 604 | log::trace!("updating notifications for {:?}", subscriptions); |
605 | let publish_diagnostics = world.feature_flags().get("lsp.diagnostics"); | ||
590 | pool.execute(move || { | 606 | pool.execute(move || { |
591 | for file_id in subscriptions { | 607 | for file_id in subscriptions { |
592 | match handlers::publish_diagnostics(&world, file_id) { | 608 | if publish_diagnostics { |
593 | Err(e) => { | 609 | match handlers::publish_diagnostics(&world, file_id) { |
594 | if !is_canceled(&e) { | 610 | Err(e) => { |
595 | log::error!("failed to compute diagnostics: {:?}", e); | 611 | if !is_canceled(&e) { |
612 | log::error!("failed to compute diagnostics: {:?}", e); | ||
613 | } | ||
614 | } | ||
615 | Ok(params) => { | ||
616 | let not = RawNotification::new::<req::PublishDiagnostics>(¶ms); | ||
617 | sender.send(Task::Notify(not)).unwrap(); | ||
596 | } | 618 | } |
597 | } | ||
598 | Ok(params) => { | ||
599 | let not = RawNotification::new::<req::PublishDiagnostics>(¶ms); | ||
600 | sender.send(Task::Notify(not)).unwrap(); | ||
601 | } | 619 | } |
602 | } | 620 | } |
603 | if publish_decorations { | 621 | if publish_decorations { |
@@ -617,7 +635,11 @@ fn update_file_notifications_on_threadpool( | |||
617 | }); | 635 | }); |
618 | } | 636 | } |
619 | 637 | ||
620 | fn show_message(typ: req::MessageType, message: impl Into<String>, sender: &Sender<RawMessage>) { | 638 | pub fn show_message( |
639 | typ: req::MessageType, | ||
640 | message: impl Into<String>, | ||
641 | sender: &Sender<RawMessage>, | ||
642 | ) { | ||
621 | let message = message.into(); | 643 | let message = message.into(); |
622 | let params = req::ShowMessageParams { typ, message }; | 644 | let params = req::ShowMessageParams { typ, message }; |
623 | let not = RawNotification::new::<req::ShowMessage>(¶ms); | 645 | let not = RawNotification::new::<req::ShowMessage>(¶ms); |
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 10f96812f..6696dff71 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs | |||
@@ -7,7 +7,8 @@ use gen_lsp_server::ErrorCode; | |||
7 | use lsp_types::Url; | 7 | use lsp_types::Url; |
8 | use parking_lot::RwLock; | 8 | use parking_lot::RwLock; |
9 | use ra_ide_api::{ | 9 | use ra_ide_api::{ |
10 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, | 10 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData, |
11 | SourceRootId, | ||
11 | }; | 12 | }; |
12 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; | 13 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; |
13 | use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; | 14 | use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; |
@@ -22,7 +23,6 @@ use crate::{ | |||
22 | #[derive(Debug, Clone)] | 23 | #[derive(Debug, Clone)] |
23 | pub struct Options { | 24 | pub struct Options { |
24 | pub publish_decorations: bool, | 25 | pub publish_decorations: bool, |
25 | pub show_workspace_loaded: bool, | ||
26 | pub supports_location_link: bool, | 26 | pub supports_location_link: bool, |
27 | } | 27 | } |
28 | 28 | ||
@@ -58,6 +58,7 @@ impl WorldState { | |||
58 | lru_capacity: Option<usize>, | 58 | lru_capacity: Option<usize>, |
59 | exclude_globs: &[Glob], | 59 | exclude_globs: &[Glob], |
60 | options: Options, | 60 | options: Options, |
61 | feature_flags: FeatureFlags, | ||
61 | ) -> WorldState { | 62 | ) -> WorldState { |
62 | let mut change = AnalysisChange::new(); | 63 | let mut change = AnalysisChange::new(); |
63 | 64 | ||
@@ -99,7 +100,7 @@ impl WorldState { | |||
99 | } | 100 | } |
100 | change.set_crate_graph(crate_graph); | 101 | change.set_crate_graph(crate_graph); |
101 | 102 | ||
102 | let mut analysis_host = AnalysisHost::new(lru_capacity); | 103 | let mut analysis_host = AnalysisHost::new(lru_capacity, feature_flags); |
103 | analysis_host.apply_change(change); | 104 | analysis_host.apply_change(change); |
104 | WorldState { | 105 | WorldState { |
105 | options, | 106 | options, |
@@ -184,6 +185,10 @@ impl WorldState { | |||
184 | pub fn complete_request(&mut self, request: CompletedRequest) { | 185 | pub fn complete_request(&mut self, request: CompletedRequest) { |
185 | self.latest_requests.write().record(request) | 186 | self.latest_requests.write().record(request) |
186 | } | 187 | } |
188 | |||
189 | pub fn feature_flags(&self) -> &FeatureFlags { | ||
190 | self.analysis_host.feature_flags() | ||
191 | } | ||
187 | } | 192 | } |
188 | 193 | ||
189 | impl WorldSnapshot { | 194 | impl WorldSnapshot { |
@@ -246,4 +251,8 @@ impl WorldSnapshot { | |||
246 | let path = self.vfs.read().file2path(VfsFile(file_id.0)); | 251 | let path = self.vfs.read().file2path(VfsFile(file_id.0)); |
247 | self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path)) | 252 | self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path)) |
248 | } | 253 | } |
254 | |||
255 | pub fn feature_flags(&self) -> &FeatureFlags { | ||
256 | self.analysis.feature_flags() | ||
257 | } | ||
249 | } | 258 | } |