Adds the DiagnosticsSource seam trait in harness-core::lsp (kept out of harness-tools so tools never link the LSP crate directly), and implements it in harness-lsp as a pool that lazily spawns one language server per file extension (rust-analyzer, typescript-language-server, gopls, pyright-langserver) only when the binary is on PATH. Adds harness-tools::diagnostics and wires diagnostics into edit/write/bash/glob/grep output.
35 lines
1.4 KiB
Rust
35 lines
1.4 KiB
Rust
//! End-to-end LSP test against a real `rust-analyzer`. Ignored by default (requires the binary
|
|
//! on PATH and is slow — RA indexes the project). Run with:
|
|
//! cargo test -p harness-lsp --test rust_analyzer -- --ignored --nocapture
|
|
|
|
use std::time::Duration;
|
|
|
|
use harness_core::lsp::{DiagnosticsSource, Severity};
|
|
use harness_lsp::LspPool;
|
|
|
|
#[tokio::test]
|
|
#[ignore = "requires rust-analyzer on PATH; slow"]
|
|
async fn rust_analyzer_reports_a_type_error() {
|
|
// Minimal cargo project with a deliberate type error.
|
|
let dir = tempfile::tempdir().unwrap();
|
|
std::fs::write(
|
|
dir.path().join("Cargo.toml"),
|
|
"[package]\nname = \"probe\"\nversion = \"0.1.0\"\nedition = \"2021\"\n",
|
|
)
|
|
.unwrap();
|
|
std::fs::create_dir_all(dir.path().join("src")).unwrap();
|
|
let main_rs = dir.path().join("src/main.rs");
|
|
std::fs::write(&main_rs, "fn main() {\n let x: i32 = \"not an integer\";\n let _ = x;\n}\n").unwrap();
|
|
|
|
let pool = LspPool::new(dir.path().to_path_buf(), vec![]);
|
|
pool.touch(&main_rs).await;
|
|
// Generous wait: rust-analyzer must index the workspace before it reports anything.
|
|
let diags = pool.diagnostics(&main_rs, Duration::from_secs(60)).await;
|
|
|
|
println!("diagnostics: {diags:#?}");
|
|
assert!(
|
|
diags.iter().any(|d| d.severity == Severity::Error),
|
|
"expected at least one error diagnostic, got: {diags:?}"
|
|
);
|
|
}
|