]> git.lizzy.rs Git - rust.git/blobdiff - crates/rust-analyzer/src/main_loop/handlers.rs
Merge branch 'master' into compute-lazy-assits
[rust.git] / crates / rust-analyzer / src / main_loop / handlers.rs
index c2a5bf4d6b8f7a9cc38fad22afe194eee664f46c..a3361d6dc5e9d3f7f655830a4fa9751a67886058 100644 (file)
@@ -701,37 +701,27 @@ pub fn handle_formatting(
     }]))
 }
 
-pub fn handle_code_action(
-    snap: GlobalStateSnapshot,
-    params: lsp_types::CodeActionParams,
-) -> Result<Option<Vec<lsp_ext::CodeAction>>> {
-    let _p = profile("handle_code_action");
-    // We intentionally don't support command-based actions, as those either
-    // requires custom client-code anyway, or requires server-initiated edits.
-    // Server initiated edits break causality, so we avoid those as well.
-    if !snap.config.client_caps.code_action_literals {
-        return Ok(None);
-    }
-
+fn handle_fixes(
+    snap: &GlobalStateSnapshot,
+    params: &lsp_types::CodeActionParams,
+    res: &mut Vec<lsp_ext::CodeAction>,
+) -> Result<()> {
     let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
     let line_index = snap.analysis().file_line_index(file_id)?;
     let range = from_proto::text_range(&line_index, params.range);
-    let frange = FileRange { file_id, range };
-
     let diagnostics = snap.analysis().diagnostics(file_id)?;
-    let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
 
     let fixes_from_diagnostics = diagnostics
         .into_iter()
         .filter_map(|d| Some((d.range, d.fix?)))
         .filter(|(diag_range, _fix)| diag_range.intersect(range).is_some())
         .map(|(_range, fix)| fix);
-
     for fix in fixes_from_diagnostics {
         let title = fix.label;
         let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?;
         let action = lsp_ext::CodeAction {
             title,
+            id: None,
             group: None,
             kind: Some(lsp_types::code_action_kind::QUICKFIX.into()),
             edit: Some(edit),
@@ -747,13 +737,63 @@ pub fn handle_code_action(
         }
         res.push(fix.action.clone());
     }
+    Ok(())
+}
+
+pub fn handle_code_action(
+    snap: GlobalStateSnapshot,
+    params: lsp_types::CodeActionParams,
+) -> Result<Option<Vec<lsp_ext::CodeAction>>> {
+    let _p = profile("handle_code_action");
+    // We intentionally don't support command-based actions, as those either
+    // requires custom client-code anyway, or requires server-initiated edits.
+    // Server initiated edits break causality, so we avoid those as well.
+    if !snap.config.client_caps.code_action_literals {
+        return Ok(None);
+    }
+
+    let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
+    let line_index = snap.analysis().file_line_index(file_id)?;
+    let range = from_proto::text_range(&line_index, params.range);
+    let frange = FileRange { file_id, range };
+    let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
 
-    for assist in snap.analysis().assists(&snap.config.assist, frange)?.into_iter() {
-        res.push(to_proto::code_action(&snap, assist)?.into());
+    handle_fixes(&snap, &params, &mut res)?;
+
+    if snap.config.client_caps.resolve_code_action {
+        for (index, assist) in
+            snap.analysis().unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate()
+        {
+            res.push(to_proto::unresolved_code_action(&snap, assist, index)?);
+        }
+    } else {
+        for assist in snap.analysis().resolved_assists(&snap.config.assist, frange)?.into_iter() {
+            res.push(to_proto::resolved_code_action(&snap, assist)?);
+        }
     }
+
     Ok(Some(res))
 }
 
+pub fn handle_resolve_code_action(
+    snap: GlobalStateSnapshot,
+    params: lsp_ext::ResolveCodeActionParams,
+) -> Result<Option<lsp_ext::SnippetWorkspaceEdit>> {
+    let _p = profile("handle_resolve_code_action");
+    let file_id = from_proto::file_id(&snap, &params.code_action_params.text_document.uri)?;
+    let line_index = snap.analysis().file_line_index(file_id)?;
+    let range = from_proto::text_range(&line_index, params.code_action_params.range);
+    let frange = FileRange { file_id, range };
+
+    let assists = snap.analysis().resolved_assists(&snap.config.assist, frange)?;
+    let id_components = params.id.split(":").collect::<Vec<&str>>();
+    let index = id_components.last().unwrap().parse::<usize>().unwrap();
+    let id_string = id_components.first().unwrap();
+    let assist = &assists[index];
+    assert!(assist.assist.id.0 == *id_string);
+    Ok(to_proto::resolved_code_action(&snap, assist.clone())?.edit)
+}
+
 pub fn handle_code_lens(
     snap: GlobalStateSnapshot,
     params: lsp_types::CodeLensParams,