ryo-source 0.1.0

High-speed Rust AST manipulation engine
Documentation
//! ItemKind - Shared vocabulary for AST item types.
//!
//! This is the canonical definition of item kinds used across the ryo ecosystem.
//! All crates should use this definition instead of creating their own.

/// Kind of AST item (shared vocabulary across crates).
///
/// This enum represents the type of an AST item and is used for:
/// - Item-level conflict detection in parallel execution
/// - Intent extraction and pattern matching
/// - Spec directives and documentation
///
/// # Design
///
/// - Top-level items: items that can appear at module level
/// - Nested items: items that appear inside other items (methods in impl, fields in struct)
/// - Wildcard: for pattern matching any kind
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum ItemKind {
    // ========== Top-level items ==========
    /// Function definition (`fn foo() {}`)
    Function,
    /// Struct definition (`struct Foo {}`)
    Struct,
    /// Enum definition (`enum Foo {}`)
    Enum,
    /// Trait definition (`trait Foo {}`)
    Trait,
    /// Impl block (`impl Foo {}` or `impl Trait for Foo {}`)
    Impl,
    /// Type alias (`type Foo = Bar;`)
    TypeAlias,
    /// Const item (`const FOO: i32 = 1;`)
    Const,
    /// Static item (`static FOO: i32 = 1;`)
    Static,
    /// Module (`mod foo;` or `mod foo {}`)
    Mod,
    /// Use statement (`use std::io;`)
    Use,
    /// Macro invocation at item level (`macro_rules!` or `foo!()`)
    Macro,

    // ========== Nested items ==========
    /// Method inside an impl or trait block
    Method,
    /// Field in a struct or enum variant
    Field,
    /// Variant in an enum
    Variant,

    // ========== Variable-level items ==========
    /// Local variable (`let x = ...`)
    LocalVar,
    /// Function parameter
    Parameter,
    /// Tuple struct/enum field (indexed by number: 0, 1, 2...)
    TupleField,

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

impl ItemKind {
    /// Returns the string representation of this kind.
    pub fn as_str(&self) -> &'static str {
        match self {
            ItemKind::Function => "fn",
            ItemKind::Struct => "struct",
            ItemKind::Enum => "enum",
            ItemKind::Trait => "trait",
            ItemKind::Impl => "impl",
            ItemKind::TypeAlias => "type",
            ItemKind::Const => "const",
            ItemKind::Static => "static",
            ItemKind::Mod => "mod",
            ItemKind::Use => "use",
            ItemKind::Macro => "macro",
            ItemKind::Method => "method",
            ItemKind::Field => "field",
            ItemKind::Variant => "variant",
            ItemKind::LocalVar => "var",
            ItemKind::Parameter => "param",
            ItemKind::TupleField => "tuple_field",
            ItemKind::Any => "*",
            ItemKind::Other => "other",
        }
    }

    /// Returns true if this is a top-level item (can appear at module level).
    pub fn is_top_level(&self) -> bool {
        matches!(
            self,
            ItemKind::Function
                | ItemKind::Struct
                | ItemKind::Enum
                | ItemKind::Trait
                | ItemKind::Impl
                | ItemKind::TypeAlias
                | ItemKind::Const
                | ItemKind::Static
                | ItemKind::Mod
                | ItemKind::Use
                | ItemKind::Macro
        )
    }

    /// Returns true if this is a nested item (appears inside another item).
    pub fn is_nested(&self) -> bool {
        matches!(
            self,
            ItemKind::Method | ItemKind::Field | ItemKind::Variant | ItemKind::TupleField
        )
    }

    /// Returns true if this is a variable-level item (local scope).
    pub fn is_variable(&self) -> bool {
        matches!(self, ItemKind::LocalVar | ItemKind::Parameter)
    }

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

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

impl From<&super::PureItem> for ItemKind {
    fn from(item: &super::PureItem) -> Self {
        match item {
            super::PureItem::Use(_) => ItemKind::Use,
            super::PureItem::Fn(_) => ItemKind::Function,
            super::PureItem::Struct(_) => ItemKind::Struct,
            super::PureItem::Enum(_) => ItemKind::Enum,
            super::PureItem::Impl(_) => ItemKind::Impl,
            super::PureItem::Const(_) => ItemKind::Const,
            super::PureItem::Static(_) => ItemKind::Static,
            super::PureItem::Type(_) => ItemKind::TypeAlias,
            super::PureItem::Mod(_) => ItemKind::Mod,
            super::PureItem::Trait(_) => ItemKind::Trait,
            super::PureItem::Macro(_) => ItemKind::Macro,
            super::PureItem::Other(_) => ItemKind::Other,
        }
    }
}

impl From<super::PureSymbolKind> for ItemKind {
    fn from(kind: super::PureSymbolKind) -> Self {
        match kind {
            super::PureSymbolKind::Function => ItemKind::Function,
            super::PureSymbolKind::Struct => ItemKind::Struct,
            super::PureSymbolKind::Enum => ItemKind::Enum,
            super::PureSymbolKind::Trait => ItemKind::Trait,
            super::PureSymbolKind::TypeAlias => ItemKind::TypeAlias,
            super::PureSymbolKind::Const => ItemKind::Const,
            super::PureSymbolKind::Static => ItemKind::Static,
            super::PureSymbolKind::Module => ItemKind::Mod,
            super::PureSymbolKind::Impl => ItemKind::Impl,
            super::PureSymbolKind::LocalVar => ItemKind::LocalVar,
            super::PureSymbolKind::Parameter => ItemKind::Parameter,
        }
    }
}

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

    #[test]
    fn test_as_str() {
        assert_eq!(ItemKind::Function.as_str(), "fn");
        assert_eq!(ItemKind::Struct.as_str(), "struct");
        assert_eq!(ItemKind::Method.as_str(), "method");
    }

    #[test]
    fn test_is_top_level() {
        assert!(ItemKind::Function.is_top_level());
        assert!(ItemKind::Struct.is_top_level());
        assert!(!ItemKind::Method.is_top_level());
        assert!(!ItemKind::Field.is_top_level());
    }

    #[test]
    fn test_is_nested() {
        assert!(!ItemKind::Function.is_nested());
        assert!(ItemKind::Method.is_nested());
        assert!(ItemKind::Field.is_nested());
        assert!(ItemKind::Variant.is_nested());
        assert!(ItemKind::TupleField.is_nested());
    }

    #[test]
    fn test_is_variable() {
        assert!(ItemKind::LocalVar.is_variable());
        assert!(ItemKind::Parameter.is_variable());
        assert!(!ItemKind::Function.is_variable());
        assert!(!ItemKind::Field.is_variable());
    }

    #[test]
    fn test_matches_wildcard() {
        assert!(ItemKind::Any.matches(&ItemKind::Function));
        assert!(ItemKind::Function.matches(&ItemKind::Any));
        assert!(ItemKind::Function.matches(&ItemKind::Function));
        assert!(!ItemKind::Function.matches(&ItemKind::Struct));
    }

    #[test]
    fn test_display() {
        assert_eq!(format!("{}", ItemKind::Function), "fn");
        assert_eq!(format!("{}", ItemKind::Struct), "struct");
    }
}