diff options
-rw-r--r-- | crates/rust-analyzer/src/bin/main.rs | 84 | ||||
-rw-r--r-- | crates/rust-analyzer/src/caps.rs | 12 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 2 |
3 files changed, 47 insertions, 51 deletions
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 6c883dd58..2b842d393 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -158,7 +158,24 @@ fn run_server() -> Result<()> { | |||
158 | let initialize_params = | 158 | let initialize_params = |
159 | from_json::<lsp_types::InitializeParams>("InitializeParams", initialize_params)?; | 159 | from_json::<lsp_types::InitializeParams>("InitializeParams", initialize_params)?; |
160 | 160 | ||
161 | let server_capabilities = rust_analyzer::server_capabilities(&initialize_params.capabilities); | 161 | let root_path = match initialize_params |
162 | .root_uri | ||
163 | .and_then(|it| it.to_file_path().ok()) | ||
164 | .and_then(|it| AbsPathBuf::try_from(it).ok()) | ||
165 | { | ||
166 | Some(it) => it, | ||
167 | None => { | ||
168 | let cwd = env::current_dir()?; | ||
169 | AbsPathBuf::assert(cwd) | ||
170 | } | ||
171 | }; | ||
172 | |||
173 | let mut config = Config::new(root_path, initialize_params.capabilities); | ||
174 | if let Some(json) = initialize_params.initialization_options { | ||
175 | config.update(json); | ||
176 | } | ||
177 | |||
178 | let server_capabilities = rust_analyzer::server_capabilities(&config); | ||
162 | 179 | ||
163 | let initialize_result = lsp_types::InitializeResult { | 180 | let initialize_result = lsp_types::InitializeResult { |
164 | capabilities: server_capabilities, | 181 | capabilities: server_capabilities, |
@@ -166,11 +183,7 @@ fn run_server() -> Result<()> { | |||
166 | name: String::from("rust-analyzer"), | 183 | name: String::from("rust-analyzer"), |
167 | version: Some(String::from(env!("REV"))), | 184 | version: Some(String::from(env!("REV"))), |
168 | }), | 185 | }), |
169 | offset_encoding: if supports_utf8(&initialize_params.capabilities) { | 186 | offset_encoding: if supports_utf8(&config.caps) { Some("utf-8".to_string()) } else { None }, |
170 | Some("utf-8".to_string()) | ||
171 | } else { | ||
172 | None | ||
173 | }, | ||
174 | }; | 187 | }; |
175 | 188 | ||
176 | let initialize_result = serde_json::to_value(initialize_result).unwrap(); | 189 | let initialize_result = serde_json::to_value(initialize_result).unwrap(); |
@@ -181,47 +194,26 @@ fn run_server() -> Result<()> { | |||
181 | log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); | 194 | log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); |
182 | } | 195 | } |
183 | 196 | ||
184 | let config = { | 197 | if config.linked_projects().is_empty() && config.detached_files().is_empty() { |
185 | let root_path = match initialize_params | 198 | let workspace_roots = initialize_params |
186 | .root_uri | 199 | .workspace_folders |
187 | .and_then(|it| it.to_file_path().ok()) | 200 | .map(|workspaces| { |
188 | .and_then(|it| AbsPathBuf::try_from(it).ok()) | 201 | workspaces |
189 | { | 202 | .into_iter() |
190 | Some(it) => it, | 203 | .filter_map(|it| it.uri.to_file_path().ok()) |
191 | None => { | 204 | .filter_map(|it| AbsPathBuf::try_from(it).ok()) |
192 | let cwd = env::current_dir()?; | 205 | .collect::<Vec<_>>() |
193 | AbsPathBuf::assert(cwd) | 206 | }) |
194 | } | 207 | .filter(|workspaces| !workspaces.is_empty()) |
195 | }; | 208 | .unwrap_or_else(|| vec![config.root_path.clone()]); |
196 | 209 | ||
197 | let mut config = Config::new(root_path, initialize_params.capabilities); | 210 | let discovered = ProjectManifest::discover_all(&workspace_roots); |
198 | if let Some(json) = initialize_params.initialization_options { | 211 | log::info!("discovered projects: {:?}", discovered); |
199 | config.update(json); | 212 | if discovered.is_empty() { |
200 | } | 213 | log::error!("failed to find any projects in {:?}", workspace_roots); |
201 | |||
202 | if config.linked_projects().is_empty() && config.detached_files().is_empty() { | ||
203 | let workspace_roots = initialize_params | ||
204 | .workspace_folders | ||
205 | .map(|workspaces| { | ||
206 | workspaces | ||
207 | .into_iter() | ||
208 | .filter_map(|it| it.uri.to_file_path().ok()) | ||
209 | .filter_map(|it| AbsPathBuf::try_from(it).ok()) | ||
210 | .collect::<Vec<_>>() | ||
211 | }) | ||
212 | .filter(|workspaces| !workspaces.is_empty()) | ||
213 | .unwrap_or_else(|| vec![config.root_path.clone()]); | ||
214 | |||
215 | let discovered = ProjectManifest::discover_all(&workspace_roots); | ||
216 | log::info!("discovered projects: {:?}", discovered); | ||
217 | if discovered.is_empty() { | ||
218 | log::error!("failed to find any projects in {:?}", workspace_roots); | ||
219 | } | ||
220 | config.discovered_projects = Some(discovered); | ||
221 | } | 214 | } |
222 | 215 | config.discovered_projects = Some(discovered); | |
223 | config | 216 | } |
224 | }; | ||
225 | 217 | ||
226 | rust_analyzer::main_loop(config, connection)?; | 218 | rust_analyzer::main_loop(config, connection)?; |
227 | 219 | ||
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 702efd8f8..fe5255240 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs | |||
@@ -13,9 +13,10 @@ use lsp_types::{ | |||
13 | }; | 13 | }; |
14 | use serde_json::json; | 14 | use serde_json::json; |
15 | 15 | ||
16 | use crate::config::{Config, RustfmtConfig}; | ||
16 | use crate::semantic_tokens; | 17 | use crate::semantic_tokens; |
17 | 18 | ||
18 | pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabilities { | 19 | pub fn server_capabilities(config: &Config) -> ServerCapabilities { |
19 | ServerCapabilities { | 20 | ServerCapabilities { |
20 | text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { | 21 | text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { |
21 | open_close: Some(true), | 22 | open_close: Some(true), |
@@ -26,7 +27,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti | |||
26 | })), | 27 | })), |
27 | hover_provider: Some(HoverProviderCapability::Simple(true)), | 28 | hover_provider: Some(HoverProviderCapability::Simple(true)), |
28 | completion_provider: Some(CompletionOptions { | 29 | completion_provider: Some(CompletionOptions { |
29 | resolve_provider: completions_resolve_provider(client_caps), | 30 | resolve_provider: completions_resolve_provider(&config.caps), |
30 | trigger_characters: Some(vec![":".to_string(), ".".to_string(), "'".to_string()]), | 31 | trigger_characters: Some(vec![":".to_string(), ".".to_string(), "'".to_string()]), |
31 | all_commit_characters: None, | 32 | all_commit_characters: None, |
32 | completion_item: None, | 33 | completion_item: None, |
@@ -45,10 +46,13 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti | |||
45 | document_highlight_provider: Some(OneOf::Left(true)), | 46 | document_highlight_provider: Some(OneOf::Left(true)), |
46 | document_symbol_provider: Some(OneOf::Left(true)), | 47 | document_symbol_provider: Some(OneOf::Left(true)), |
47 | workspace_symbol_provider: Some(OneOf::Left(true)), | 48 | workspace_symbol_provider: Some(OneOf::Left(true)), |
48 | code_action_provider: Some(code_action_capabilities(client_caps)), | 49 | code_action_provider: Some(code_action_capabilities(&config.caps)), |
49 | code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), | 50 | code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), |
50 | document_formatting_provider: Some(OneOf::Left(true)), | 51 | document_formatting_provider: Some(OneOf::Left(true)), |
51 | document_range_formatting_provider: Some(OneOf::Left(true)), | 52 | document_range_formatting_provider: match config.rustfmt() { |
53 | RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => Some(OneOf::Left(true)), | ||
54 | _ => Some(OneOf::Left(false)), | ||
55 | }, | ||
52 | document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions { | 56 | document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions { |
53 | first_trigger_character: "=".to_string(), | 57 | first_trigger_character: "=".to_string(), |
54 | more_trigger_character: Some(vec![".".to_string(), ">".to_string(), "{".to_string()]), | 58 | more_trigger_character: Some(vec![".".to_string(), ">".to_string(), "{".to_string()]), |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 7620a2fe1..b6a1124a5 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -238,7 +238,7 @@ impl Default for ConfigData { | |||
238 | 238 | ||
239 | #[derive(Debug, Clone)] | 239 | #[derive(Debug, Clone)] |
240 | pub struct Config { | 240 | pub struct Config { |
241 | caps: lsp_types::ClientCapabilities, | 241 | pub caps: lsp_types::ClientCapabilities, |
242 | data: ConfigData, | 242 | data: ConfigData, |
243 | detached_files: Vec<AbsPathBuf>, | 243 | detached_files: Vec<AbsPathBuf>, |
244 | pub discovered_projects: Option<Vec<ProjectManifest>>, | 244 | pub discovered_projects: Option<Vec<ProjectManifest>>, |