wgsldoc 0.2.1

Documentation generator for WGSL shaders
Documentation
use std::env;
use clap::Parser;
use log::LevelFilter;
use wgsldoc::{cli::Args, generator::TeraGenerator, Document};
use fs_err as fs;

fn main() -> anyhow::Result<()> {
    pretty_env_logger::formatted_builder()
        .filter_level(LevelFilter::Info)
        .init();

    let mut args = Args::parse();

    if !args.target_dir.is_absolute() {
        args.target_dir = env::current_dir()?.join(&args.target_dir);
        args.target_dir = fs::canonicalize(&args.target_dir)?;
    }

    let document = if !args.files.is_empty() {
        Document::new(args.name, &args.files)?
    } else {
        Document::open(args.name, env::current_dir()?)?
    };

    if document.shaders().is_empty() {
        log::warn!("No WGSL shaders found in the specified files or directory.");
        return Ok(());
    }

    let registered = document.register();

    if args.show_undocumented {
        show_undocumented_mode(&registered);
        return Ok(());
    }
    
    if args.ast_only {
        ast_only_mode(&registered);
        return Ok(());
    }

    registered.generate(&mut TeraGenerator::new(args.base_url), args.target_dir)?;

    Ok(())
}

fn ast_only_mode(registered: &wgsldoc::RegisteredDocument) {
    log::info!("AST-only mode enabled. Printing the AST to stdout.");

    for shader in registered.shaders() {
        println!("{} => {:#?}", shader.module_name, shader);
    }
}

fn show_undocumented_mode(registered: &wgsldoc::RegisteredDocument) {
    log::info!("Entering undocumented mode. This will log warnings for any undocumented items in the shaders.");

    for shader in registered.shaders() {
        if shader.global_docs.is_none() {
            log::warn!("Shader '{}' has no documentation.", shader.module_name);
        }

        for function in &shader.functions {
            if function.docs().is_none() {
                log::warn!("Function '{}' in shader '{}' has no documentation.", function.name(), shader.module_name);
            }

            for arg in function.args() {
                if arg.docs().is_none() {
                    log::warn!("Argument '{}' in function '{}' of shader '{}' has no documentation.", arg.name(), function.name(), shader.module_name);
                }
            }
        }

        for structure in &shader.structures {
            if structure.docs().is_none() {
                log::warn!("Struct '{}' in shader '{}' has no documentation.", structure.name(), shader.module_name);
            }

            for field in structure.fields() {
                if field.docs().is_none() {
                    log::warn!("Field '{}' in struct '{}' of shader '{}' has no documentation.", field.name(), structure.name(), shader.module_name);
                }
            }
        }

        for import in &shader.imports {
            if import.docs().is_none() {
                log::warn!("Import '{}' in shader '{}' has no documentation.", import.name(), shader.module_name);
            }
        }
    }
}