diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-05-22 16:33:12 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-05-22 16:33:12 +0100 |
commit | 2a36a2a3cc016de61a5df3165037ed689f36c423 (patch) | |
tree | bc08c40bd490c35a76bfd6849b6c372f0ab8311a /crates | |
parent | 0fb71349156619e26a15ae21d7730eb9ce020446 (diff) | |
parent | 2075e77ee5784e72396c64c9ca059763508219ff (diff) |
Merge #4569
4569: CodeAction groups r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
7 files changed, 19 insertions, 67 deletions
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index d75c48597..0e4412ade 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -102,6 +102,7 @@ pub struct ClientCapsConfig { | |||
102 | pub hierarchical_symbols: bool, | 102 | pub hierarchical_symbols: bool, |
103 | pub code_action_literals: bool, | 103 | pub code_action_literals: bool, |
104 | pub work_done_progress: bool, | 104 | pub work_done_progress: bool, |
105 | pub code_action_group: bool, | ||
105 | } | 106 | } |
106 | 107 | ||
107 | impl Default for Config { | 108 | impl Default for Config { |
@@ -294,9 +295,13 @@ impl Config { | |||
294 | 295 | ||
295 | self.assist.allow_snippets(false); | 296 | self.assist.allow_snippets(false); |
296 | if let Some(experimental) = &caps.experimental { | 297 | if let Some(experimental) = &caps.experimental { |
297 | let enable = | 298 | let snippet_text_edit = |
298 | experimental.get("snippetTextEdit").and_then(|it| it.as_bool()) == Some(true); | 299 | experimental.get("snippetTextEdit").and_then(|it| it.as_bool()) == Some(true); |
299 | self.assist.allow_snippets(enable); | 300 | self.assist.allow_snippets(snippet_text_edit); |
301 | |||
302 | let code_action_group = | ||
303 | experimental.get("codeActionGroup").and_then(|it| it.as_bool()) == Some(true); | ||
304 | self.client_caps.code_action_group = code_action_group | ||
300 | } | 305 | } |
301 | } | 306 | } |
302 | } | 307 | } |
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap index 96466b5c9..c40cfdcdc 100644 --- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap +++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap | |||
@@ -65,6 +65,7 @@ expression: diag | |||
65 | fixes: [ | 65 | fixes: [ |
66 | CodeAction { | 66 | CodeAction { |
67 | title: "return the expression directly", | 67 | title: "return the expression directly", |
68 | group: None, | ||
68 | kind: Some( | 69 | kind: Some( |
69 | "quickfix", | 70 | "quickfix", |
70 | ), | 71 | ), |
diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap index 8f962277f..6dd3fcb2e 100644 --- a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap +++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap | |||
@@ -50,6 +50,7 @@ expression: diag | |||
50 | fixes: [ | 50 | fixes: [ |
51 | CodeAction { | 51 | CodeAction { |
52 | title: "consider prefixing with an underscore", | 52 | title: "consider prefixing with an underscore", |
53 | group: None, | ||
53 | kind: Some( | 54 | kind: Some( |
54 | "quickfix", | 55 | "quickfix", |
55 | ), | 56 | ), |
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index afea59525..a500d670a 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs | |||
@@ -145,6 +145,7 @@ fn map_rust_child_diagnostic( | |||
145 | } else { | 145 | } else { |
146 | MappedRustChildDiagnostic::SuggestedFix(lsp_ext::CodeAction { | 146 | MappedRustChildDiagnostic::SuggestedFix(lsp_ext::CodeAction { |
147 | title: rd.message.clone(), | 147 | title: rd.message.clone(), |
148 | group: None, | ||
148 | kind: Some("quickfix".to_string()), | 149 | kind: Some("quickfix".to_string()), |
149 | edit: Some(lsp_ext::SnippetWorkspaceEdit { | 150 | edit: Some(lsp_ext::SnippetWorkspaceEdit { |
150 | // FIXME: there's no good reason to use edit_map here.... | 151 | // FIXME: there's no good reason to use edit_map here.... |
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 0fd60caf4..c25d90a50 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs | |||
@@ -133,14 +133,6 @@ pub struct Runnable { | |||
133 | pub cwd: Option<PathBuf>, | 133 | pub cwd: Option<PathBuf>, |
134 | } | 134 | } |
135 | 135 | ||
136 | #[derive(Deserialize, Serialize, Debug)] | ||
137 | #[serde(rename_all = "camelCase")] | ||
138 | pub struct SourceChange { | ||
139 | pub label: String, | ||
140 | pub workspace_edit: SnippetWorkspaceEdit, | ||
141 | pub cursor_position: Option<lsp_types::TextDocumentPositionParams>, | ||
142 | } | ||
143 | |||
144 | pub enum InlayHints {} | 136 | pub enum InlayHints {} |
145 | 137 | ||
146 | impl Request for InlayHints { | 138 | impl Request for InlayHints { |
@@ -196,6 +188,8 @@ impl Request for CodeActionRequest { | |||
196 | pub struct CodeAction { | 188 | pub struct CodeAction { |
197 | pub title: String, | 189 | pub title: String, |
198 | #[serde(skip_serializing_if = "Option::is_none")] | 190 | #[serde(skip_serializing_if = "Option::is_none")] |
191 | pub group: Option<String>, | ||
192 | #[serde(skip_serializing_if = "Option::is_none")] | ||
199 | pub kind: Option<String>, | 193 | pub kind: Option<String>, |
200 | #[serde(skip_serializing_if = "Option::is_none")] | 194 | #[serde(skip_serializing_if = "Option::is_none")] |
201 | pub command: Option<lsp_types::Command>, | 195 | pub command: Option<lsp_types::Command>, |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index 25e660bd5..89144f743 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -18,7 +18,7 @@ use lsp_types::{ | |||
18 | SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, Url, WorkspaceEdit, | 18 | SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, Url, WorkspaceEdit, |
19 | }; | 19 | }; |
20 | use ra_ide::{ | 20 | use ra_ide::{ |
21 | Assist, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope, | 21 | FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope, |
22 | TextEdit, | 22 | TextEdit, |
23 | }; | 23 | }; |
24 | use ra_prof::profile; | 24 | use ra_prof::profile; |
@@ -720,6 +720,7 @@ pub fn handle_code_action( | |||
720 | let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?; | 720 | let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?; |
721 | let line_index = world.analysis().file_line_index(file_id)?; | 721 | let line_index = world.analysis().file_line_index(file_id)?; |
722 | let range = from_proto::text_range(&line_index, params.range); | 722 | let range = from_proto::text_range(&line_index, params.range); |
723 | let frange = FileRange { file_id, range }; | ||
723 | 724 | ||
724 | let diagnostics = world.analysis().diagnostics(file_id)?; | 725 | let diagnostics = world.analysis().diagnostics(file_id)?; |
725 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); | 726 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); |
@@ -733,7 +734,8 @@ pub fn handle_code_action( | |||
733 | for source_edit in fixes_from_diagnostics { | 734 | for source_edit in fixes_from_diagnostics { |
734 | let title = source_edit.label.clone(); | 735 | let title = source_edit.label.clone(); |
735 | let edit = to_proto::snippet_workspace_edit(&world, source_edit)?; | 736 | let edit = to_proto::snippet_workspace_edit(&world, source_edit)?; |
736 | let action = lsp_ext::CodeAction { title, kind: None, edit: Some(edit), command: None }; | 737 | let action = |
738 | lsp_ext::CodeAction { title, group: None, kind: None, edit: Some(edit), command: None }; | ||
737 | res.push(action); | 739 | res.push(action); |
738 | } | 740 | } |
739 | 741 | ||
@@ -745,53 +747,9 @@ pub fn handle_code_action( | |||
745 | res.push(fix.action.clone()); | 747 | res.push(fix.action.clone()); |
746 | } | 748 | } |
747 | 749 | ||
748 | let mut grouped_assists: FxHashMap<String, (usize, Vec<Assist>)> = FxHashMap::default(); | 750 | for assist in world.analysis().assists(&world.config.assist, frange)?.into_iter() { |
749 | for assist in | 751 | res.push(to_proto::code_action(&world, assist)?.into()); |
750 | world.analysis().assists(&world.config.assist, FileRange { file_id, range })?.into_iter() | ||
751 | { | ||
752 | match &assist.group_label { | ||
753 | Some(label) => grouped_assists | ||
754 | .entry(label.to_owned()) | ||
755 | .or_insert_with(|| { | ||
756 | let idx = res.len(); | ||
757 | let dummy = lsp_ext::CodeAction { | ||
758 | title: String::new(), | ||
759 | kind: None, | ||
760 | command: None, | ||
761 | edit: None, | ||
762 | }; | ||
763 | res.push(dummy); | ||
764 | (idx, Vec::new()) | ||
765 | }) | ||
766 | .1 | ||
767 | .push(assist), | ||
768 | None => { | ||
769 | res.push(to_proto::code_action(&world, assist)?.into()); | ||
770 | } | ||
771 | } | ||
772 | } | ||
773 | |||
774 | for (group_label, (idx, assists)) in grouped_assists { | ||
775 | if assists.len() == 1 { | ||
776 | res[idx] = to_proto::code_action(&world, assists.into_iter().next().unwrap())?.into(); | ||
777 | } else { | ||
778 | let title = group_label; | ||
779 | |||
780 | let mut arguments = Vec::with_capacity(assists.len()); | ||
781 | for assist in assists { | ||
782 | let source_change = to_proto::source_change(&world, assist.source_change)?; | ||
783 | arguments.push(to_value(source_change)?); | ||
784 | } | ||
785 | |||
786 | let command = Some(Command { | ||
787 | title: title.clone(), | ||
788 | command: "rust-analyzer.selectAndApplySourceChange".to_string(), | ||
789 | arguments: Some(vec![serde_json::Value::Array(arguments)]), | ||
790 | }); | ||
791 | res[idx] = lsp_ext::CodeAction { title, kind: None, edit: None, command }; | ||
792 | } | ||
793 | } | 752 | } |
794 | |||
795 | Ok(Some(res)) | 753 | Ok(Some(res)) |
796 | } | 754 | } |
797 | 755 | ||
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index f6f4bb134..461944ada 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -478,15 +478,6 @@ pub(crate) fn resource_op( | |||
478 | Ok(res) | 478 | Ok(res) |
479 | } | 479 | } |
480 | 480 | ||
481 | pub(crate) fn source_change( | ||
482 | world: &WorldSnapshot, | ||
483 | source_change: SourceChange, | ||
484 | ) -> Result<lsp_ext::SourceChange> { | ||
485 | let label = source_change.label.clone(); | ||
486 | let workspace_edit = self::snippet_workspace_edit(world, source_change)?; | ||
487 | Ok(lsp_ext::SourceChange { label, workspace_edit, cursor_position: None }) | ||
488 | } | ||
489 | |||
490 | pub(crate) fn snippet_workspace_edit( | 481 | pub(crate) fn snippet_workspace_edit( |
491 | world: &WorldSnapshot, | 482 | world: &WorldSnapshot, |
492 | source_change: SourceChange, | 483 | source_change: SourceChange, |
@@ -606,6 +597,7 @@ fn main() <fold>{ | |||
606 | pub(crate) fn code_action(world: &WorldSnapshot, assist: Assist) -> Result<lsp_ext::CodeAction> { | 597 | pub(crate) fn code_action(world: &WorldSnapshot, assist: Assist) -> Result<lsp_ext::CodeAction> { |
607 | let res = lsp_ext::CodeAction { | 598 | let res = lsp_ext::CodeAction { |
608 | title: assist.label, | 599 | title: assist.label, |
600 | group: if world.config.client_caps.code_action_group { assist.group_label } else { None }, | ||
609 | kind: Some(String::new()), | 601 | kind: Some(String::new()), |
610 | edit: Some(snippet_workspace_edit(world, assist.source_change)?), | 602 | edit: Some(snippet_workspace_edit(world, assist.source_change)?), |
611 | command: None, | 603 | command: None, |