#![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;
#[test]
fn test_method_call_auto_deref_receiver() {
let src = r#"
pub fn length(s: string) -> usize {
s.len()
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("s.len()"));
}
#[test]
fn test_method_call_owned_receiver() {
let src = r#"
pub struct Timer { pub id: i32 }
impl Timer {
pub fn id(self) -> i32 { self.id }
}
pub fn get_id(t: Timer) -> i32 {
t.id() + 0
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("t.id()"));
}
#[test]
fn test_builder_pattern_needs_clone() {
let src = r#"
pub struct Builder {}
impl Builder {
pub fn with_value(self, v: i32) -> Self { self }
}
pub fn build(b: Builder) -> Builder {
b.with_value(42)
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(
result.contains("clone().with_value")
|| (result.contains("with_value(42") && result.contains("b.with_value")),
"Expected builder call with clone or autoderef. Got:\n{}",
result
);
}
#[test]
fn test_mutating_method_push() {
let src = r#"
pub fn add_item() {
let mut v = Vec::new()
v.push(42)
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("v.push(42)"));
}
#[test]
fn test_mutating_method_clear() {
let src = r#"
pub fn clear_vec() {
let mut v = Vec::new()
v.push(1)
v.clear()
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("clear"));
}
#[test]
fn test_chain_calls_trim_len() {
let src = r#"
pub fn trimmed_len(s: string) -> usize {
s.trim().len() + 0
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("s.trim().len()"));
}
#[test]
fn test_chain_calls_multiple() {
let src = r#"
pub fn process(s: string) -> usize {
if s.trim().to_lowercase().len() > 0 {
1
} else {
0
}
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("trim"));
assert!(result.contains("to_lowercase"));
}
#[test]
fn test_borrowed_receiver_len() {
let src = r#"
pub fn get_len(v: Vec<i32>) -> usize {
v.len()
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("v.len()"));
assert!(!result.contains("v.clone()"));
}
#[test]
fn test_borrowed_receiver_is_empty() {
let src = r#"
pub fn check_empty(v: Vec<i32>) -> bool {
v.is_empty()
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("v.is_empty()"));
}
#[test]
fn test_unwrap_on_borrowed_field() {
let src = r#"
pub struct Node { pub value: Option<i32> }
pub fn get_value(n: Node) -> i32 {
n.value.unwrap()
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(
result.contains("unwrap()"),
"Expected unwrap. Got:\n{}",
result
);
}
#[test]
fn test_option_map_with_borrowed_self() {
let src = r#"
pub struct Container { pub items: Option<Vec<i32>> }
impl Container {
pub fn count(self) -> usize {
match self.items {
Some(v) => v.len(),
None => 0
}
}
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("len()"));
}
#[test]
fn test_vec_index_method_owned_receiver() {
let src = r#"
pub struct Item { pub id: i32 }
pub fn get_first_id(items: Vec<Item>) -> i32 {
items[0].id
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("items") && result.contains("id"));
}
#[test]
fn test_explicit_clone_no_double() {
let src = r#"
pub struct Data { pub name: string }
pub fn copy_name(d: Data) -> string {
d.name
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("clone()"));
assert!(
!result.contains(".clone().clone()"),
"Double clone detected. Got:\n{}",
result
);
}
#[test]
fn test_copy_type_no_clone() {
let src = r#"
pub struct Point { pub x: i32, pub y: i32 }
pub fn get_x(p: Point) -> i32 {
p.x
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("p.x"));
assert!(!result.contains("p.x.clone()"));
}
#[test]
fn test_string_starts_with() {
let src = r#"
pub fn check_prefix(s: string) -> bool {
s.starts_with("foo")
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("starts_with"));
}
#[test]
fn test_string_contains() {
let src = r#"
pub fn has_substring(s: string, sub: string) -> bool {
s.contains(sub)
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("contains"));
}
#[test]
fn test_vec_new_static_call() {
let src = r#"
pub fn make_vec() -> Vec<i32> {
Vec::new()
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(
result.contains("Vec::new()") || result.contains("Vec::<i32>::new()"),
"Expected Vec::new() or Vec::<i32>::new(), got:\n{}",
result
);
}
#[test]
fn test_get_on_borrowed_vec() {
let src = r#"
pub fn has_elements(v: Vec<i32>) -> bool {
!v.is_empty()
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("v.is_empty()"));
}
#[test]
fn test_iter_method_on_borrowed() {
let src = r#"
pub fn sum(v: Vec<i32>) -> i32 {
let mut s = 0
for x in v {
s = s + x
}
s
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(
result.contains("for x in v") || result.contains("for x in &v"),
"Should iterate over vec directly or via borrow. Got:\n{}",
result
);
}
#[test]
fn test_field_after_method_call() {
let src = r#"
pub struct Wrapper { pub value: i32 }
pub fn get_inner(w: Wrapper) -> i32 {
w.value
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(result.contains("w.value"));
}