}]))
}
-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, ¶ms.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),
}
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, ¶ms.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, ¶ms, &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, ¶ms.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,