diff options
Diffstat (limited to 'crates/ra_lsp_server/src')
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 76 |
1 files changed, 48 insertions, 28 deletions
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 282f6e8fc..65e8bc856 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -2,20 +2,21 @@ | |||
2 | //! The majority of requests are fulfilled by calling into the `ra_ide` crate. | 2 | //! The majority of requests are fulfilled by calling into the `ra_ide` crate. |
3 | 3 | ||
4 | use std::{ | 4 | use std::{ |
5 | collections::hash_map::Entry, | ||
5 | fmt::Write as _, | 6 | fmt::Write as _, |
6 | io::Write as _, | 7 | io::Write as _, |
7 | process::{self, Stdio}, | 8 | process::{self, Stdio}, |
8 | }; | 9 | }; |
9 | 10 | ||
10 | use either::Either; | ||
11 | use lsp_server::ErrorCode; | 11 | use lsp_server::ErrorCode; |
12 | use lsp_types::{ | 12 | use lsp_types::{ |
13 | CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, | 13 | CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, |
14 | CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, | 14 | CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, |
15 | CodeAction, CodeActionResponse, CodeLens, Command, CompletionItem, Diagnostic, | 15 | CodeAction, CodeActionOrCommand, CodeActionResponse, CodeLens, Command, CompletionItem, |
16 | DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams, | 16 | Diagnostic, DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, |
17 | Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, | 17 | FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, |
18 | Range, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit, | 18 | PrepareRenameResponse, Range, RenameParams, SymbolInformation, TextDocumentIdentifier, |
19 | TextEdit, WorkspaceEdit, | ||
19 | }; | 20 | }; |
20 | use ra_ide::{ | 21 | use ra_ide::{ |
21 | AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, | 22 | AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, |
@@ -685,34 +686,53 @@ pub fn handle_code_action( | |||
685 | res.push(fix.action.clone()); | 686 | res.push(fix.action.clone()); |
686 | } | 687 | } |
687 | 688 | ||
689 | let mut groups = FxHashMap::default(); | ||
688 | for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() { | 690 | for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() { |
689 | let title = assist.label.clone(); | 691 | let arg = to_value(assist.source_change.try_conv_with(&world)?)?; |
692 | |||
693 | let (command, title, arg) = match assist.group_label { | ||
694 | None => ("rust-analyzer.applySourceChange", assist.label.clone(), arg), | ||
695 | |||
696 | // Group all assists with the same `group_label` into a single CodeAction. | ||
697 | Some(group_label) => { | ||
698 | match groups.entry(group_label.clone()) { | ||
699 | Entry::Occupied(entry) => { | ||
700 | let idx: usize = *entry.get(); | ||
701 | match &mut res[idx] { | ||
702 | CodeActionOrCommand::CodeAction(CodeAction { | ||
703 | command: Some(Command { arguments: Some(arguments), .. }), | ||
704 | .. | ||
705 | }) => match arguments.as_mut_slice() { | ||
706 | [serde_json::Value::Array(arguments)] => arguments.push(arg), | ||
707 | _ => panic!("invalid group"), | ||
708 | }, | ||
709 | _ => panic!("invalid group"), | ||
710 | } | ||
711 | continue; | ||
712 | } | ||
713 | Entry::Vacant(entry) => { | ||
714 | entry.insert(res.len()); | ||
715 | } | ||
716 | } | ||
717 | ("rust-analyzer.selectAndApplySourceChange", group_label, to_value(vec![arg])?) | ||
718 | } | ||
719 | }; | ||
690 | 720 | ||
691 | let command = match assist.change_data { | 721 | let command = Command { |
692 | Either::Left(change) => Command { | 722 | title: assist.label.clone(), |
693 | title, | 723 | command: command.to_string(), |
694 | command: "rust-analyzer.applySourceChange".to_string(), | 724 | arguments: Some(vec![arg]), |
695 | arguments: Some(vec![to_value(change.try_conv_with(&world)?)?]), | 725 | }; |
696 | }, | 726 | |
697 | Either::Right(changes) => Command { | 727 | let kind = match assist.id { |
698 | title, | 728 | AssistId("introduce_variable") => Some("refactor.extract.variable".to_string()), |
699 | command: "rust-analyzer.selectAndApplySourceChange".to_string(), | 729 | AssistId("add_custom_impl") => Some("refactor.rewrite.add_custom_impl".to_string()), |
700 | arguments: Some(vec![to_value( | 730 | _ => None, |
701 | changes | ||
702 | .into_iter() | ||
703 | .map(|change| change.try_conv_with(&world)) | ||
704 | .collect::<Result<Vec<_>>>()?, | ||
705 | )?]), | ||
706 | }, | ||
707 | }; | 731 | }; |
708 | 732 | ||
709 | let action = CodeAction { | 733 | let action = CodeAction { |
710 | title: command.title.clone(), | 734 | title, |
711 | kind: match assist.id { | 735 | kind, |
712 | AssistId("introduce_variable") => Some("refactor.extract.variable".to_string()), | ||
713 | AssistId("add_custom_impl") => Some("refactor.rewrite.add_custom_impl".to_string()), | ||
714 | _ => None, | ||
715 | }, | ||
716 | diagnostics: None, | 736 | diagnostics: None, |
717 | edit: None, | 737 | edit: None, |
718 | command: Some(command), | 738 | command: Some(command), |