ricecoder_research/
models.rs

1//! Data models for the research system
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use std::path::PathBuf;
6
7// ============================================================================
8// Project Analysis Models
9// ============================================================================
10
11/// Complete context about a project
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ProjectContext {
14    /// Type of project (library, application, service, etc.)
15    pub project_type: ProjectType,
16    /// Languages detected in the project
17    pub languages: Vec<Language>,
18    /// Frameworks detected in the project
19    pub frameworks: Vec<Framework>,
20    /// Project structure information
21    pub structure: ProjectStructure,
22    /// Detected patterns in the codebase
23    pub patterns: Vec<DetectedPattern>,
24    /// Project dependencies
25    pub dependencies: Vec<Dependency>,
26    /// Architectural intent and decisions
27    pub architectural_intent: ArchitecturalIntent,
28    /// Detected standards and conventions
29    pub standards: StandardsProfile,
30}
31
32/// Type of project
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
34pub enum ProjectType {
35    /// Library crate/package
36    Library,
37    /// Application/binary
38    Application,
39    /// Microservice
40    Service,
41    /// Monorepo with multiple packages
42    Monorepo,
43    /// Unknown project type
44    Unknown,
45}
46
47/// Programming language
48#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
49pub enum Language {
50    /// Rust
51    Rust,
52    /// TypeScript/JavaScript
53    TypeScript,
54    /// Python
55    Python,
56    /// Go
57    Go,
58    /// Java
59    Java,
60    /// Kotlin
61    Kotlin,
62    /// C#/.NET
63    CSharp,
64    /// PHP
65    Php,
66    /// Ruby
67    Ruby,
68    /// Swift
69    Swift,
70    /// Dart
71    Dart,
72    /// Other language
73    Other(String),
74}
75
76/// Framework or library
77#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
78pub struct Framework {
79    /// Framework name
80    pub name: String,
81    /// Framework version
82    pub version: Option<String>,
83}
84
85/// Project structure information
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct ProjectStructure {
88    /// Root directory of the project
89    pub root: PathBuf,
90    /// Source directories
91    pub source_dirs: Vec<PathBuf>,
92    /// Test directories
93    pub test_dirs: Vec<PathBuf>,
94    /// Configuration files
95    pub config_files: Vec<PathBuf>,
96    /// Entry points (main.rs, index.js, etc.)
97    pub entry_points: Vec<PathBuf>,
98}
99
100/// Detected pattern in the codebase
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct DetectedPattern {
103    /// Pattern name
104    pub name: String,
105    /// Pattern category
106    pub category: PatternCategory,
107    /// Confidence score (0.0 to 1.0)
108    pub confidence: f32,
109    /// Locations where pattern was detected
110    pub locations: Vec<PathBuf>,
111    /// Pattern description
112    pub description: String,
113}
114
115/// Category of detected pattern
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
117pub enum PatternCategory {
118    /// Architectural pattern
119    Architectural,
120    /// Design pattern
121    Design,
122    /// Coding idiom
123    Coding,
124    /// Testing pattern
125    Testing,
126    /// Configuration pattern
127    Configuration,
128}
129
130/// Project dependency
131#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct Dependency {
133    /// Dependency name
134    pub name: String,
135    /// Dependency version
136    pub version: String,
137    /// Version constraints (e.g., "^1.0", "~2.1")
138    pub constraints: Option<String>,
139    /// Whether this is a dev dependency
140    pub is_dev: bool,
141}
142
143// ============================================================================
144// Architectural Intent Models
145// ============================================================================
146
147/// Architectural intent and decisions
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct ArchitecturalIntent {
150    /// Detected architectural style
151    pub style: ArchitecturalStyle,
152    /// Architectural principles
153    pub principles: Vec<String>,
154    /// Architectural constraints
155    pub constraints: Vec<String>,
156    /// Architectural decisions
157    pub decisions: Vec<ArchitecturalDecision>,
158}
159
160/// Architectural style
161#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
162pub enum ArchitecturalStyle {
163    /// Layered architecture
164    Layered,
165    /// Microservices architecture
166    Microservices,
167    /// Event-driven architecture
168    EventDriven,
169    /// Monolithic architecture
170    Monolithic,
171    /// Serverless architecture
172    Serverless,
173    /// Unknown architecture
174    Unknown,
175}
176
177/// Architectural decision record
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct ArchitecturalDecision {
180    /// Decision ID
181    pub id: String,
182    /// Decision title
183    pub title: String,
184    /// Context for the decision
185    pub context: String,
186    /// The decision itself
187    pub decision: String,
188    /// Consequences of the decision
189    pub consequences: Vec<String>,
190    /// Date the decision was made
191    pub date: DateTime<Utc>,
192}
193
194// ============================================================================
195// Code Context Models
196// ============================================================================
197
198/// Code context for AI providers
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct CodeContext {
201    /// Files included in the context
202    pub files: Vec<FileContext>,
203    /// Symbols in the context
204    pub symbols: Vec<Symbol>,
205    /// Symbol references
206    pub references: Vec<SymbolReference>,
207    /// Total tokens in the context
208    pub total_tokens: usize,
209}
210
211/// File context information
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct FileContext {
214    /// File path
215    pub path: PathBuf,
216    /// Relevance score (0.0 to 1.0)
217    pub relevance: f32,
218    /// Summary of the file
219    pub summary: Option<String>,
220    /// File content (may be truncated)
221    pub content: Option<String>,
222}
223
224/// Code symbol (function, class, type, etc.)
225#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
226pub struct Symbol {
227    /// Unique symbol ID
228    pub id: String,
229    /// Symbol name
230    pub name: String,
231    /// Symbol kind
232    pub kind: SymbolKind,
233    /// File containing the symbol
234    pub file: PathBuf,
235    /// Line number (1-indexed)
236    pub line: usize,
237    /// Column number (1-indexed)
238    pub column: usize,
239    /// References to this symbol
240    pub references: Vec<SymbolReference>,
241}
242
243/// Kind of symbol
244#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
245pub enum SymbolKind {
246    /// Function or method
247    Function,
248    /// Class or struct
249    Class,
250    /// Type alias or type definition
251    Type,
252    /// Constant
253    Constant,
254    /// Variable
255    Variable,
256    /// Module or namespace
257    Module,
258    /// Trait or interface
259    Trait,
260    /// Enum
261    Enum,
262}
263
264/// Reference to a symbol
265#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
266pub struct SymbolReference {
267    /// ID of the referenced symbol
268    pub symbol_id: String,
269    /// File containing the reference
270    pub file: PathBuf,
271    /// Line number of the reference
272    pub line: usize,
273    /// Kind of reference
274    pub kind: ReferenceKind,
275}
276
277/// Kind of symbol reference
278#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
279pub enum ReferenceKind {
280    /// Symbol definition
281    Definition,
282    /// Symbol usage
283    Usage,
284    /// Import statement
285    Import,
286    /// Export statement
287    Export,
288}
289
290/// Search result for semantic search
291#[derive(Debug, Clone, Serialize, Deserialize)]
292pub struct SearchResult {
293    /// Symbol found
294    pub symbol: Symbol,
295    /// Relevance score (0.0 to 1.0)
296    pub relevance: f32,
297    /// Context around the symbol
298    pub context: Option<String>,
299}
300
301// ============================================================================
302// Standards Detection Models
303// ============================================================================
304
305/// Detected standards and conventions
306#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
307pub struct StandardsProfile {
308    /// Naming conventions
309    pub naming_conventions: NamingConventions,
310    /// Formatting style
311    pub formatting_style: FormattingStyle,
312    /// Import organization
313    pub import_organization: ImportOrganization,
314    /// Documentation style
315    pub documentation_style: DocumentationStyle,
316}
317
318impl Default for NamingConventions {
319    fn default() -> Self {
320        NamingConventions {
321            function_case: CaseStyle::SnakeCase,
322            variable_case: CaseStyle::SnakeCase,
323            class_case: CaseStyle::PascalCase,
324            constant_case: CaseStyle::UpperCase,
325        }
326    }
327}
328
329impl Default for FormattingStyle {
330    fn default() -> Self {
331        FormattingStyle {
332            indent_size: 4,
333            indent_type: IndentType::Spaces,
334            line_length: 100,
335        }
336    }
337}
338
339impl Default for ImportOrganization {
340    fn default() -> Self {
341        ImportOrganization {
342            order: vec![
343                ImportGroup::Standard,
344                ImportGroup::External,
345                ImportGroup::Internal,
346            ],
347            sort_within_group: true,
348        }
349    }
350}
351
352impl Default for DocumentationStyle {
353    fn default() -> Self {
354        DocumentationStyle {
355            format: DocFormat::RustDoc,
356            required_for_public: true,
357        }
358    }
359}
360
361/// Naming conventions
362#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
363pub struct NamingConventions {
364    /// Function naming case style
365    pub function_case: CaseStyle,
366    /// Variable naming case style
367    pub variable_case: CaseStyle,
368    /// Class/type naming case style
369    pub class_case: CaseStyle,
370    /// Constant naming case style
371    pub constant_case: CaseStyle,
372}
373
374/// Case style for naming
375#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
376pub enum CaseStyle {
377    /// camelCase
378    CamelCase,
379    /// snake_case
380    SnakeCase,
381    /// PascalCase
382    PascalCase,
383    /// kebab-case
384    KebabCase,
385    /// UPPER_CASE
386    UpperCase,
387    /// Mixed case styles
388    Mixed,
389}
390
391/// Formatting style
392#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
393pub struct FormattingStyle {
394    /// Indentation size in spaces
395    pub indent_size: usize,
396    /// Indentation type
397    pub indent_type: IndentType,
398    /// Preferred line length
399    pub line_length: usize,
400}
401
402/// Indentation type
403#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
404pub enum IndentType {
405    /// Spaces for indentation
406    Spaces,
407    /// Tabs for indentation
408    Tabs,
409}
410
411/// Import organization
412#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
413pub struct ImportOrganization {
414    /// Order of import groups
415    pub order: Vec<ImportGroup>,
416    /// Whether to sort within groups
417    pub sort_within_group: bool,
418}
419
420/// Import group
421#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
422pub enum ImportGroup {
423    /// Standard library imports
424    Standard,
425    /// External/third-party imports
426    External,
427    /// Internal project imports
428    Internal,
429    /// Relative imports
430    Relative,
431}
432
433/// Documentation style
434#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
435pub struct DocumentationStyle {
436    /// Documentation format
437    pub format: DocFormat,
438    /// Whether documentation is required for public items
439    pub required_for_public: bool,
440}
441
442/// Documentation format
443#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
444pub enum DocFormat {
445    /// JavaDoc style (/** ... */)
446    JavaDoc,
447    /// RustDoc style (/// ...)
448    RustDoc,
449    /// JSDoc style (/** ... */)
450    JSDoc,
451    /// Python docstring style (""" ... """)
452    PythonDoc,
453}
454
455#[cfg(test)]
456mod tests {
457    use super::*;
458
459    #[test]
460    fn test_project_type_serialization() {
461        let project_type = ProjectType::Library;
462        let json = serde_json::to_string(&project_type).unwrap();
463        let deserialized: ProjectType = serde_json::from_str(&json).unwrap();
464        assert_eq!(project_type, deserialized);
465    }
466
467    #[test]
468    fn test_language_serialization() {
469        let language = Language::Rust;
470        let json = serde_json::to_string(&language).unwrap();
471        let deserialized: Language = serde_json::from_str(&json).unwrap();
472        assert_eq!(language, deserialized);
473    }
474
475    #[test]
476    fn test_symbol_kind_serialization() {
477        let kind = SymbolKind::Function;
478        let json = serde_json::to_string(&kind).unwrap();
479        let deserialized: SymbolKind = serde_json::from_str(&json).unwrap();
480        assert_eq!(kind, deserialized);
481    }
482
483    #[test]
484    fn test_case_style_serialization() {
485        let style = CaseStyle::SnakeCase;
486        let json = serde_json::to_string(&style).unwrap();
487        let deserialized: CaseStyle = serde_json::from_str(&json).unwrap();
488        assert_eq!(style, deserialized);
489    }
490
491    #[test]
492    fn test_project_context_creation() {
493        let context = ProjectContext {
494            project_type: ProjectType::Library,
495            languages: vec![Language::Rust],
496            frameworks: vec![],
497            structure: ProjectStructure {
498                root: PathBuf::from("/project"),
499                source_dirs: vec![PathBuf::from("/project/src")],
500                test_dirs: vec![PathBuf::from("/project/tests")],
501                config_files: vec![PathBuf::from("/project/Cargo.toml")],
502                entry_points: vec![],
503            },
504            patterns: vec![],
505            dependencies: vec![],
506            architectural_intent: ArchitecturalIntent {
507                style: ArchitecturalStyle::Layered,
508                principles: vec![],
509                constraints: vec![],
510                decisions: vec![],
511            },
512            standards: StandardsProfile {
513                naming_conventions: NamingConventions {
514                    function_case: CaseStyle::SnakeCase,
515                    variable_case: CaseStyle::SnakeCase,
516                    class_case: CaseStyle::PascalCase,
517                    constant_case: CaseStyle::UpperCase,
518                },
519                formatting_style: FormattingStyle {
520                    indent_size: 4,
521                    indent_type: IndentType::Spaces,
522                    line_length: 100,
523                },
524                import_organization: ImportOrganization {
525                    order: vec![
526                        ImportGroup::Standard,
527                        ImportGroup::External,
528                        ImportGroup::Internal,
529                    ],
530                    sort_within_group: true,
531                },
532                documentation_style: DocumentationStyle {
533                    format: DocFormat::RustDoc,
534                    required_for_public: true,
535                },
536            },
537        };
538
539        assert_eq!(context.project_type, ProjectType::Library);
540        assert_eq!(context.languages.len(), 1);
541    }
542}