Skip to main content

ryo_symbol/
kind.rs

1//! SymbolKind - Symbol type classification
2
3use serde::{Deserialize, Serialize};
4
5/// Symbol type classification
6///
7/// This enum classifies symbols for analysis and search purposes.
8/// It extends AST-level item kinds with additional types for
9/// variables, parameters, and fields (InSymbol).
10///
11/// # Design
12///
13/// | Layer | Kind Type | Responsibility |
14/// |-------|-----------|----------------|
15/// | AST (ryo-source) | ItemKind | Syntactic item classification (no Var) |
16/// | Symbol (ryo-symbol) | SymbolKind | Analysis/search classification (includes Var) |
17///
18/// Conversion from `ItemKind` is done via `From` trait implemented
19/// in the consuming crate (e.g., ryo-analysis), not here.
20///
21/// # InSymbol Extensions
22///
23/// | SymbolKind | VarScope | Path Example |
24/// |------------|----------|--------------|
25/// | Parameter | $param | `my_crate::my_fn::$param::x` |
26/// | Variable | $var | `my_crate::my_fn::$var::result` |
27/// | Field | $field | `my_crate::MyStruct::$field::name` |
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
29pub enum SymbolKind {
30    // === Item-derived (from AST ItemKind) ===
31    /// Struct definition
32    Struct,
33    /// Enum definition
34    Enum,
35    /// Free function
36    Function,
37    /// Method (in impl block)
38    Method,
39    /// Trait definition
40    Trait,
41    /// Impl block
42    Impl,
43    /// Module
44    Mod,
45    /// Constant
46    Const,
47    /// Static variable
48    Static,
49    /// Type alias
50    TypeAlias,
51    /// Union type
52    Union,
53    /// Macro definition
54    Macro,
55
56    // === InSymbol extensions ===
57    /// Local variable ($var)
58    Variable,
59    /// Function/method parameter ($param)
60    Parameter,
61    /// Struct/enum field ($field)
62    Field,
63    /// Tuple struct/enum field (indexed: 0, 1, 2...)
64    TupleField,
65
66    // === Enum variants ===
67    /// Enum variant
68    Variant,
69
70    // === Import/Special ===
71    /// Use statement (import)
72    Use,
73    /// Wildcard - matches any kind (for pattern matching)
74    Any,
75    /// Unknown or unsupported
76    Other,
77}
78
79impl SymbolKind {
80    /// Check if this is an InSymbol kind (variable, parameter, or field)
81    pub fn is_in_symbol(&self) -> bool {
82        matches!(
83            self,
84            SymbolKind::Variable
85                | SymbolKind::Parameter
86                | SymbolKind::Field
87                | SymbolKind::TupleField
88        )
89    }
90
91    /// Check if this is a type definition
92    pub fn is_type(&self) -> bool {
93        matches!(
94            self,
95            SymbolKind::Struct
96                | SymbolKind::Enum
97                | SymbolKind::Trait
98                | SymbolKind::TypeAlias
99                | SymbolKind::Union
100        )
101    }
102
103    /// Check if this is callable
104    pub fn is_callable(&self) -> bool {
105        matches!(self, SymbolKind::Function | SymbolKind::Method)
106    }
107
108    /// Check if this is a value (const, static, field, variable, parameter)
109    pub fn is_value(&self) -> bool {
110        matches!(
111            self,
112            SymbolKind::Const
113                | SymbolKind::Static
114                | SymbolKind::Field
115                | SymbolKind::TupleField
116                | SymbolKind::Variable
117                | SymbolKind::Parameter
118        )
119    }
120
121    /// Get display name for this kind
122    pub fn display_name(&self) -> &'static str {
123        match self {
124            SymbolKind::Struct => "struct",
125            SymbolKind::Enum => "enum",
126            SymbolKind::Function => "function",
127            SymbolKind::Method => "method",
128            SymbolKind::Trait => "trait",
129            SymbolKind::Impl => "impl",
130            SymbolKind::Mod => "module",
131            SymbolKind::Const => "const",
132            SymbolKind::Static => "static",
133            SymbolKind::TypeAlias => "type alias",
134            SymbolKind::Union => "union",
135            SymbolKind::Macro => "macro",
136            SymbolKind::Variable => "variable",
137            SymbolKind::Parameter => "parameter",
138            SymbolKind::Field => "field",
139            SymbolKind::TupleField => "tuple field",
140            SymbolKind::Variant => "variant",
141            SymbolKind::Use => "use",
142            SymbolKind::Any => "*",
143            SymbolKind::Other => "other",
144        }
145    }
146
147    /// Check if this is a wildcard that matches any kind
148    pub fn is_any(&self) -> bool {
149        matches!(self, SymbolKind::Any)
150    }
151
152    /// Returns true if this matches the given kind (considering Any as wildcard).
153    pub fn matches(&self, other: &SymbolKind) -> bool {
154        *self == SymbolKind::Any || *other == SymbolKind::Any || self == other
155    }
156}
157
158impl std::fmt::Display for SymbolKind {
159    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160        write!(f, "{}", self.display_name())
161    }
162}
163
164#[cfg(test)]
165mod tests {
166    use super::*;
167
168    #[test]
169    fn test_is_in_symbol() {
170        assert!(SymbolKind::Variable.is_in_symbol());
171        assert!(SymbolKind::Parameter.is_in_symbol());
172        assert!(SymbolKind::Field.is_in_symbol());
173        assert!(!SymbolKind::Function.is_in_symbol());
174        assert!(!SymbolKind::Struct.is_in_symbol());
175    }
176
177    #[test]
178    fn test_is_type() {
179        assert!(SymbolKind::Struct.is_type());
180        assert!(SymbolKind::Enum.is_type());
181        assert!(SymbolKind::Trait.is_type());
182        assert!(!SymbolKind::Function.is_type());
183        assert!(!SymbolKind::Variable.is_type());
184    }
185
186    #[test]
187    fn test_is_callable() {
188        assert!(SymbolKind::Function.is_callable());
189        assert!(SymbolKind::Method.is_callable());
190        assert!(!SymbolKind::Struct.is_callable());
191        assert!(!SymbolKind::Const.is_callable());
192    }
193
194    #[test]
195    fn test_display_name() {
196        assert_eq!(SymbolKind::Struct.display_name(), "struct");
197        assert_eq!(SymbolKind::Function.display_name(), "function");
198        assert_eq!(SymbolKind::Variable.display_name(), "variable");
199    }
200}