aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs76
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
4use std::{ 4use 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
10use either::Either;
11use lsp_server::ErrorCode; 11use lsp_server::ErrorCode;
12use lsp_types::{ 12use 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};
20use ra_ide::{ 21use 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),