diff options
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r-- | crates/ra_lsp_server/src/caps.rs | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/config.rs | 14 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 2 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 35 |
4 files changed, 41 insertions, 12 deletions
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 30bcbd7a8..eea0965ed 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs | |||
@@ -38,7 +38,7 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
38 | document_range_formatting_provider: None, | 38 | document_range_formatting_provider: None, |
39 | document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions { | 39 | document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions { |
40 | first_trigger_character: "=".to_string(), | 40 | first_trigger_character: "=".to_string(), |
41 | more_trigger_character: Some(vec![".".to_string()]), | 41 | more_trigger_character: Some(vec![".".to_string(), ">".to_string()]), |
42 | }), | 42 | }), |
43 | selection_range_provider: Some(GenericCapability::default()), | 43 | selection_range_provider: Some(GenericCapability::default()), |
44 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), | 44 | folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), |
diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs index 579d4c692..9871a3b37 100644 --- a/crates/ra_lsp_server/src/config.rs +++ b/crates/ra_lsp_server/src/config.rs | |||
@@ -1,4 +1,11 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Config used by the language server. |
2 | //! | ||
3 | //! We currently get this config from `initialize` LSP request, which is not the | ||
4 | //! best way to do it, but was the simplest thing we could implement. | ||
5 | //! | ||
6 | //! Of particular interest is the `feature_flags` hash map: while other fields | ||
7 | //! configure the server itself, feature flags are passed into analysis, and | ||
8 | //! tweak things like automatic insertion of `()` in completions. | ||
2 | 9 | ||
3 | use rustc_hash::FxHashMap; | 10 | use rustc_hash::FxHashMap; |
4 | 11 | ||
@@ -72,10 +79,7 @@ mod test { | |||
72 | assert_eq!(default, serde_json::from_str(r#"{}"#).unwrap()); | 79 | assert_eq!(default, serde_json::from_str(r#"{}"#).unwrap()); |
73 | assert_eq!( | 80 | assert_eq!( |
74 | default, | 81 | default, |
75 | serde_json::from_str( | 82 | serde_json::from_str(r#"{"publishDecorations":null, "lruCapacity":null}"#).unwrap() |
76 | r#"{"publishDecorations":null, "showWorkspaceLoaded":null, "lruCapacity":null}"# | ||
77 | ) | ||
78 | .unwrap() | ||
79 | ); | 83 | ); |
80 | } | 84 | } |
81 | } | 85 | } |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 1a87706fe..379dab438 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -196,7 +196,7 @@ pub fn main_loop( | |||
196 | task_receiver.into_iter().for_each(|task| { | 196 | task_receiver.into_iter().for_each(|task| { |
197 | on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut world_state) | 197 | on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut world_state) |
198 | }); | 198 | }); |
199 | libdata_receiver.into_iter().for_each(|lib| drop(lib)); | 199 | libdata_receiver.into_iter().for_each(drop); |
200 | log::info!("...tasks have finished"); | 200 | log::info!("...tasks have finished"); |
201 | log::info!("joining threadpool..."); | 201 | log::info!("joining threadpool..."); |
202 | drop(pool); | 202 | drop(pool); |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index a29971d10..20f9aee13 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -27,6 +27,7 @@ use crate::{ | |||
27 | }; | 27 | }; |
28 | 28 | ||
29 | pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> { | 29 | pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> { |
30 | let _p = profile("handle_analyzer_status"); | ||
30 | let mut buf = world.status(); | 31 | let mut buf = world.status(); |
31 | writeln!(buf, "\n\nrequests:").unwrap(); | 32 | writeln!(buf, "\n\nrequests:").unwrap(); |
32 | let requests = world.latest_requests.read(); | 33 | let requests = world.latest_requests.read(); |
@@ -38,6 +39,7 @@ pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> { | |||
38 | } | 39 | } |
39 | 40 | ||
40 | pub fn handle_syntax_tree(world: WorldSnapshot, params: req::SyntaxTreeParams) -> Result<String> { | 41 | pub fn handle_syntax_tree(world: WorldSnapshot, params: req::SyntaxTreeParams) -> Result<String> { |
42 | let _p = profile("handle_syntax_tree"); | ||
41 | let id = params.text_document.try_conv_with(&world)?; | 43 | let id = params.text_document.try_conv_with(&world)?; |
42 | let line_index = world.analysis().file_line_index(id)?; | 44 | let line_index = world.analysis().file_line_index(id)?; |
43 | let text_range = params.range.map(|p| p.conv_with(&line_index)); | 45 | let text_range = params.range.map(|p| p.conv_with(&line_index)); |
@@ -132,6 +134,7 @@ pub fn handle_on_enter( | |||
132 | } | 134 | } |
133 | } | 135 | } |
134 | 136 | ||
137 | // Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`. | ||
135 | pub fn handle_on_type_formatting( | 138 | pub fn handle_on_type_formatting( |
136 | world: WorldSnapshot, | 139 | world: WorldSnapshot, |
137 | params: req::DocumentOnTypeFormattingParams, | 140 | params: req::DocumentOnTypeFormattingParams, |
@@ -144,12 +147,17 @@ pub fn handle_on_type_formatting( | |||
144 | // in `ra_ide_api`, the `on_type` invariant is that | 147 | // in `ra_ide_api`, the `on_type` invariant is that |
145 | // `text.char_at(position) == typed_char`. | 148 | // `text.char_at(position) == typed_char`. |
146 | position.offset = position.offset - TextUnit::of_char('.'); | 149 | position.offset = position.offset - TextUnit::of_char('.'); |
150 | let char_typed = params.ch.chars().next().unwrap_or('\0'); | ||
147 | 151 | ||
148 | let edit = match params.ch.as_str() { | 152 | // We have an assist that inserts ` ` after typing `->` in `fn foo() ->{`, |
149 | "=" => world.analysis().on_eq_typed(position), | 153 | // but it requires precise cursor positioning to work, and one can't |
150 | "." => world.analysis().on_dot_typed(position), | 154 | // position the cursor with on_type formatting. So, let's just toggle this |
151 | _ => return Ok(None), | 155 | // feature off here, hoping that we'll enable it one day, 😿. |
152 | }?; | 156 | if char_typed == '>' { |
157 | return Ok(None); | ||
158 | } | ||
159 | |||
160 | let edit = world.analysis().on_char_typed(position, char_typed)?; | ||
153 | let mut edit = match edit { | 161 | let mut edit = match edit { |
154 | Some(it) => it, | 162 | Some(it) => it, |
155 | None => return Ok(None), | 163 | None => return Ok(None), |
@@ -166,6 +174,7 @@ pub fn handle_document_symbol( | |||
166 | world: WorldSnapshot, | 174 | world: WorldSnapshot, |
167 | params: req::DocumentSymbolParams, | 175 | params: req::DocumentSymbolParams, |
168 | ) -> Result<Option<req::DocumentSymbolResponse>> { | 176 | ) -> Result<Option<req::DocumentSymbolResponse>> { |
177 | let _p = profile("handle_document_symbol"); | ||
169 | let file_id = params.text_document.try_conv_with(&world)?; | 178 | let file_id = params.text_document.try_conv_with(&world)?; |
170 | let line_index = world.analysis().file_line_index(file_id)?; | 179 | let line_index = world.analysis().file_line_index(file_id)?; |
171 | 180 | ||
@@ -204,6 +213,7 @@ pub fn handle_workspace_symbol( | |||
204 | world: WorldSnapshot, | 213 | world: WorldSnapshot, |
205 | params: req::WorkspaceSymbolParams, | 214 | params: req::WorkspaceSymbolParams, |
206 | ) -> Result<Option<Vec<SymbolInformation>>> { | 215 | ) -> Result<Option<Vec<SymbolInformation>>> { |
216 | let _p = profile("handle_workspace_symbol"); | ||
207 | let all_symbols = params.query.contains('#'); | 217 | let all_symbols = params.query.contains('#'); |
208 | let libs = params.query.contains('*'); | 218 | let libs = params.query.contains('*'); |
209 | let query = { | 219 | let query = { |
@@ -247,6 +257,7 @@ pub fn handle_goto_definition( | |||
247 | world: WorldSnapshot, | 257 | world: WorldSnapshot, |
248 | params: req::TextDocumentPositionParams, | 258 | params: req::TextDocumentPositionParams, |
249 | ) -> Result<Option<req::GotoDefinitionResponse>> { | 259 | ) -> Result<Option<req::GotoDefinitionResponse>> { |
260 | let _p = profile("handle_goto_definition"); | ||
250 | let position = params.try_conv_with(&world)?; | 261 | let position = params.try_conv_with(&world)?; |
251 | let nav_info = match world.analysis().goto_definition(position)? { | 262 | let nav_info = match world.analysis().goto_definition(position)? { |
252 | None => return Ok(None), | 263 | None => return Ok(None), |
@@ -260,6 +271,7 @@ pub fn handle_goto_implementation( | |||
260 | world: WorldSnapshot, | 271 | world: WorldSnapshot, |
261 | params: req::TextDocumentPositionParams, | 272 | params: req::TextDocumentPositionParams, |
262 | ) -> Result<Option<req::GotoImplementationResponse>> { | 273 | ) -> Result<Option<req::GotoImplementationResponse>> { |
274 | let _p = profile("handle_goto_implementation"); | ||
263 | let position = params.try_conv_with(&world)?; | 275 | let position = params.try_conv_with(&world)?; |
264 | let nav_info = match world.analysis().goto_implementation(position)? { | 276 | let nav_info = match world.analysis().goto_implementation(position)? { |
265 | None => return Ok(None), | 277 | None => return Ok(None), |
@@ -273,6 +285,7 @@ pub fn handle_goto_type_definition( | |||
273 | world: WorldSnapshot, | 285 | world: WorldSnapshot, |
274 | params: req::TextDocumentPositionParams, | 286 | params: req::TextDocumentPositionParams, |
275 | ) -> Result<Option<req::GotoTypeDefinitionResponse>> { | 287 | ) -> Result<Option<req::GotoTypeDefinitionResponse>> { |
288 | let _p = profile("handle_goto_type_definition"); | ||
276 | let position = params.try_conv_with(&world)?; | 289 | let position = params.try_conv_with(&world)?; |
277 | let nav_info = match world.analysis().goto_type_definition(position)? { | 290 | let nav_info = match world.analysis().goto_type_definition(position)? { |
278 | None => return Ok(None), | 291 | None => return Ok(None), |
@@ -286,6 +299,7 @@ pub fn handle_parent_module( | |||
286 | world: WorldSnapshot, | 299 | world: WorldSnapshot, |
287 | params: req::TextDocumentPositionParams, | 300 | params: req::TextDocumentPositionParams, |
288 | ) -> Result<Vec<Location>> { | 301 | ) -> Result<Vec<Location>> { |
302 | let _p = profile("handle_parent_module"); | ||
289 | let position = params.try_conv_with(&world)?; | 303 | let position = params.try_conv_with(&world)?; |
290 | world.analysis().parent_module(position)?.iter().try_conv_with_to_vec(&world) | 304 | world.analysis().parent_module(position)?.iter().try_conv_with_to_vec(&world) |
291 | } | 305 | } |
@@ -294,6 +308,7 @@ pub fn handle_runnables( | |||
294 | world: WorldSnapshot, | 308 | world: WorldSnapshot, |
295 | params: req::RunnablesParams, | 309 | params: req::RunnablesParams, |
296 | ) -> Result<Vec<req::Runnable>> { | 310 | ) -> Result<Vec<req::Runnable>> { |
311 | let _p = profile("handle_runnables"); | ||
297 | let file_id = params.text_document.try_conv_with(&world)?; | 312 | let file_id = params.text_document.try_conv_with(&world)?; |
298 | let line_index = world.analysis().file_line_index(file_id)?; | 313 | let line_index = world.analysis().file_line_index(file_id)?; |
299 | let offset = params.position.map(|it| it.conv_with(&line_index)); | 314 | let offset = params.position.map(|it| it.conv_with(&line_index)); |
@@ -335,6 +350,7 @@ pub fn handle_decorations( | |||
335 | world: WorldSnapshot, | 350 | world: WorldSnapshot, |
336 | params: TextDocumentIdentifier, | 351 | params: TextDocumentIdentifier, |
337 | ) -> Result<Vec<Decoration>> { | 352 | ) -> Result<Vec<Decoration>> { |
353 | let _p = profile("handle_decorations"); | ||
338 | let file_id = params.try_conv_with(&world)?; | 354 | let file_id = params.try_conv_with(&world)?; |
339 | highlight(&world, file_id) | 355 | highlight(&world, file_id) |
340 | } | 356 | } |
@@ -383,6 +399,7 @@ pub fn handle_folding_range( | |||
383 | world: WorldSnapshot, | 399 | world: WorldSnapshot, |
384 | params: FoldingRangeParams, | 400 | params: FoldingRangeParams, |
385 | ) -> Result<Option<Vec<FoldingRange>>> { | 401 | ) -> Result<Option<Vec<FoldingRange>>> { |
402 | let _p = profile("handle_folding_range"); | ||
386 | let file_id = params.text_document.try_conv_with(&world)?; | 403 | let file_id = params.text_document.try_conv_with(&world)?; |
387 | let folds = world.analysis().folding_ranges(file_id)?; | 404 | let folds = world.analysis().folding_ranges(file_id)?; |
388 | let text = world.analysis().file_text(file_id)?; | 405 | let text = world.analysis().file_text(file_id)?; |
@@ -400,6 +417,7 @@ pub fn handle_signature_help( | |||
400 | world: WorldSnapshot, | 417 | world: WorldSnapshot, |
401 | params: req::TextDocumentPositionParams, | 418 | params: req::TextDocumentPositionParams, |
402 | ) -> Result<Option<req::SignatureHelp>> { | 419 | ) -> Result<Option<req::SignatureHelp>> { |
420 | let _p = profile("handle_signature_help"); | ||
403 | let position = params.try_conv_with(&world)?; | 421 | let position = params.try_conv_with(&world)?; |
404 | if let Some(call_info) = world.analysis().call_info(position)? { | 422 | if let Some(call_info) = world.analysis().call_info(position)? { |
405 | let active_parameter = call_info.active_parameter.map(|it| it as i64); | 423 | let active_parameter = call_info.active_parameter.map(|it| it as i64); |
@@ -419,6 +437,7 @@ pub fn handle_hover( | |||
419 | world: WorldSnapshot, | 437 | world: WorldSnapshot, |
420 | params: req::TextDocumentPositionParams, | 438 | params: req::TextDocumentPositionParams, |
421 | ) -> Result<Option<Hover>> { | 439 | ) -> Result<Option<Hover>> { |
440 | let _p = profile("handle_hover"); | ||
422 | let position = params.try_conv_with(&world)?; | 441 | let position = params.try_conv_with(&world)?; |
423 | let info = match world.analysis().hover(position)? { | 442 | let info = match world.analysis().hover(position)? { |
424 | None => return Ok(None), | 443 | None => return Ok(None), |
@@ -517,6 +536,7 @@ pub fn handle_formatting( | |||
517 | world: WorldSnapshot, | 536 | world: WorldSnapshot, |
518 | params: DocumentFormattingParams, | 537 | params: DocumentFormattingParams, |
519 | ) -> Result<Option<Vec<TextEdit>>> { | 538 | ) -> Result<Option<Vec<TextEdit>>> { |
539 | let _p = profile("handle_formatting"); | ||
520 | let file_id = params.text_document.try_conv_with(&world)?; | 540 | let file_id = params.text_document.try_conv_with(&world)?; |
521 | let file = world.analysis().file_text(file_id)?; | 541 | let file = world.analysis().file_text(file_id)?; |
522 | 542 | ||
@@ -639,6 +659,7 @@ pub fn handle_code_lens( | |||
639 | world: WorldSnapshot, | 659 | world: WorldSnapshot, |
640 | params: req::CodeLensParams, | 660 | params: req::CodeLensParams, |
641 | ) -> Result<Option<Vec<CodeLens>>> { | 661 | ) -> Result<Option<Vec<CodeLens>>> { |
662 | let _p = profile("handle_code_lens"); | ||
642 | let file_id = params.text_document.try_conv_with(&world)?; | 663 | let file_id = params.text_document.try_conv_with(&world)?; |
643 | let line_index = world.analysis().file_line_index(file_id)?; | 664 | let line_index = world.analysis().file_line_index(file_id)?; |
644 | 665 | ||
@@ -699,6 +720,7 @@ enum CodeLensResolveData { | |||
699 | } | 720 | } |
700 | 721 | ||
701 | pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> { | 722 | pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> { |
723 | let _p = profile("handle_code_lens_resolve"); | ||
702 | let data = code_lens.data.unwrap(); | 724 | let data = code_lens.data.unwrap(); |
703 | let resolve = serde_json::from_value(data)?; | 725 | let resolve = serde_json::from_value(data)?; |
704 | match resolve { | 726 | match resolve { |
@@ -770,6 +792,7 @@ pub fn publish_diagnostics( | |||
770 | world: &WorldSnapshot, | 792 | world: &WorldSnapshot, |
771 | file_id: FileId, | 793 | file_id: FileId, |
772 | ) -> Result<req::PublishDiagnosticsParams> { | 794 | ) -> Result<req::PublishDiagnosticsParams> { |
795 | let _p = profile("publish_diagnostics"); | ||
773 | let uri = world.file_id_to_uri(file_id)?; | 796 | let uri = world.file_id_to_uri(file_id)?; |
774 | let line_index = world.analysis().file_line_index(file_id)?; | 797 | let line_index = world.analysis().file_line_index(file_id)?; |
775 | let diagnostics = world | 798 | let diagnostics = world |
@@ -792,6 +815,7 @@ pub fn publish_decorations( | |||
792 | world: &WorldSnapshot, | 815 | world: &WorldSnapshot, |
793 | file_id: FileId, | 816 | file_id: FileId, |
794 | ) -> Result<req::PublishDecorationsParams> { | 817 | ) -> Result<req::PublishDecorationsParams> { |
818 | let _p = profile("publish_decorations"); | ||
795 | let uri = world.file_id_to_uri(file_id)?; | 819 | let uri = world.file_id_to_uri(file_id)?; |
796 | Ok(req::PublishDecorationsParams { uri, decorations: highlight(&world, file_id)? }) | 820 | Ok(req::PublishDecorationsParams { uri, decorations: highlight(&world, file_id)? }) |
797 | } | 821 | } |
@@ -841,6 +865,7 @@ pub fn handle_inlay_hints( | |||
841 | world: WorldSnapshot, | 865 | world: WorldSnapshot, |
842 | params: InlayHintsParams, | 866 | params: InlayHintsParams, |
843 | ) -> Result<Vec<InlayHint>> { | 867 | ) -> Result<Vec<InlayHint>> { |
868 | let _p = profile("handle_inlay_hints"); | ||
844 | let file_id = params.text_document.try_conv_with(&world)?; | 869 | let file_id = params.text_document.try_conv_with(&world)?; |
845 | let analysis = world.analysis(); | 870 | let analysis = world.analysis(); |
846 | let line_index = analysis.file_line_index(file_id)?; | 871 | let line_index = analysis.file_line_index(file_id)?; |