diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 91c5708fd5..f1798b491b 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1167,13 +1167,13 @@ impl Project { pub fn apply_code_action( &self, - buffer: ModelHandle, + buffer_handle: ModelHandle, mut action: CodeAction, cx: &mut ModelContext, ) -> Task, Vec<(Range, clock::Local)>>>> { if self.is_local() { - let buffer = buffer.read(cx); + let buffer = buffer_handle.read(cx); let lang_name = if let Some(lang) = buffer.language() { lang.name().to_string() } else { @@ -1196,21 +1196,41 @@ impl Project { .and_then(|d| d.get_mut("range")) { *range = serde_json::to_value(&lsp::Range::new(position, position)).unwrap(); - action = CodeAction { - position: action.position, - lsp_action: lang_server - .request::(action.lsp_action) - .await?, - } + action.lsp_action = lang_server + .request::(action.lsp_action) + .await?; + } else { + let actions = buffer_handle + .update(&mut cx, |buffer, cx| { + buffer.code_actions(action.position.clone(), cx) + }) + .await?; + action.lsp_action = actions + .into_iter() + .find(|a| a.lsp_action.title == action.lsp_action.title) + .ok_or_else(|| anyhow!("code action is outdated"))? + .lsp_action; } let mut operations = Vec::new(); - match action.lsp_action.edit.and_then(|e| e.document_changes) { - Some(lsp::DocumentChanges::Edits(edits)) => { - operations.extend(edits.into_iter().map(lsp::DocumentChangeOperation::Edit)) + if let Some(edit) = action.lsp_action.edit { + if let Some(document_changes) = edit.document_changes { + match document_changes { + lsp::DocumentChanges::Edits(edits) => operations + .extend(edits.into_iter().map(lsp::DocumentChangeOperation::Edit)), + lsp::DocumentChanges::Operations(ops) => operations = ops, + } + } else if let Some(changes) = edit.changes { + operations.extend(changes.into_iter().map(|(uri, edits)| { + lsp::DocumentChangeOperation::Edit(lsp::TextDocumentEdit { + text_document: lsp::OptionalVersionedTextDocumentIdentifier { + uri, + version: None, + }, + edits: edits.into_iter().map(lsp::OneOf::Left).collect(), + }) + })); } - Some(lsp::DocumentChanges::Operations(ops)) => operations = ops, - None => {} } let mut edited_buffers = HashMap::default();