codeprism_lang_rust/
types.rs

1//! Types for Rust parser
2//!
3//! These types mirror the ones in codeprism_core::ast but are defined here to avoid
4//! circular dependencies. The parser returns these types which are then
5//! converted to codeprism types by the caller.
6
7use blake3::Hasher;
8use serde::{Deserialize, Serialize};
9use std::path::{Path, PathBuf};
10
11/// Unique identifier for AST nodes
12#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub struct NodeId([u8; 16]);
14
15impl NodeId {
16    /// Create a new NodeId from components
17    pub fn new(repo_id: &str, file_path: &Path, span: &Span, kind: &NodeKind) -> Self {
18        let mut hasher = Hasher::new();
19        hasher.update(repo_id.as_bytes());
20        hasher.update(file_path.to_string_lossy().as_bytes());
21        hasher.update(&span.start_byte.to_le_bytes());
22        hasher.update(&span.end_byte.to_le_bytes());
23        hasher.update(format!("{:?}", kind).as_bytes());
24
25        let hash = hasher.finalize();
26        let mut id = [0u8; 16];
27        id.copy_from_slice(&hash.as_bytes()[..16]);
28        Self(id)
29    }
30
31    /// Get the ID as a hex string
32    pub fn to_hex(&self) -> String {
33        hex::encode(self.0)
34    }
35}
36
37impl std::fmt::Debug for NodeId {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        write!(f, "NodeId({})", &self.to_hex()[..8])
40    }
41}
42
43/// Types of nodes in the Universal AST for Rust
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
45#[serde(rename_all = "snake_case")]
46pub enum NodeKind {
47    /// A module or file
48    Module,
49    /// A class definition (for compatibility)
50    Class,
51    /// A function definition
52    Function,
53    /// A method definition
54    Method,
55    /// A function/method parameter
56    Parameter,
57    /// A variable declaration
58    Variable,
59    /// A function/method call
60    Call,
61    /// An import statement
62    Import,
63    /// A literal value
64    Literal,
65    /// An HTTP route definition
66    Route,
67    /// A SQL query
68    SqlQuery,
69    /// An event emission
70    Event,
71
72    // Rust-specific node types
73    /// A trait definition
74    Trait,
75    /// An implementation block (impl)
76    Impl,
77    /// A struct definition
78    Struct,
79    /// An enum definition
80    Enum,
81    /// A module definition (mod)
82    Mod,
83    /// A macro definition or invocation
84    Macro,
85    /// A lifetime parameter
86    Lifetime,
87    /// A use statement (import)
88    Use,
89    /// A pub modifier (visibility)
90    Pub,
91    /// A const declaration
92    Const,
93    /// A static declaration
94    Static,
95    /// A type alias
96    TypeAlias,
97    /// A union definition
98    Union,
99    /// An associated type
100    AssociatedType,
101    /// An associated const
102    AssociatedConst,
103    /// A field in a struct/enum
104    Field,
105    /// An enum variant
106    Variant,
107    /// An attribute
108    Attribute,
109
110    /// Unknown node type
111    Unknown,
112}
113
114/// Types of edges between nodes for Rust
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
116#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
117pub enum EdgeKind {
118    /// Function/method call
119    Calls,
120    /// Variable/field read
121    Reads,
122    /// Variable/field write
123    Writes,
124    /// Module import
125    Imports,
126    /// Event emission
127    Emits,
128    /// HTTP route mapping
129    RoutesTo,
130    /// Exception raising
131    Raises,
132    /// Type inheritance
133    Extends,
134    /// Interface implementation (generic)
135    Implements,
136
137    // Rust-specific edge types
138    /// Trait implementation (for a type)
139    ImplementsTrait,
140    /// Use statement relationship
141    Uses,
142    /// Derive attribute relationship
143    Derives,
144    /// Generic constraint relationship
145    Constrains,
146    /// Ownership transfer
147    Owns,
148    /// Borrowing relationship
149    Borrows,
150    /// Mutable borrowing
151    BorrowsMut,
152    /// Lifetime constraint
153    Outlives,
154    /// Type parameter bound
155    Bounds,
156    /// Associated type binding
157    Binds,
158    /// Macro expansion
159    Expands,
160    /// Module containment
161    Contains,
162}
163
164/// Source code location
165#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
166pub struct Span {
167    /// Starting byte offset
168    pub start_byte: usize,
169    /// Ending byte offset (exclusive)
170    pub end_byte: usize,
171    /// Starting line (1-indexed)
172    pub start_line: usize,
173    /// Ending line (1-indexed)
174    pub end_line: usize,
175    /// Starting column (1-indexed)
176    pub start_column: usize,
177    /// Ending column (1-indexed)
178    pub end_column: usize,
179}
180
181impl Span {
182    /// Create a new span
183    pub fn new(
184        start_byte: usize,
185        end_byte: usize,
186        start_line: usize,
187        end_line: usize,
188        start_column: usize,
189        end_column: usize,
190    ) -> Self {
191        Self {
192            start_byte,
193            end_byte,
194            start_line,
195            end_line,
196            start_column,
197            end_column,
198        }
199    }
200
201    /// Create a span from tree-sitter node
202    pub fn from_node(node: &tree_sitter::Node) -> Self {
203        let start_pos = node.start_position();
204        let end_pos = node.end_position();
205
206        Self {
207            start_byte: node.start_byte(),
208            end_byte: node.end_byte(),
209            start_line: start_pos.row + 1, // tree-sitter uses 0-indexed
210            end_line: end_pos.row + 1,
211            start_column: start_pos.column + 1,
212            end_column: end_pos.column + 1,
213        }
214    }
215}
216
217/// Programming language
218#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
219#[serde(rename_all = "lowercase")]
220pub enum Language {
221    /// Rust
222    Rust,
223    /// Python (for compatibility)
224    Python,
225}
226
227/// A node in the Universal AST
228#[derive(Debug, Clone, Serialize, Deserialize)]
229pub struct Node {
230    /// Unique identifier
231    pub id: NodeId,
232    /// Node type
233    pub kind: NodeKind,
234    /// Node name (e.g., function name)
235    pub name: String,
236    /// Programming language
237    pub lang: Language,
238    /// Source file path
239    pub file: PathBuf,
240    /// Source location
241    pub span: Span,
242    /// Optional type signature
243    pub signature: Option<String>,
244    /// Additional metadata (Rust-specific info like visibility, mutability, etc.)
245    pub metadata: serde_json::Value,
246}
247
248impl Node {
249    /// Create a new node
250    pub fn new(
251        repo_id: &str,
252        kind: NodeKind,
253        name: String,
254        lang: Language,
255        file: PathBuf,
256        span: Span,
257    ) -> Self {
258        let id = NodeId::new(repo_id, &file, &span, &kind);
259        Self {
260            id,
261            kind,
262            name,
263            lang,
264            file,
265            span,
266            signature: None,
267            metadata: serde_json::Value::Null,
268        }
269    }
270
271    /// Set metadata for the node
272    pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
273        self.metadata = metadata;
274        self
275    }
276
277    /// Set signature for the node
278    pub fn with_signature(mut self, signature: String) -> Self {
279        self.signature = Some(signature);
280        self
281    }
282}
283
284/// An edge between nodes
285#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
286pub struct Edge {
287    /// Source node ID
288    pub source: NodeId,
289    /// Target node ID
290    pub target: NodeId,
291    /// Edge type
292    pub kind: EdgeKind,
293}
294
295impl Edge {
296    /// Create a new edge
297    pub fn new(source: NodeId, target: NodeId, kind: EdgeKind) -> Self {
298        Self {
299            source,
300            target,
301            kind,
302        }
303    }
304}