nocturne 0.0.1

Code analyzer
Documentation
use judge::rust::RustJudge;
use judge::{Judge, Position};

fn main() {
    let judge = RustJudge::new();

    println!("Advanced Example: Complex Rust Code\n");

    // Example with generics, lifetimes, and trait bounds
    let complex_source = r#"
        use std::collections::HashMap;

        trait Processor<T> {
            fn process(&self, item: T) -> Result<String, String>;
        }

        struct DataProcessor<'a, T: Clone> {
            cache: &'a HashMap<String, T>,
            multiplier: i32,
        }

        impl<'a, T: Clone + std::fmt::Debug> Processor<T> for DataProcessor<'a, T> {
            fn process(&self, item: T) -> Result<String, String> {
                Ok(format!("{:?}", item))
            }
        }

        impl<'a, T: Clone> DataProcessor<'a, T> {
            fn new(cache: &'a HashMap<String, T>) -> Self {
                Self {
                    cache,
                    multiplier: 1,
                }
            }

            fn get_from_cache(&self, key: &str) -> Option<&T> {
                self.cache.get(key)
            }
        }

        type ProcessorResult = Result<String, Box<dyn std::error::Error>>;

        const MAX_ITEMS: usize = 100;
        static GLOBAL_COUNTER: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);

        macro_rules! debug_println {
            ($($arg:tt)*) => {
                #[cfg(debug_assertions)]
                println!($($arg)*);
            };
        }

        fn main() {
            let cache = HashMap::new();
            let processor = DataProcessor::new(&cache);
        }
    "#;

    // Test parsing
    println!("1. Diagnostics:");
    let diagnostics = judge.diagnostics(complex_source);
    if diagnostics.is_empty() {
        println!("   ✓ No syntax errors!\n");
    } else {
        println!("   Errors found:");
        for diag in &diagnostics {
            println!("   {}", diag);
        }
        println!();
    }

    // Test symbol extraction
    println!("2. Symbol Extraction:");
    match judge.symbols(complex_source) {
        Ok(symbols) => {
            println!("   Found {} symbols:\n", symbols.len());
            for symbol in &symbols {
                println!("   {:?}: {}", symbol.kind, symbol.name);
                if let Some(detail) = &symbol.detail {
                    println!("      {}", detail);
                }
                println!();
            }
        }
        Err(e) => println!("   Error: {}", e),
    }

    // Example with incomplete/invalid code (rust-analyzer handles this better)
    println!("\nExample: Incomplete Code (Good Error Recovery)\n");

    let incomplete_source = r#"
        struct Point {
            x: f64,
            y: f64,
        }

        impl Point {
            fn distance(&self, other: &
            // Missing type and incomplete function
        }
    "#;

    println!("3. Parsing Incomplete Code:");
    let diagnostics = judge.diagnostics(incomplete_source);
    println!("   Found {} errors:", diagnostics.len());
    for diag in &diagnostics {
        println!("   {}", diag);
    }

    // Even with errors, we can still extract some symbols
    println!("\n   Symbols extracted despite errors:");
    if let Ok(symbols) = judge.symbols(incomplete_source) {
        for symbol in &symbols {
            println!(
                "   {:?}: {} - {}",
                symbol.kind,
                symbol.name,
                symbol.detail.as_ref().unwrap_or(&"(no detail)".to_string())
            );
        }
    }

    // Example showing method extraction from impl blocks
    println!("\nExample: Method Detection in Impl Blocks\n");

    let methods_source = r#"
        pub struct Calculator {
            value: i32,
        }

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

            pub fn add(&mut self, n: i32) -> &mut Self {
                self.value += n;
                self
            }

            pub fn subtract(&mut self, n: i32) -> &mut Self {
                self.value -= n;
                self
            }

            pub fn get(&self) -> i32 {
                self.value
            }
        }

        impl Default for Calculator {
            fn default() -> Self {
                Self::new()
            }
        }
    "#;

    println!("4. Methods in Impl Blocks:");
    if let Ok(symbols) = judge.symbols(methods_source) {
        for symbol in &symbols {
            if let Some(detail) = &symbol.detail {
                println!("   {}", detail);
            }
        }
    }
}