Skip to content

Commit 5162334

Browse files
committed
Fix backend autosave and LSP notification errors
1 parent 75ca040 commit 5162334

5 files changed

Lines changed: 106 additions & 65 deletions

File tree

anycode-backend/src/acp_fs.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,6 @@ async fn handle_write(
121121
}
122122

123123
let lang = code.lang.clone();
124-
let saved_content = code.get_content();
125-
126124
// Serialize edits for frontend notification
127125
let edits_json = json!({
128126
"file": abs_path,
@@ -141,8 +139,12 @@ async fn handle_write(
141139
if !lsp_changes.is_empty() {
142140
let mut lsp = lsp_manager.lock().await;
143141
if let Some(lsp) = lsp.get(&lang).await {
144-
lsp.did_change_multi(&abs_path, lsp_changes).await;
145-
lsp.did_save(&abs_path, Some(&saved_content));
142+
if let Err(e) = lsp.did_change_multi(&abs_path, lsp_changes).await {
143+
error!("ACP write: failed to notify LSP didChange for {}: {}", abs_path, e);
144+
}
145+
if let Err(e) = lsp.did_save(&abs_path) {
146+
error!("ACP write: failed to notify LSP didSave for {}: {}", abs_path, e);
147+
}
146148
}
147149
}
148150

anycode-backend/src/handlers/io_handler.rs

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ pub async fn handle_file_open(
142142

143143
let mut lsp_manager = state.lsp_manager.lock().await;
144144
if let Some(lsp) = lsp_manager.get(&code.lang).await {
145-
lsp.did_open(&code.lang, &abs_path, &content);
145+
if let Err(e) = lsp.did_open(&code.lang, &abs_path, &content) {
146+
error!("Failed to notify LSP didOpen for {}: {:?}", abs_path, e);
147+
}
146148
}
147149
}
148150

@@ -254,7 +256,9 @@ pub async fn handle_file_close(
254256
{
255257
let mut lsp_manager = state.lsp_manager.lock().await;
256258
if let Some(lsp) = lsp_manager.get(&lang).await {
257-
lsp.did_close(&abs_path);
259+
if let Err(e) = lsp.did_close(&abs_path) {
260+
error!("Failed to notify LSP didClose for {}: {:?}", abs_path, e);
261+
}
258262
}
259263
}
260264

@@ -315,37 +319,58 @@ pub async fn handle_file_change(
315319
}
316320
};
317321

318-
let mut f2c = state.file2code.lock().await;
319-
let code = match get_or_create_code(&mut f2c, &abs_path, &state.config) {
320-
Ok(c) => c,
321-
Err(e) => {
322-
tracing::error!("Failed to get code: {:?}", e);
323-
return;
324-
}
325-
};
326-
327-
let mut lsp_manager = state.lsp_manager.lock().await;
328322
let edits = change.edits.clone();
323+
let (lsp_changes, lang, did_autosave) = {
324+
let mut f2c = state.file2code.lock().await;
325+
let code = match get_or_create_code(&mut f2c, &abs_path, &state.config) {
326+
Ok(c) => c,
327+
Err(e) => {
328+
tracing::error!("Failed to get code: {:?}", e);
329+
return;
330+
}
331+
};
329332

330-
let mut apply_tx = true;
333+
let mut apply_tx = true;
331334

332-
if let Some(true) = change.is_undo {
333-
let _undo = code.undo_change();
334-
apply_tx = false;
335-
}
335+
if let Some(true) = change.is_undo {
336+
let _undo = code.undo_change();
337+
apply_tx = false;
338+
}
336339

337-
if let Some(true) = change.is_redo {
338-
let _redo = code.redo_change();
339-
apply_tx = false;
340-
}
340+
if let Some(true) = change.is_redo {
341+
let _redo = code.redo_change();
342+
apply_tx = false;
343+
}
341344

342-
// Apply all edits to code and collect LSP changes
343-
let lsp_changes = apply_edits_to_code(code, &edits, apply_tx);
345+
// Apply all edits to code and collect LSP changes
346+
let lsp_changes = apply_edits_to_code(code, &edits, apply_tx);
347+
let lang = code.lang.clone();
348+
let did_autosave = match code.save_file() {
349+
Ok(()) => true,
350+
Err(e) => {
351+
error!("Autosave failed for {}: {:?}", abs_path, e);
352+
false
353+
}
354+
};
355+
356+
(lsp_changes, lang, did_autosave)
357+
};
344358

345-
// Send all changes to LSP in a single notification
346-
if !lsp_changes.is_empty() {
347-
if let Some(lsp) = lsp_manager.get(&code.lang).await {
348-
lsp.did_change_multi(&abs_path, lsp_changes).await;
359+
// Send all changes to LSP in a single notification, then notify save after autosave.
360+
if !lsp_changes.is_empty() || did_autosave {
361+
let mut lsp_manager = state.lsp_manager.lock().await;
362+
if let Some(lsp) = lsp_manager.get(&lang).await {
363+
if !lsp_changes.is_empty() {
364+
if let Err(e) = lsp.did_change_multi(&abs_path, lsp_changes).await {
365+
error!("Failed to notify LSP didChange for {}: {:?}", abs_path, e);
366+
}
367+
}
368+
369+
if did_autosave {
370+
if let Err(e) = lsp.did_save(&abs_path) {
371+
error!("Failed to notify LSP didSave for {}: {:?}", abs_path, e);
372+
}
373+
}
349374
}
350375
}
351376

@@ -385,7 +410,9 @@ pub async fn handle_file_save(
385410

386411
let mut lsp_manager = state.lsp_manager.lock().await;
387412
if let Some(lsp) = lsp_manager.get(&code.lang).await {
388-
lsp.did_save(&abs_path, Some(&code.text.to_string()));
413+
if let Err(e) = lsp.did_save(&abs_path) {
414+
error!("Failed to notify LSP didSave for {}: {:?}", abs_path, e);
415+
}
389416
}
390417

391418
ack.send(&json!({ "success": true, "file": abs_path })).ok();

anycode-backend/src/handlers/watch_handler.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::sync::Arc;
66
use std::time::Duration;
77
use tokio::sync::{Mutex, watch};
88
use tokio_util::sync::CancellationToken;
9-
use tracing::info;
9+
use tracing::{error, info};
1010

1111
use crate::app_state::SocketData;
1212
use crate::code::Code;
@@ -353,8 +353,12 @@ async fn handle_file_modification(
353353
if !lsp_changes.is_empty() {
354354
let mut lsp = lsp_manager.lock().await;
355355
if let Some(lsp) = lsp.get(&lang).await {
356-
lsp.did_change_multi(path_str, lsp_changes).await;
357-
lsp.did_save(path_str, Some(&new_text));
356+
if let Err(e) = lsp.did_change_multi(path_str, lsp_changes).await {
357+
error!("Failed to notify LSP didChange for {}: {:?}", path_str, e);
358+
}
359+
if let Err(e) = lsp.did_save(path_str) {
360+
error!("Failed to notify LSP didSave for {}: {:?}", path_str, e);
361+
}
358362
}
359363
}
360364

anycode-backend/src/lsp.rs

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use anyhow::Result;
12
use serde::{Deserialize, Serialize};
23
use serde_json::Value;
34
use std::collections::{HashMap, HashSet};
@@ -215,11 +216,11 @@ impl Lsp {
215216
}
216217
}
217218

218-
pub async fn init(&mut self, dir: &str) {
219+
pub async fn init(&mut self, dir: &str) -> Result<()> {
219220
let id = 0;
220221
let (tx, rx) = mpsc::channel::<String>(1);
221222
self.add_pending(id, tx).await;
222-
let message = lsp_messages::initialize(dir, self.lsp_name.as_deref());
223+
let message = lsp_messages::initialize(dir, self.lsp_name.as_deref())?;
223224
self.send_async(message);
224225
self.wait(5, rx).await;
225226
self.remove_pending(id).await;
@@ -231,7 +232,8 @@ impl Lsp {
231232
self.did_change_configuration(settings);
232233
}
233234

234-
self.ready.store(true, Ordering::SeqCst)
235+
self.ready.store(true, Ordering::SeqCst);
236+
Ok(())
235237
}
236238

237239
pub fn send_notification<N>(&self, params: N::Params)
@@ -308,41 +310,41 @@ impl Lsp {
308310
self.send_notification::<DidChangeConfiguration>(params);
309311
}
310312

311-
pub fn did_open(&mut self, lang: &str, path: &str, text: &str) {
313+
pub fn did_open(&mut self, lang: &str, path: &str, text: &str) -> Result<()> {
312314
self.opened.insert(path.to_string());
313-
315+
let uri = path_to_uri(path)?;
314316
let params = DidOpenTextDocumentParams {
315317
text_document: TextDocumentItem {
316-
uri: path_to_uri(path).unwrap(),
318+
uri,
317319
language_id: lang.to_string(),
318320
version: 0,
319321
text: text.to_string(),
320322
},
321323
};
322324
self.send_notification::<DidOpenTextDocument>(params);
325+
Ok(())
323326
}
324327

325-
pub fn did_close(&mut self, path: &str) {
328+
pub fn did_close(&mut self, path: &str) -> Result<()> {
326329
if !self.opened.remove(path) {
327-
return;
330+
return Ok(());
328331
}
332+
let uri = path_to_uri(path)?;
329333
let params = DidCloseTextDocumentParams {
330-
text_document: TextDocumentIdentifier {
331-
uri: path_to_uri(path).unwrap(),
332-
},
334+
text_document: TextDocumentIdentifier { uri },
333335
};
334336
self.send_notification::<DidCloseTextDocument>(params);
337+
Ok(())
335338
}
336339

337-
pub fn did_save(&mut self, path: &str, text: Option<&str>) {
340+
pub fn did_save(&mut self, path: &str) -> Result<()> {
341+
let uri = path_to_uri(path)?;
338342
let params = DidSaveTextDocumentParams {
339-
text_document: TextDocumentIdentifier {
340-
uri: path_to_uri(path).unwrap(),
341-
},
343+
text_document: TextDocumentIdentifier { uri },
342344
text: None,
343-
// text: text.map(|s| s.to_string()),
344345
};
345346
self.send_notification::<DidSaveTextDocument>(params);
347+
Ok(())
346348
}
347349

348350
fn get_next_version(&mut self, path: &str) -> usize {
@@ -366,7 +368,7 @@ impl Lsp {
366368
end_column: usize,
367369
path: &str,
368370
text: &str,
369-
) {
371+
) -> Result<()> {
370372
self.did_change_multi(
371373
path,
372374
vec![TextDocumentContentChangeEvent {
@@ -378,23 +380,25 @@ impl Lsp {
378380
text: text.to_string(),
379381
}],
380382
)
381-
.await;
383+
.await
382384
}
383385

384386
pub async fn did_change_multi(
385387
&mut self,
386388
path: &str,
387389
content_changes: Vec<TextDocumentContentChangeEvent>,
388-
) {
390+
) -> Result<()> {
391+
let uri = path_to_uri(path)?;
389392
let params = DidChangeTextDocumentParams {
390393
text_document: VersionedTextDocumentIdentifier {
391-
uri: path_to_uri(path).unwrap(),
394+
uri,
392395
version: self.get_next_version(path) as i32,
393396
},
394397
content_changes,
395398
};
396399

397400
self.send_notification::<DidChangeTextDocument>(params);
401+
Ok(())
398402
}
399403

400404
pub async fn completion(
@@ -536,17 +540,16 @@ mod tests {
536540
None,
537541
)?;
538542

539-
let dir = std::env::current_dir()
540-
.unwrap()
543+
let dir = std::env::current_dir()?
541544
.to_string_lossy()
542545
.into_owned();
543546

544-
lsp.init(&dir).await;
547+
lsp.init(&dir).await?;
545548

546549
let content = r#"for i in range(10000): print(i)"#;
547550
let file_path = "fast.py";
548551

549-
lsp.did_open(lang, file_path, content);
552+
lsp.did_open(lang, file_path, content)?;
550553

551554
// Test completion on 'range'
552555
let completions = lsp.completion(file_path, 0, 12).await?;
@@ -665,8 +668,8 @@ pub mod lsp_messages {
665668
}
666669
}
667670

668-
pub fn initialize(dir: &str, lsp_name: Option<&str>) -> String {
669-
let uri: Uri = path_to_uri(dir).unwrap();
671+
pub fn initialize(dir: &str, lsp_name: Option<&str>) -> Result<String> {
672+
let uri: Uri = path_to_uri(dir)?;
670673

671674
let path = std::path::Path::new(dir);
672675
let folder_name = path
@@ -743,7 +746,7 @@ pub mod lsp_messages {
743746
"params": params
744747
});
745748

746-
to_string(&request).unwrap()
749+
Ok(to_string(&request)?)
747750
}
748751
}
749752

@@ -804,7 +807,10 @@ impl LspManager {
804807
.to_string_lossy()
805808
.into_owned();
806809

807-
lsp.init(&dir).await;
810+
if let Err(e) = lsp.init(&dir).await {
811+
error!("error initializing lsp process {}: {}", &lsp_cmd, e);
812+
return;
813+
}
808814

809815
self.lang2lsp.insert(lang, lsp);
810816
}

anycode-backend/src/main.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use socketioxide::{
99
};
1010
use tower::ServiceBuilder;
1111
use tower_http::cors::CorsLayer;
12-
use tracing::info;
12+
use tracing::{error, info};
1313

1414
mod acp;
1515
mod acp_fs;
@@ -151,7 +151,9 @@ async fn on_disconnect(socket: SocketRef, state: State<AppState>) {
151151

152152
for (file_path, lang) in &files_to_close {
153153
if let Some(lsp) = lsp_manager.get(lang).await {
154-
lsp.did_close(file_path);
154+
if let Err(e) = lsp.did_close(file_path) {
155+
error!("Failed to notify LSP didClose for {}: {:?}", file_path, e);
156+
}
155157
// f2c.remove(file_path);
156158
}
157159
}

0 commit comments

Comments
 (0)