aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/rust-analyzer/src/config.rs9
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap1
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap1
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs1
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs10
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs54
-rw-r--r--crates/rust-analyzer/src/to_proto.rs10
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
107impl Default for Config { 108impl 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")]
138pub struct SourceChange {
139 pub label: String,
140 pub workspace_edit: SnippetWorkspaceEdit,
141 pub cursor_position: Option<lsp_types::TextDocumentPositionParams>,
142}
143
144pub enum InlayHints {} 136pub enum InlayHints {}
145 137
146impl Request for InlayHints { 138impl Request for InlayHints {
@@ -196,6 +188,8 @@ impl Request for CodeActionRequest {
196pub struct CodeAction { 188pub 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};
20use ra_ide::{ 20use 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};
24use ra_prof::profile; 24use ra_prof::profile;
@@ -720,6 +720,7 @@ pub fn handle_code_action(
720 let file_id = from_proto::file_id(&world, &params.text_document.uri)?; 720 let file_id = from_proto::file_id(&world, &params.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
481pub(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
490pub(crate) fn snippet_workspace_edit( 481pub(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>{
606pub(crate) fn code_action(world: &WorldSnapshot, assist: Assist) -> Result<lsp_ext::CodeAction> { 597pub(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,