diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index 65a74ec..a6daff3 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -157,9 +157,32 @@ impl Backend { modified.push(' '); modified.push_str(&source[offset..]); - let transpiled = transpile_mist(mist_path, &modified, extra_mod_decl).ok()?; - let rust_pos = find_marker_position(&transpiled.rust_content, &marker)?; - let rust_uri = clean_lsp_url(&transpiled.rust_path)?; + let transpiled = match transpile_mist(mist_path, &modified, extra_mod_decl) { + Ok(t) => t, + Err(e) => { + eprintln!("[marker] transpile failed for {marker} at LSP({line},{character}): {e}"); + return None; + } + }; + let rust_pos = match find_marker_position(&transpiled.rust_content, &marker) { + Some(p) => p, + None => { + eprintln!("[marker] marker {marker} not found in transpiled output"); + return None; + } + }; + let rust_uri = match clean_lsp_url(&transpiled.rust_path) { + Some(u) => u, + None => { + eprintln!("[marker] failed to create URI for {:?}", transpiled.rust_path); + return None; + } + }; + + eprintln!( + "[marker] {marker}: mist LSP({line},{character}) -> rust LSP({},{})", + rust_pos.line, rust_pos.character + ); Some((rust_uri, rust_pos)) } @@ -552,6 +575,7 @@ impl LanguageServer for Backend { ) .await else { + eprintln!("[completion] resolve_mist_via_marker returned None at ({}, {})", mist_pos.line, mist_pos.character); return Ok(None); }; @@ -624,6 +648,7 @@ impl LanguageServer for Backend { ) .await else { + eprintln!("[goto_definition] resolve_mist_via_marker returned None at ({}, {})", mist_pos.line, mist_pos.character); return Ok(None); }; @@ -747,6 +772,7 @@ impl LanguageServer for Backend { ) .await else { + eprintln!("[hover] resolve_mist_via_marker returned None at ({}, {})", mist_pos.line, mist_pos.character); return Ok(None); }; diff --git a/crates/analyzer/src/rust_analyzer.rs b/crates/analyzer/src/rust_analyzer.rs index 8a4a7d3..a5ba763 100644 --- a/crates/analyzer/src/rust_analyzer.rs +++ b/crates/analyzer/src/rust_analyzer.rs @@ -47,8 +47,16 @@ async fn send_lsp_message( ) -> std::io::Result<()> { let payload = serde_json::to_string(value)?; let frame = format!("Content-Length: {}\r\n\r\n{}", payload.len(), payload); - writer.write_all(frame.as_bytes()).await?; - writer.flush().await?; + eprintln!("[send] writing {} bytes to child stdin", frame.len()); + if let Err(e) = writer.write_all(frame.as_bytes()).await { + eprintln!("[send] write_all failed: {e}"); + return Err(e); + } + if let Err(e) = writer.flush().await { + eprintln!("[send] flush failed: {e}"); + return Err(e); + } + eprintln!("[send] write OK"); Ok(()) } @@ -106,7 +114,7 @@ impl RustAnalyzer { let mut child = tokio::process::Command::new("rust-analyzer") .stdin(Stdio::piped()) .stdout(Stdio::piped()) - .stderr(Stdio::null()) + .stderr(Stdio::piped()) .spawn()?; let stdin = child @@ -117,12 +125,35 @@ impl RustAnalyzer { .stdout .take() .ok_or("Failed to open child stdout pipe")?; + let stderr = child + .stderr + .take() + .ok_or("Failed to open child stderr pipe")?; + + tokio::spawn(async move { + let mut stderr = stderr; + let mut buf = vec![0u8; 4096]; + loop { + match stderr.read(&mut buf).await { + Ok(0) => break, + Ok(n) => { + eprintln!("[ra-stderr] {}", String::from_utf8_lossy(&buf[..n]).trim_end()); + } + Err(e) => { + eprintln!("[ra-stderr] read error: {e}"); + break; + } + } + } + eprintln!("[ra-stderr] stream closed"); + }); let pending: PendingMap = Arc::new(Mutex::new(HashMap::new())); let pending_clone = pending.clone(); tokio::spawn(async move { let mut stdout = BufReader::new(stdout); + eprintln!("[ra-reader] started"); loop { let raw = match read_lsp_message(&mut stdout).await { @@ -137,6 +168,7 @@ impl RustAnalyzer { // EOF means the child process exited — stop the reader. // Other errors (malformed frames) get a brief backoff then retry. if err.to_string().contains("LSP stream closed (EOF)") { + eprintln!("LSP reader task: EOF detected, stopping reader"); break; } tokio::time::sleep(Duration::from_millis(50)).await;