#![cfg(any(
not(any(
feature = "parser_tests",
feature = "analyzer_tests",
feature = "codegen_tests",
feature = "interpreter_tests",
feature = "conformance_tests",
feature = "integration_tests",
)),
feature = "analyzer_tests",
))]
#[path = "common/test_utils.rs"]
mod test_utils;
use anyhow::Result;
use std::fs;
use std::process::Command;
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_suppress_return_when_last_statement() -> Result<()> {
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos();
let _tmp = tempfile::tempdir().unwrap();
let temp_dir = _tmp.path().join(format!("wj_return_test_{}", timestamp));
fs::create_dir_all(&temp_dir)?;
let src_dir = temp_dir.join("src");
fs::create_dir_all(&src_dir)?;
fs::write(
src_dir.join("main.wj"),
r#"
fn get_number() -> i32 {
return 42
}
fn get_optional() -> Option<i32> {
return Some(10)
}
fn process(x: i32) -> i32 {
if x > 0 {
return x * 2
} else {
return 0
}
}
fn main() {
let n = get_number()
let opt = get_optional()
let result = process(5)
}
"#,
)?;
fs::write(
temp_dir.join("wj.toml"),
r#"
[package]
name = "return-test"
version = "0.1.0"
[dependencies]
"#,
)?;
let output_dir = temp_dir.join("src");
let output = Command::new(test_utils::wj_binary())
.args(["build", "--no-cargo"])
.arg(src_dir.to_str().unwrap())
.arg("--output")
.arg(output_dir.to_str().unwrap())
.output()?;
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
let generated = fs::read_to_string(output_dir.join("main.rs")).unwrap_or_else(|_| {
panic!(
"Failed to read generated main.rs\nstdout: {}\nstderr: {}",
stdout, stderr
)
});
assert!(
!generated.contains("return 42;"),
"Last statement 'return 42' should be optimized to implicit return.\nGenerated:\n{}",
generated
);
assert!(
!generated.contains("return x * 2;") || !generated.contains("return 0;"),
"Return statements in if-else branches as last statements should be optimized.\nGenerated:\n{}",
generated
);
assert!(
generated.contains("fn get_number() -> i32") && (generated.contains(" 42") || generated.contains("42\n}")),
"Function should have implicit return (expression without 'return' keyword).\nGenerated:\n{}",
generated
);
Ok(())
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_keep_return_when_early_exit() -> Result<()> {
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos();
let _tmp2 = tempfile::tempdir().unwrap();
let temp_dir = _tmp2
.path()
.join(format!("wj_early_return_test_{}", timestamp));
fs::create_dir_all(&temp_dir)?;
let src_dir = temp_dir.join("src");
fs::create_dir_all(&src_dir)?;
fs::write(
src_dir.join("main.wj"),
r#"
fn check_value(x: i32) -> string {
if x < 0 {
return "negative"
}
if x == 0 {
return "zero"
}
"positive"
}
fn main() {
let result = check_value(10)
}
"#,
)?;
fs::write(
temp_dir.join("wj.toml"),
r#"
[package]
name = "early-return-test"
version = "0.1.0"
[dependencies]
"#,
)?;
let output_dir = temp_dir.join("src");
let output = Command::new(test_utils::wj_binary())
.args(["build", "--no-cargo"])
.arg(src_dir.to_str().unwrap())
.arg("--output")
.arg(output_dir.to_str().unwrap())
.output()?;
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
let generated = fs::read_to_string(output_dir.join("main.rs")).unwrap_or_else(|_| {
panic!(
"Failed to read generated main.rs\nstdout: {}\nstderr: {}",
stdout, stderr
)
});
assert!(
generated.contains("return") && generated.contains("negative"),
"Early return statements should be preserved (they're not last statements).\nGenerated:\n{}",
generated
);
Ok(())
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_suppress_void_return() -> Result<()> {
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos();
let _tmp3 = tempfile::tempdir().unwrap();
let temp_dir = _tmp3
.path()
.join(format!("wj_void_return_test_{}", timestamp));
fs::create_dir_all(&temp_dir)?;
let src_dir = temp_dir.join("src");
fs::create_dir_all(&src_dir)?;
fs::write(
src_dir.join("main.wj"),
r#"
fn do_something(x: i32) {
if x > 0 {
// some work
return
}
// more work
}
fn main() {
do_something(5)
}
"#,
)?;
fs::write(
temp_dir.join("wj.toml"),
r#"
[package]
name = "void-return-test"
version = "0.1.0"
[dependencies]
"#,
)?;
let output_dir = temp_dir.join("src");
let output = Command::new(test_utils::wj_binary())
.args(["build", "--no-cargo"])
.arg(src_dir.to_str().unwrap())
.arg("--output")
.arg(output_dir.to_str().unwrap())
.output()?;
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
let generated = fs::read_to_string(output_dir.join("main.rs")).unwrap_or_else(|_| {
panic!(
"Failed to read generated main.rs\nstdout: {}\nstderr: {}",
stdout, stderr
)
});
assert!(
output.status.success() || generated.contains("fn do_something"),
"Void return handling should compile successfully.\nGenerated:\n{}",
generated
);
Ok(())
}