ryo-symbol 0.1.0

Symbol system for Rust codebase - unique identifiers and file path management
Documentation
//! SymbolKind - Symbol type classification

use serde::{Deserialize, Serialize};

/// Symbol type classification
///
/// This enum classifies symbols for analysis and search purposes.
/// It extends AST-level item kinds with additional types for
/// variables, parameters, and fields (InSymbol).
///
/// # Design
///
/// | Layer | Kind Type | Responsibility |
/// |-------|-----------|----------------|
/// | AST (ryo-source) | ItemKind | Syntactic item classification (no Var) |
/// | Symbol (ryo-symbol) | SymbolKind | Analysis/search classification (includes Var) |
///
/// Conversion from `ItemKind` is done via `From` trait implemented
/// in the consuming crate (e.g., ryo-analysis), not here.
///
/// # InSymbol Extensions
///
/// | SymbolKind | VarScope | Path Example |
/// |------------|----------|--------------|
/// | Parameter | $param | `my_crate::my_fn::$param::x` |
/// | Variable | $var | `my_crate::my_fn::$var::result` |
/// | Field | $field | `my_crate::MyStruct::$field::name` |
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum SymbolKind {
    // === Item-derived (from AST ItemKind) ===
    /// Struct definition
    Struct,
    /// Enum definition
    Enum,
    /// Free function
    Function,
    /// Method (in impl block)
    Method,
    /// Trait definition
    Trait,
    /// Impl block
    Impl,
    /// Module
    Mod,
    /// Constant
    Const,
    /// Static variable
    Static,
    /// Type alias
    TypeAlias,
    /// Union type
    Union,
    /// Macro definition
    Macro,

    // === InSymbol extensions ===
    /// Local variable ($var)
    Variable,
    /// Function/method parameter ($param)
    Parameter,
    /// Struct/enum field ($field)
    Field,
    /// Tuple struct/enum field (indexed: 0, 1, 2...)
    TupleField,

    // === Enum variants ===
    /// Enum variant
    Variant,

    // === Import/Special ===
    /// Use statement (import)
    Use,
    /// Wildcard - matches any kind (for pattern matching)
    Any,
    /// Unknown or unsupported
    Other,
}

impl SymbolKind {
    /// Check if this is an InSymbol kind (variable, parameter, or field)
    pub fn is_in_symbol(&self) -> bool {
        matches!(
            self,
            SymbolKind::Variable
                | SymbolKind::Parameter
                | SymbolKind::Field
                | SymbolKind::TupleField
        )
    }

    /// Check if this is a type definition
    pub fn is_type(&self) -> bool {
        matches!(
            self,
            SymbolKind::Struct
                | SymbolKind::Enum
                | SymbolKind::Trait
                | SymbolKind::TypeAlias
                | SymbolKind::Union
        )
    }

    /// Check if this is callable
    pub fn is_callable(&self) -> bool {
        matches!(self, SymbolKind::Function | SymbolKind::Method)
    }

    /// Check if this is a value (const, static, field, variable, parameter)
    pub fn is_value(&self) -> bool {
        matches!(
            self,
            SymbolKind::Const
                | SymbolKind::Static
                | SymbolKind::Field
                | SymbolKind::TupleField
                | SymbolKind::Variable
                | SymbolKind::Parameter
        )
    }

    /// Get display name for this kind
    pub fn display_name(&self) -> &'static str {
        match self {
            SymbolKind::Struct => "struct",
            SymbolKind::Enum => "enum",
            SymbolKind::Function => "function",
            SymbolKind::Method => "method",
            SymbolKind::Trait => "trait",
            SymbolKind::Impl => "impl",
            SymbolKind::Mod => "module",
            SymbolKind::Const => "const",
            SymbolKind::Static => "static",
            SymbolKind::TypeAlias => "type alias",
            SymbolKind::Union => "union",
            SymbolKind::Macro => "macro",
            SymbolKind::Variable => "variable",
            SymbolKind::Parameter => "parameter",
            SymbolKind::Field => "field",
            SymbolKind::TupleField => "tuple field",
            SymbolKind::Variant => "variant",
            SymbolKind::Use => "use",
            SymbolKind::Any => "*",
            SymbolKind::Other => "other",
        }
    }

    /// Check if this is a wildcard that matches any kind
    pub fn is_any(&self) -> bool {
        matches!(self, SymbolKind::Any)
    }

    /// Returns true if this matches the given kind (considering Any as wildcard).
    pub fn matches(&self, other: &SymbolKind) -> bool {
        *self == SymbolKind::Any || *other == SymbolKind::Any || self == other
    }
}

impl std::fmt::Display for SymbolKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.display_name())
    }
}

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

    #[test]
    fn test_is_in_symbol() {
        assert!(SymbolKind::Variable.is_in_symbol());
        assert!(SymbolKind::Parameter.is_in_symbol());
        assert!(SymbolKind::Field.is_in_symbol());
        assert!(!SymbolKind::Function.is_in_symbol());
        assert!(!SymbolKind::Struct.is_in_symbol());
    }

    #[test]
    fn test_is_type() {
        assert!(SymbolKind::Struct.is_type());
        assert!(SymbolKind::Enum.is_type());
        assert!(SymbolKind::Trait.is_type());
        assert!(!SymbolKind::Function.is_type());
        assert!(!SymbolKind::Variable.is_type());
    }

    #[test]
    fn test_is_callable() {
        assert!(SymbolKind::Function.is_callable());
        assert!(SymbolKind::Method.is_callable());
        assert!(!SymbolKind::Struct.is_callable());
        assert!(!SymbolKind::Const.is_callable());
    }

    #[test]
    fn test_display_name() {
        assert_eq!(SymbolKind::Struct.display_name(), "struct");
        assert_eq!(SymbolKind::Function.display_name(), "function");
        assert_eq!(SymbolKind::Variable.display_name(), "variable");
    }
}