ryo-app 0.1.0

[preview] Application layer for RYO - Project management, Intent handling, API
Documentation
//! Core types for Graph module

use ryo_analysis::{SymbolId, SymbolKind};
use std::path::PathBuf;

/// Graph statistics
#[derive(Debug, Clone)]
pub struct GraphStats {
    pub files: usize,
    pub nodes: usize,
    pub functions: usize,
    pub structs: usize,
    pub enums: usize,
    pub traits: usize,
    pub impls: usize,
    pub edges: usize,
}

/// A code node returned from queries
#[derive(Debug, Clone)]
pub struct CodeNode {
    pub name: String,
    pub file: PathBuf,
    pub kind: NodeKind,
    pub is_public: bool,
    pub is_async: bool,
    pub symbol_id: SymbolId,
}

/// Kind of code node
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeKind {
    Function,
    Struct,
    Enum,
    Trait,
    Impl,
    Mod,
    TypeAlias,
    Const,
    Static,
}

impl NodeKind {
    pub fn as_str(&self) -> &'static str {
        match self {
            NodeKind::Function => "fn",
            NodeKind::Struct => "struct",
            NodeKind::Enum => "enum",
            NodeKind::Trait => "trait",
            NodeKind::Impl => "impl",
            NodeKind::Mod => "mod",
            NodeKind::TypeAlias => "type",
            NodeKind::Const => "const",
            NodeKind::Static => "static",
        }
    }
}

impl From<SymbolKind> for NodeKind {
    fn from(kind: SymbolKind) -> Self {
        match kind {
            SymbolKind::Function | SymbolKind::Method => NodeKind::Function,
            SymbolKind::Struct => NodeKind::Struct,
            SymbolKind::Enum => NodeKind::Enum,
            SymbolKind::Trait => NodeKind::Trait,
            SymbolKind::Impl => NodeKind::Impl,
            SymbolKind::Mod => NodeKind::Mod,
            SymbolKind::TypeAlias => NodeKind::TypeAlias,
            SymbolKind::Const => NodeKind::Const,
            SymbolKind::Static => NodeKind::Static,
            _ => NodeKind::Function,
        }
    }
}

/// Graph API error
#[derive(Debug, thiserror::Error)]
pub enum GraphError {
    #[error("Failed to load project: {0}")]
    LoadFailed(String),
}

#[cfg(test)]
mod tests {
    use super::*;
    use ryo_analysis::SymbolKind;

    #[test]
    fn test_node_kind_as_str() {
        assert_eq!(NodeKind::Function.as_str(), "fn");
        assert_eq!(NodeKind::Struct.as_str(), "struct");
        assert_eq!(NodeKind::Enum.as_str(), "enum");
        assert_eq!(NodeKind::Trait.as_str(), "trait");
        assert_eq!(NodeKind::Impl.as_str(), "impl");
        assert_eq!(NodeKind::Mod.as_str(), "mod");
        assert_eq!(NodeKind::TypeAlias.as_str(), "type");
        assert_eq!(NodeKind::Const.as_str(), "const");
        assert_eq!(NodeKind::Static.as_str(), "static");
    }

    #[test]
    fn test_node_kind_from_symbol_kind() {
        assert_eq!(NodeKind::from(SymbolKind::Function), NodeKind::Function);
        assert_eq!(NodeKind::from(SymbolKind::Struct), NodeKind::Struct);
        assert_eq!(NodeKind::from(SymbolKind::Enum), NodeKind::Enum);
        assert_eq!(NodeKind::from(SymbolKind::Trait), NodeKind::Trait);
        assert_eq!(NodeKind::from(SymbolKind::Impl), NodeKind::Impl);
        assert_eq!(NodeKind::from(SymbolKind::Mod), NodeKind::Mod);
    }

    #[test]
    fn test_graph_error_display() {
        let err = GraphError::LoadFailed("file not found".to_string());
        assert!(err.to_string().contains("Failed to load project"));
        assert!(err.to_string().contains("file not found"));
    }
}