From 5df43937f183af57f0bab05b9ae2d134b2dc9179 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 15 Oct 2024 19:14:16 +0800 Subject: [PATCH] lsp: Add `source.fixAll` to LSP. (#221) --- autocorrect-lsp/src/lib.rs | 69 +++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/autocorrect-lsp/src/lib.rs b/autocorrect-lsp/src/lib.rs index fa6a3e7..a41d564 100644 --- a/autocorrect-lsp/src/lib.rs +++ b/autocorrect-lsp/src/lib.rs @@ -11,6 +11,7 @@ struct Backend { work_dir: RwLock, documents: RwLock>>, ignorer: RwLock>, + diagnostics: RwLock>>, } static DEFAULT_CONFIG_FILE: &str = ".autocorrectrc"; @@ -89,12 +90,18 @@ impl Backend { } async fn send_diagnostics(&self, document: &TextDocumentItem, diagnostics: Vec) { + if let Ok(mut map) = self.diagnostics.write() { + map.entry(document.uri.clone()) + .and_modify(|old_diagnostics| old_diagnostics.extend_from_slice(&diagnostics)) + .or_insert_with(|| diagnostics.clone()); + } self.client .publish_diagnostics(document.uri.clone(), diagnostics, None) .await; } async fn clear_diagnostics(&self, uri: &Url) { + self.diagnostics.write().unwrap().remove(uri); self.client .publish_diagnostics(uri.clone(), vec![], None) .await; @@ -175,7 +182,10 @@ impl LanguageServer for Backend { document_formatting_provider: Some(OneOf::Left(true)), code_action_provider: Some(CodeActionProviderCapability::Options( CodeActionOptions { - code_action_kinds: Some(vec![CodeActionKind::QUICKFIX]), + code_action_kinds: Some(vec![ + CodeActionKind::QUICKFIX, + CodeActionKind::SOURCE_FIX_ALL, + ]), ..Default::default() }, )), @@ -327,14 +337,48 @@ impl LanguageServer for Backend { return Ok(None); } - self.client - .log_message( - MessageType::INFO, - format!("code_action {}\n", text_document.uri), - ) - .await; - let mut response = CodeActionResponse::new(); + + let all_diagnostics = self + .diagnostics + .read() + .unwrap() + .get(&text_document.uri) + .cloned(); + + let all_changes = all_diagnostics.map(|diagnostics| { + let mut map = HashMap::new(); + map.insert( + text_document.uri.clone(), + diagnostics + .iter() + .map(|diagnostic| TextEdit { + range: diagnostic.range, + new_text: diagnostic.message.clone(), + }) + .collect(), + ); + map + }); + + // self.client + // .log_message( + // MessageType::LOG, + // format!("all changes: {:?}\n", all_changes), + // ) + // .await; + + let fix_all_action = CodeAction { + title: "AutoCorrect All".into(), + kind: Some(CodeActionKind::SOURCE_FIX_ALL), + diagnostics: None, + edit: Some(WorkspaceEdit { + changes: all_changes, + ..Default::default() + }), + ..Default::default() + }; + for diagnostic in context.diagnostics.iter() { let action = CodeAction { title: diagnostic.source.clone().unwrap_or("AutoCorrect".into()), @@ -352,15 +396,13 @@ impl LanguageServer for Backend { .into_iter() .collect(), ), - document_changes: None, - change_annotations: None, + ..Default::default() }), - command: None, is_preferred: Some(true), - disabled: None, - data: None, + ..Default::default() }; response.push(CodeActionOrCommand::CodeAction(action)); + response.push(CodeActionOrCommand::CodeAction(fix_all_action.clone())) } return Ok(Some(response)); } @@ -375,6 +417,7 @@ pub async fn start() { work_dir: RwLock::new(PathBuf::new()), documents: RwLock::new(HashMap::new()), ignorer: RwLock::new(None), + diagnostics: RwLock::new(HashMap::new()), }); Server::new(stdin, stdout, socket).serve(service).await;