#[cfg(test)]
mod tests {
use crate::tree::{
ast::{
expression::ExpressionKind,
identifier::{ParsedSimpleIdentifier, SimpleIdentifier},
},
builder::*,
};
use rstest::rstest;
#[test]
fn test_builder_chaining() {
let expr = array().element(1).element(2).element(3);
let ast = expr.build();
match &ast.kind {
ExpressionKind::ArrayLiteral(arr) => {
assert_eq!(arr.elements.len(), 3);
}
_ => panic!("Expected ArrayLiteral"),
}
}
#[rstest]
#[case(42)]
#[case(3.14)]
#[case("hello")]
#[case(true)]
fn test_into_expression_builder<T: IntoExpressionBuilder>(#[case] value: T) {
let _: Box<dyn ExpressionBuilder> = value.into_expression_builder();
}
#[test]
fn test_builder_produces_valid_ast() {
let int_ast = int(42).build();
assert!(matches!(int_ast.kind, ExpressionKind::IntLiteral(_)));
let str_ast = string("hello").build();
assert!(matches!(str_ast.kind, ExpressionKind::StringLiteral(_)));
let bool_ast = boolean(true).build();
assert!(matches!(bool_ast.kind, ExpressionKind::BooleanLiteral(_)));
let arr_ast = array().element(1).element(2).build();
assert!(matches!(arr_ast.kind, ExpressionKind::ArrayLiteral(_)));
let binary_ast = add(1, 2).build();
assert!(matches!(binary_ast.kind, ExpressionKind::BinaryOperator(_)));
let func_ast = call("test").arg(1).build();
assert!(matches!(func_ast.kind, ExpressionKind::FunctionCall(_)));
}
#[test]
fn test_builder_roundtripping() {
let original = add(1, 2);
let ast = original.build();
let builder_from_ast = ast.clone().into_expression_builder();
let ast2 = builder_from_ast.build();
assert!(matches!(ast.kind, ExpressionKind::BinaryOperator(_)));
assert!(matches!(ast2.kind, ExpressionKind::BinaryOperator(_)));
}
#[test]
fn test_nested_builder_composition() {
let complex = struct_literal()
.field("array", array().element(1).element(2))
.field("tuple", tuple().element("a").element(true))
.field("nested", struct_literal().field("x", 10));
let ast = complex.build();
match &ast.kind {
ExpressionKind::StructLiteral(s) => {
assert_eq!(s.fields.len(), 3);
}
_ => panic!("Expected StructLiteral"),
}
}
#[test]
fn test_function_builder_arguments() {
let func1 = call("test").arg(1).arg(2).arg(3).build();
match &func1.kind {
ExpressionKind::FunctionCall(f) => {
assert_eq!(f.positional_args.len(), 3);
assert_eq!(f.named_args.len(), 0);
}
_ => panic!("Expected FunctionCall"),
}
let func2 = call("test")
.named_arg("param1", 1)
.named_arg("param2", 2)
.build();
match &func2.kind {
ExpressionKind::FunctionCall(f) => {
assert_eq!(f.positional_args.len(), 0);
assert_eq!(f.named_args.len(), 2);
assert!(f.named_args.contains_key(&ParsedSimpleIdentifier::Valid(
SimpleIdentifier::new("param1")
)));
assert!(f.named_args.contains_key(&ParsedSimpleIdentifier::Valid(
SimpleIdentifier::new("param2")
)));
}
_ => panic!("Expected FunctionCall"),
}
let func3 = call("test").arg(1).named_arg("param", 2).arg(3).build();
match &func3.kind {
ExpressionKind::FunctionCall(f) => {
assert_eq!(f.positional_args.len(), 2);
assert_eq!(f.named_args.len(), 1);
}
_ => panic!("Expected FunctionCall"),
}
}
#[test]
fn test_collection_element_methods() {
let arr = array()
.element(1)
.element("string")
.element(true)
.element(array().element(2).element(3));
let ast = arr.build();
match &ast.kind {
ExpressionKind::ArrayLiteral(a) => {
assert_eq!(a.elements.len(), 4);
}
_ => panic!("Expected ArrayLiteral"),
}
let tup = tuple().element(42).element(3.14).element("test");
let ast = tup.build();
match &ast.kind {
ExpressionKind::TupleLiteral(t) => {
assert_eq!(t.elements.len(), 3);
}
_ => panic!("Expected TupleLiteral"),
}
let s = struct_literal()
.field("a", 1)
.field("b", "test")
.field("c", true);
let ast = s.build();
match &ast.kind {
ExpressionKind::StructLiteral(s) => {
assert_eq!(s.fields.len(), 3);
}
_ => panic!("Expected StructLiteral"),
}
}
}