use {
crate::process,
ferrotype::Ferrotype,
quote::quote,
};
#[test_log::test]
fn test_simple_ast_struct() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST)]
pub struct Simple {
field: NodeId<crate::Type>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
let output_str = output.to_string();
assert!(output_str.contains("impl Simple"));
},
| Err(e) => {
panic!("Unexpected error: {e:?}");
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_with_field_types() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST)]
pub struct Complex {
simple_field: NodeId<crate::Type>,
optional_field: Option<NodeId<crate::Type>>,
vec_field: Vec<crate::Item>,
field_field: Field<bool>,
enum_field: Field<Enum<crate::Visibility>>,
enum_node: EnumNodeId<crate::Expression>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
},
| Err(e) => {
panic!("Unexpected error: {e:?}");
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_with_multiple_type_params() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST)]
pub struct MultiType {
union_field: NodeId<crate::Type1, crate::Type2>,
triple_field: NodeId<crate::Type1, crate::Type2, crate::Type3>,
vec_multi: Vec<crate::Type1, crate::Type2>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
},
| Err(e) => {
panic!("Unexpected error: {e:?}");
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_with_doc_comments() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST)]
pub struct Documented {
field1: NodeId<crate::Type>,
field2: Option<NodeId<crate::Type>>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
},
| Err(e) => {
panic!("Unexpected error: {e:?}");
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_error_node() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST, error)]
pub struct ErrorNode {
message: String,
span: Span,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST, error), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
},
| Err(e) => {
panic!("Unexpected error: {e:?}");
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_with_semantic_tokens() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST, allow_semantic)]
pub struct SemanticNode {
token: NodeId<crate::Token>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST, allow_semantic), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
},
| Err(e) => {
panic!("Unexpected error: {e:?}");
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_error_not_struct() {
let mut snapshot = Ferrotype::new();
snapshot.set_expect_errors(true);
let input = quote! {
#[laburnum_syntax(AST)]
pub enum NotAStruct {
Variant1,
Variant2,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(_) => {
panic!("Expected error for non-struct item");
},
| Err(e) => {
snapshot.add_debug("Error", &e);
let error_message = e.to_string();
assert!(
error_message.contains("struct"),
"Error message should mention 'struct', got: {error_message}",
);
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_error_invalid_field_type() {
let mut snapshot = Ferrotype::new();
snapshot.set_expect_errors(true);
let input = quote! {
#[laburnum_syntax(AST)]
pub struct InvalidField {
bad_field: HashMap<String, i32>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(_) => {
panic!("Expected error for invalid field type");
},
| Err(e) => {
snapshot.add_debug("Error", &e);
let error_message = e.to_string();
assert!(
error_message.contains("literal types do not take any arguments"),
"Expected error message about literal types, but got: {error_message}",
);
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_error_empty_struct() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST)]
pub struct Empty {}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
},
| Err(e) => {
snapshot.add_debug("Error", &e);
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_with_generics() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST)]
pub struct Generic<T> {
field: NodeId<T>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
},
| Err(e) => {
snapshot.add_debug("Error", &e);
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_complex_real_world_example() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST)]
pub struct Function {
visibility: Field<Enum<crate::modifier::Visibility>>,
ident: NodeId<crate::symbol::Ident>,
generic_parameters: Option<NodeId<crate::ty::GenericParameters>>,
parameters: Vec<crate::ty::Parameters>,
return_ty: Option<NodeId<crate::ty::Path>>,
effects_required: Vec<NodeId<crate::ty::Path>>,
effects_handled: Vec<NodeId<crate::ty::Path>>,
body: NodeId<crate::expression::Block>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
let output_str = output.to_string();
assert!(output_str.contains("impl Function"));
},
| Err(e) => {
panic!("Unexpected error: {e:?}");
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_multiple_attributes() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[derive(Debug, Clone)]
#[laburnum_syntax(AST)]
pub struct MultiAttr {
field: NodeId<crate::Type>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
let output_str = output.to_string();
assert!(output_str.contains("derive"));
},
| Err(e) => {
panic!("Unexpected error: {e:?}");
},
}
ferrotype::assert!(snapshot);
}
#[test_log::test]
fn test_ast_private_struct() {
let mut snapshot = Ferrotype::new();
let input = quote! {
#[laburnum_syntax(AST)]
struct Private {
field: NodeId<crate::Type>,
}
};
snapshot.add_token_stream("Input", &input);
match process(quote!(AST), input) {
| Ok(output) => {
snapshot.add_token_stream("Output", &output);
},
| Err(e) => {
panic!("Unexpected error: {e:?}");
},
}
ferrotype::assert!(snapshot);
}