diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index def553a..afd085c 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -374,76 +374,42 @@ impl LanguageServer for Backend { eprintln!("Loaded {} mist files", files.len()); - let mapping_c = mapping.clone(); - let documents_c = documents.clone(); - let ra_c = ra.clone(); + // Compute mod_decls before any transpile so the root file gets its + // child module declarations from the very first didOpen. + let package_mist = read_mist_package(root); + let src_root = root.join("src"); + let mod_decls = { + let docs = documents.lock().await; + compute_mod_decls(&docs, &src_root, &package_mist) + }; for file in &files { - if let Some(source) = documents_c.lock().await.get(file).map(|r| r.to_string()) - { - let transpiled = match transpile_mist(file, &source, "") { - Ok(t) => t, - Err(e) => { - eprintln!("transpile error for {:?}: {e}", file); - continue; - } - }; - - if let Some(rust_uri) = clean_lsp_url(&transpiled.rust_path) { - let _ = ra_c - .lock() - .await - .did_open(rust_uri, &transpiled.rust_content) - .await; - mapping_c - .lock() - .await - .insert(transpiled.rust_path, transpiled.mapping); - } - } - } - - // After loading all documents, rebuild the module tree so rust-analyzer - // sees cross-module declarations. - // We need a reference to self here; capture what we need via the Arcs. - { - let ra = ra.clone(); - let mapping = mapping.clone(); - let documents = documents.clone(); - - // Read config and compute mod_decls for the root file - let src_root = root.join("src"); - let package_mist = read_mist_package(root); - let mod_decls = { - let docs = documents.lock().await; - compute_mod_decls(&docs, &src_root, &package_mist) - }; - for (mist_path, decl) in &mod_decls { - if decl.is_empty() { + let decl = mod_decls.get(file).map(String::as_str).unwrap_or(""); + let source = match documents.lock().await.get(file) { + Some(r) => r.to_string(), + None => { + eprintln!("missing document for {:?}", file); continue; } - let source = match documents.lock().await.get(mist_path) { - Some(r) => r.to_string(), - None => continue, - }; - let transpiled = match transpile_mist(mist_path, &source, decl) { - Ok(t) => t, - Err(e) => { - eprintln!("module tree transpile error for {:?}: {e}", mist_path); - continue; - } - }; - if let Some(rust_uri) = clean_lsp_url(&transpiled.rust_path) { - let _ = ra - .lock() - .await - .did_change(rust_uri, &transpiled.rust_content, 0) - .await; - mapping - .lock() - .await - .insert(transpiled.rust_path, transpiled.mapping); + }; + let transpiled = match transpile_mist(file, &source, decl) { + Ok(t) => t, + Err(e) => { + eprintln!("transpile error for {:?}: {e}", file); + continue; } + }; + + if let Some(rust_uri) = clean_lsp_url(&transpiled.rust_path) { + let _ = ra + .lock() + .await + .did_open(rust_uri, &transpiled.rust_content) + .await; + mapping + .lock() + .await + .insert(transpiled.rust_path, transpiled.mapping); } } diff --git a/crates/analyzer/src/rust_analyzer.rs b/crates/analyzer/src/rust_analyzer.rs index 56450cb..2fbee2f 100644 --- a/crates/analyzer/src/rust_analyzer.rs +++ b/crates/analyzer/src/rust_analyzer.rs @@ -61,12 +61,15 @@ async fn read_lsp_message( for _ in 0..100 { line.clear(); let bytes_read = reader.read_line(&mut line).await?; - if bytes_read == 0 || line == "\r\n" || line.is_empty() { + if bytes_read == 0 || line.trim().is_empty() { break; } if line.to_ascii_lowercase().starts_with("content-length:") { if let Some(val_str) = line.split(':').nth(1) { - content_length = val_str.trim().parse::()?; + let trimmed = val_str.trim(); + if !trimmed.is_empty() { + content_length = trimmed.parse::()?; + } } } } @@ -117,12 +120,16 @@ impl RustAnalyzer { let raw = match read_lsp_message(&mut stdout).await { Ok(v) => v, Err(err) => { - eprintln!("LSP fatal stream read failure: {err}"); + eprintln!("LSP stream error: {err}"); + // Drain pending requests so they don't hang forever. let mut lock = pending_clone.lock().await; for (_, tx) in lock.drain() { - let _ = tx.send(Err(format!("LSP reader task dropped: {}", err))); + let _ = tx.send(Err(format!("LSP reader error: {}", err))); } - break; + // Brief backoff then retry — ra may have sent a malformed frame + // but the connection is still alive. + tokio::time::sleep(Duration::from_millis(50)).await; + continue; } };