use std::fs;
use std::path::PathBuf;
use impactsense_parser::scanner::FileScanConfig;
use impactsense_parser::scanner_incremental::{scan_and_parse_incremental_vector, scan_and_stream_incremental_ir};
use impactsense_parser::LanguageId;
fn write_fixture(root: &std::path::Path) -> (PathBuf, PathBuf) {
let cs = root.join("SmokeInc.cs");
let erl = root.join("smoke_inc_mod.erl");
fs::write(
&cs,
r#"namespace SmokeIncNs {
public class SmokeIncType {
public int Counter { get; set; }
public void Run() { }
}
}
"#,
)
.expect("write cs");
fs::write(
&erl,
r#"-module(smoke_inc_mod).
-export([main/0]).
main() -> ok.
"#,
)
.expect("write erl");
(cs, erl)
}
#[test]
fn smoke_incremental_vector_parses_cs_and_erl() {
let root = tempfile::tempdir().expect("tempdir");
let (cs_path, erl_path) = write_fixture(root.path());
let config = FileScanConfig::new(root.path());
let targets = vec![cs_path.clone(), erl_path.clone()];
let parsed = scan_and_parse_incremental_vector(&config, &targets).expect("incremental vector");
assert_eq!(parsed.len(), 2, "expected two parsed files");
let langs: Vec<_> = parsed.iter().map(|f| f.language).collect();
assert!(langs.contains(&LanguageId::CSharp));
assert!(langs.contains(&LanguageId::Erlang));
}
#[test]
fn smoke_streaming_ir_populates_csharp_structural_ir() {
let root = tempfile::tempdir().expect("tempdir");
let (cs_path, erl_path) = write_fixture(root.path());
let config = FileScanConfig::new(root.path());
let targets = vec![cs_path, erl_path];
let ir = scan_and_stream_incremental_ir(&config, &targets).expect("streaming ir");
assert_eq!(ir.files.len(), 2);
assert!(
ir.classes.iter().any(|c| c.fqn == "SmokeIncNs.SmokeIncType"),
"missing C# class in IR: {:?}",
ir.classes
);
assert!(
ir.properties
.iter()
.any(|p| p.fqn == "SmokeIncNs.SmokeIncType.Counter"),
"missing C# property in IR: {:?}",
ir.properties
);
assert!(
ir.edges.iter().any(|e| {
e.kind == impactsense_parser::ir::EdgeKind::DeclaresClass && e.to_key == "SmokeIncNs.SmokeIncType"
}),
"missing DECLARES_CLASS edge"
);
}