aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/rust-analyzer/src/handlers.rs38
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs2
-rw-r--r--crates/rust-analyzer/src/to_proto.rs4
-rw-r--r--docs/dev/lsp-extensions.md3
4 files changed, 29 insertions, 18 deletions
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 0fd03bbaa..f6e40f872 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1058,41 +1058,44 @@ pub(crate) fn handle_code_action_resolve(
1058 .only 1058 .only
1059 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); 1059 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
1060 1060
1061 let assist_kind: AssistKind = match params.kind.parse() { 1061 let (assist_index, assist_resolve) = match parse_action_id(&params.id) {
1062 Ok(kind) => kind, 1062 Ok(parsed_data) => parsed_data,
1063 Err(e) => { 1063 Err(e) => {
1064 return Err(LspError::new( 1064 return Err(LspError::new(
1065 ErrorCode::InvalidParams as i32, 1065 ErrorCode::InvalidParams as i32,
1066 format!("For the assist to resolve, failed to parse the kind: {}", e), 1066 format!("Failed to parse action id string '{}': {}", params.id, e),
1067 ) 1067 )
1068 .into()) 1068 .into())
1069 } 1069 }
1070 }; 1070 };
1071 1071
1072 let expected_assist_id = assist_resolve.assist_id.clone();
1073 let expected_kind = assist_resolve.assist_kind;
1074
1072 let assists = snap.analysis.assists_with_fixes( 1075 let assists = snap.analysis.assists_with_fixes(
1073 &assists_config, 1076 &assists_config,
1074 &snap.config.diagnostics(), 1077 &snap.config.diagnostics(),
1075 AssistResolveStrategy::Single(SingleResolve { assist_id: params.id.clone(), assist_kind }), 1078 AssistResolveStrategy::Single(assist_resolve),
1076 frange, 1079 frange,
1077 )?; 1080 )?;
1078 1081
1079 let assist = match assists.get(params.index) { 1082 let assist = match assists.get(assist_index) {
1080 Some(assist) => assist, 1083 Some(assist) => assist,
1081 None => return Err(LspError::new( 1084 None => return Err(LspError::new(
1082 ErrorCode::InvalidParams as i32, 1085 ErrorCode::InvalidParams as i32,
1083 format!( 1086 format!(
1084 "Failed to find the assist for index {} provided by the resolve request. Expected assist id: {:?}", 1087 "Failed to find the assist for index {} provided by the resolve request. Resolve request assist id: {}",
1085 params.index, params.id, 1088 assist_index, params.id,
1086 ), 1089 ),
1087 ) 1090 )
1088 .into()) 1091 .into())
1089 }; 1092 };
1090 if assist.id.0 != params.id || assist.id.1 != assist_kind { 1093 if assist.id.0 != expected_assist_id || assist.id.1 != expected_kind {
1091 return Err(LspError::new( 1094 return Err(LspError::new(
1092 ErrorCode::InvalidParams as i32, 1095 ErrorCode::InvalidParams as i32,
1093 format!( 1096 format!(
1094 "Failed to find exactly the same assist at index {} for the resolve parameters given. Expected id and kind: {}, {:?}, actual id: {:?}.", 1097 "Mismatching assist at index {} for the resolve parameters given. Resolve request assist id: {}, actual id: {:?}.",
1095 params.index, params.id, assist_kind, assist.id 1098 assist_index, params.id, assist.id
1096 ), 1099 ),
1097 ) 1100 )
1098 .into()); 1101 .into());
@@ -1102,6 +1105,21 @@ pub(crate) fn handle_code_action_resolve(
1102 Ok(code_action) 1105 Ok(code_action)
1103} 1106}
1104 1107
1108fn parse_action_id(action_id: &str) -> Result<(usize, SingleResolve), String> {
1109 let id_parts = action_id.split(':').collect_vec();
1110 match id_parts.as_slice() {
1111 &[assist_id_string, assist_kind_string, index_string] => {
1112 let assist_kind: AssistKind = assist_kind_string.parse()?;
1113 let index: usize = match index_string.parse() {
1114 Ok(index) => index,
1115 Err(e) => return Err(format!("Incorrect index string: {}", e)),
1116 };
1117 Ok((index, SingleResolve { assist_id: assist_id_string.to_string(), assist_kind }))
1118 }
1119 _ => Err("Action id contains incorrect number of segments".to_string()),
1120 }
1121}
1122
1105pub(crate) fn handle_code_lens( 1123pub(crate) fn handle_code_lens(
1106 snap: GlobalStateSnapshot, 1124 snap: GlobalStateSnapshot,
1107 params: lsp_types::CodeLensParams, 1125 params: lsp_types::CodeLensParams,
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 292aedc9c..b8835a534 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -303,8 +303,6 @@ pub struct CodeAction {
303pub struct CodeActionData { 303pub struct CodeActionData {
304 pub code_action_params: lsp_types::CodeActionParams, 304 pub code_action_params: lsp_types::CodeActionParams,
305 pub id: String, 305 pub id: String,
306 pub kind: String,
307 pub index: usize,
308} 306}
309 307
310#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] 308#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 62e16680b..1d27aa7b3 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -897,10 +897,8 @@ pub(crate) fn code_action(
897 (Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?), 897 (Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?),
898 (None, Some((index, code_action_params))) => { 898 (None, Some((index, code_action_params))) => {
899 res.data = Some(lsp_ext::CodeActionData { 899 res.data = Some(lsp_ext::CodeActionData {
900 id: assist.id.0.to_string(), 900 id: format!("{}:{}:{}", assist.id.0, assist.id.1.name(), index),
901 code_action_params, 901 code_action_params,
902 kind: assist.id.1.name().to_string(),
903 index,
904 }); 902 });
905 } 903 }
906 (None, None) => { 904 (None, None) => {
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index e2ea695f2..f0f981802 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -81,7 +81,6 @@ If this capability is set, `CodeAction` returned from the server contain an addi
81interface CodeAction { 81interface CodeAction {
82 title: string; 82 title: string;
83 group?: string; 83 group?: string;
84 data?: string;
85 ... 84 ...
86} 85}
87``` 86```
@@ -102,8 +101,6 @@ The set of actions `[ { title: "foo" }, { group: "frobnicate", title: "bar" }, {
102 101
103Alternatively, selecting `frobnicate` could present a user with an additional menu to choose between `bar` and `baz`. 102Alternatively, selecting `frobnicate` could present a user with an additional menu to choose between `bar` and `baz`.
104 103
105`data` field contains optional json data for deferred resolve of the action data that's slow to compute in the original request.
106
107### Example 104### Example
108 105
109```rust 106```rust