windjammer 0.48.0

A simple language inspired by Go, Ruby, and Elixir that transpiles to Rust - 80% of Rust's power with 20% of the complexity
Documentation
#![cfg(any(
    not(any(
        feature = "parser_tests",
        feature = "analyzer_tests",
        feature = "codegen_tests",
        feature = "interpreter_tests",
        feature = "conformance_tests",
        feature = "integration_tests",
    )),
    feature = "codegen_tests",
))]

//! Comprehensive Codegen Generics Tests
//!
//! These tests verify that the Windjammer compiler correctly generates
//! Rust code for generics, including:
//! - Type parameters
//! - Trait bounds
//! - Where clauses
//! - Generic structs and functions

#[path = "common/test_utils.rs"]
mod test_utils;

// ============================================================================
// HELPER FUNCTIONS
// ============================================================================

// ============================================================================
// GENERIC FUNCTIONS
// ============================================================================

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_generic_function_simple() {
    let code = r#"
pub fn identity<T>(x: T) -> T {
    x
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Generic function should compile. Error: {}", err);
}

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_generic_function_multiple_params() {
    let code = r#"
pub fn pair<A, B>(a: A, b: B) -> (A, B) {
    (a, b)
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(
        success,
        "Multiple generic params should compile. Error: {}",
        err
    );
}

// ============================================================================
// GENERIC STRUCTS
// ============================================================================

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_generic_struct() {
    let code = r#"
@derive(Clone, Debug)
pub struct Container<T> {
    value: T,
}

impl<T> Container<T> {
    pub fn new(value: T) -> Container<T> {
        Container { value: value }
    }
    
    pub fn get(self) -> &T {
        self.value
    }
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Generic struct should compile. Error: {}", err);
}

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_generic_struct_multiple() {
    let code = r#"
@derive(Clone, Debug)
pub struct Pair<A, B> {
    first: A,
    second: B,
}

impl<A, B> Pair<A, B> {
    pub fn new(first: A, second: B) -> Pair<A, B> {
        Pair { first: first, second: second }
    }
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(
        success,
        "Generic struct multiple should compile. Error: {}",
        err
    );
}

// ============================================================================
// TRAIT BOUNDS
// ============================================================================

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_trait_bound_clone() {
    let code = r#"
pub fn duplicate<T: Clone>(item: T) -> (T, T) {
    (item, item)
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Clone bound should compile. Error: {}", err);
}

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_trait_bound_multiple() {
    // Multiple trait bounds
    let code = r#"
pub fn clone_twice<T: Clone>(item: T) -> (T, T) {
    let a = item;
    let b = item;
    (a, b)
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Multiple bounds should compile. Error: {}", err);
}

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_trait_bound_default() {
    let code = r#"
pub fn get_default<T: Default>() -> T {
    T::default()
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Default bound should compile. Error: {}", err);
}

// ============================================================================
// GENERIC ENUMS
// ============================================================================

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_generic_enum() {
    // Simple generic enum definition
    let code = r#"
pub enum Maybe<T> {
    Just(T),
    Nothing,
}

pub fn is_just<T>(m: Maybe<T>) -> bool {
    match m {
        Maybe::Just(_) => true,
        Maybe::Nothing => false,
    }
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Generic enum should compile. Error: {}", err);
}

// ============================================================================
// GENERIC TRAITS
// ============================================================================

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_simple_impl() {
    // Simple impl block
    let code = r#"
@derive(Clone, Debug)
pub struct Counter {
    count: i32,
}

impl Counter {
    pub fn increment(self) {
        self.count += 1
    }
    
    pub fn get(self) -> i32 {
        self.count
    }
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Simple impl should compile. Error: {}", err);
}

// ============================================================================
// GENERIC METHODS
// ============================================================================

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_generic_method() {
    // Simpler generic method
    let code = r#"
@derive(Clone, Debug)
pub struct Container<T> {
    value: T,
}

impl<T: Clone> Container<T> {
    pub fn duplicate(self) -> Container<T> {
        Container { value: self.value }
    }
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Generic method should compile. Error: {}", err);
}

// ============================================================================
// VEC AND OPTION USAGE
// ============================================================================

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_vec_generic() {
    let code = r#"
pub fn first<T: Clone>(items: Vec<T>) -> Option<T> {
    items.first()
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Vec generic should compile. Error: {}", err);
}

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_option_generic() {
    // Simple option usage
    let code = r#"
pub fn is_some<T>(opt: Option<T>) -> bool {
    match opt {
        Some(_) => true,
        None => false,
    }
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Option generic should compile. Error: {}", err);
}

// ============================================================================
// ASSOCIATED TYPES (SIMULATED)
// ============================================================================

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_iterator_usage() {
    // Basic iterator usage with Vec
    let code = r#"
pub fn count_items(items: Vec<i32>) -> usize {
    items.count()
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Iterator usage should compile. Error: {}", err);
}

// ============================================================================
// LIFETIME PARAMETERS (BASIC)
// ============================================================================

#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_reference_return() {
    // Simple reference return (lifetime inferred)
    let code = r#"
pub fn get_first(items: Vec<i32>) -> Option<&i32> {
    items.first()
}
"#;
    let (success, _generated, err) = test_utils::compile_via_cli(code);
    assert!(success, "Reference return should compile. Error: {}", err);
}