inline-fn 0.0.1

Inline the content of a function without duplicating code. Useful when duplicating code is desired but you are too embarrassed to do it manually.
Documentation
use super::*;

#[test]
fn basic_function() {
    let code = r#"
        fn hello() {
            println!("Hello, world!");
        }"#;

    let result = extract_function(code, "hello");
    let function = result.expect("Function not found");
    assert_eq!(function, r#"println!("Hello, world!");"#);
}

#[test]
fn function_with_parameters() {
    let code = r#"
        fn add(a: i32, b: i32) -> i32 {
            a + b
        }"#;

    let result = extract_function(code, "add");
    let function = result.expect("Function not found");
    assert_eq!(function, "a + b");
}

#[test]
fn function_with_generics() {
    let code = r#"
        fn process<T: Display>(item: T) -> String {
            format!("Processed: {}", item)
        }"#;

    let result = extract_function(code, "process");
    let function = result.expect("Function not found");
    assert_eq!(function, "format!(\"Processed: {}\", item)");
}

#[test]
fn nested_braces() {
    let code = r#"
        fn complex() {
            if true {
                let x = {
                    let y = 5;
                    y * 2
                };
                println!("{}", x);
            }
        }"#;

    let result = extract_function(code, "complex");
    let function = result.expect("Function not found");
    assert!(function.starts_with("if true {"));
}

#[test]
fn string_with_braces() {
    let code = r##"
        fn tricky_strings() {
            println!("This is a { with a } inside a string");
            let json = r#"{"key": "value"}"#;
        }"##;

    let result = extract_function(code, "tricky_strings");
    let function = result.expect("Function not found");
    assert!(function.starts_with("println!("));
    assert!(function.contains("This is a { with a } inside a string"));
}

#[test]
fn comments() {
    let code = r#"
fn commented() {
    // This is a comment with { braces }
    /* This is a block comment
       with { nested } braces */
    let x = 5; // Another comment
}"#;

    let result = extract_function(code, "commented");
    let function = result.expect("Function not found");
    assert!(function.contains("let x = 5;"));
}

#[test]
fn public_function() {
    let code = r#"
pub fn public_function() {
    println!("I'm public!");
}"#;

    let result = extract_function(code, "public_function");
    let function = result.expect("Function not found");
    assert!(function.contains("I'm public!"));
}

#[test]
fn function_with_attributes() {
    let code = r#"
#[derive(Debug)]
#[inline]
pub fn attributed() {
    println!("I have attributes!");
}"#;

    let result = extract_function(code, "attributed");
    let function = result.expect("Function not found");
    assert!(function.contains("I have attributes!"));
}

#[test]
fn async_function() {
    let code = r#"
async fn fetch_data() -> Result<String, Error> {
    Ok("data".to_string())
}"#;

    let result = extract_function(code, "fetch_data");
    let function = result.expect("Function not found");
    assert!(function.contains("Ok(\"data\".to_string())"));
}

#[test]
fn unsafe_function() {
    let code = r#"
unsafe fn dangerous() {
    let ptr = 0x12345 as *mut i32;
    *ptr = 42;
}"#;

    let result = extract_function(code, "dangerous");
    let function = result.expect("Function not found");
    assert!(function.contains("*ptr = 42;"));
}

#[test]
fn multiple_functions() {
    let code = r#"
fn first() {
    println!("First");
}

fn second() {
    println!("Second");
}

fn third() {
    println!("Third");
}"#;

    let result = extract_function(code, "second");
    let function = result.expect("Function not found");
    assert!(function.contains("println!(\"Second\");"));
    assert!(!function.contains("println!(\"First\");"));
    assert!(!function.contains("println!(\"Third\");"));
}

#[test]
fn nested_functions() {
    let code = r#"
fn outer() {
    println!("Outer start");

    fn inner() {
        println!("Inner function");
    }

    inner();
    println!("Outer end");
}"#;

    let outer = extract_function(code, "outer");
    assert!(outer.is_some());
    let outer_fn = outer.unwrap();
    assert!(outer_fn.contains("fn inner()"));

    let inner = extract_function(code, "inner");
    assert!(inner.is_some());
    let inner_fn = inner.unwrap();
    assert!(inner_fn.contains("Inner function"));
}

#[test]
fn impl_method() {
    let code = r#"
struct Calculator;

impl Calculator {
    pub fn new() -> Self {
        Calculator
    }

    fn add(&self, a: i32, b: i32) -> i32 {
        a + b
    }
}"#;

    let result = extract_function(code, "add");
    let function = result.expect("Function not found");
    assert!(function.contains("a + b"));
}

#[test]
fn function_with_where_clause() {
    let code = r#"
fn complex_generic<T, U>(t: T, u: U) -> Vec<String>
where
    T: Display + Clone,
    U: AsRef<str>,
{
    vec![format!("{}", t), u.as_ref().to_string()]
}"#;

    let result = extract_function(code, "complex_generic");
    let function = result.expect("Function not found");
    assert_eq!(
        function,
        r#"vec![format!("{}", t), u.as_ref().to_string()]"#
    );
}

#[test]
fn function_not_found() {
    let code = r#"
fn hello() {
    println!("Hello!");
}"#;

    let result = extract_function(code, "goodbye");
    assert!(result.is_none());
}

#[test]
fn closure_with_same_name_as_function() {
    let code = r#"
fn process() {
    println!("Real function");
}

fn main() {
    let process = || {
        println!("Closure");
    };
    process();
}"#;

    let result = extract_function(code, "process");
    let function = result.expect("Function not found");
    assert_eq!(function, r#"println!("Real function");"#);
    assert!(!function.contains("Closure"));
}