Skip to main content

gitcortex_core/
schema.rs

1use serde::{Deserialize, Serialize};
2
3/// Bumped whenever the on-disk graph schema changes.
4/// Stores compare this against the persisted version and re-index on mismatch.
5pub const SCHEMA_VERSION: u32 = 3;
6
7/// Every named, referenceable syntactic entity becomes a node of one of these kinds.
8#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
9#[serde(rename_all = "snake_case")]
10pub enum NodeKind {
11    Folder,
12    File,
13    Module,
14    Struct,
15    Enum,
16    /// Rust trait. Languages with a separate notion of interface use [`NodeKind::Interface`].
17    Trait,
18    /// Language interface (Java, TypeScript, Go) — semantically distinct from Rust traits.
19    Interface,
20    TypeAlias,
21    Function,
22    Method,
23    /// Property (Python `@property`, TypeScript `readonly` field, getter/setter pair).
24    Property,
25    Constant,
26    Macro,
27    /// Decorator / annotation declaration (e.g. `@dataclass`, `@Override`, `#[derive(...)]`).
28    Annotation,
29    /// Member of an enum (`Color::Red`, `Direction.NORTH`).
30    EnumMember,
31}
32
33impl std::fmt::Display for NodeKind {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        let s = match self {
36            NodeKind::Folder => "folder",
37            NodeKind::File => "file",
38            NodeKind::Module => "module",
39            NodeKind::Struct => "struct",
40            NodeKind::Enum => "enum",
41            NodeKind::Trait => "trait",
42            NodeKind::Interface => "interface",
43            NodeKind::TypeAlias => "type_alias",
44            NodeKind::Function => "function",
45            NodeKind::Method => "method",
46            NodeKind::Property => "property",
47            NodeKind::Constant => "constant",
48            NodeKind::Macro => "macro",
49            NodeKind::Annotation => "annotation",
50            NodeKind::EnumMember => "enum_member",
51        };
52        f.write_str(s)
53    }
54}
55
56/// Directed relationship between two nodes.
57#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
58#[serde(rename_all = "snake_case")]
59pub enum EdgeKind {
60    /// Parent–child containment: File→Module, Module→Struct, Struct→Method.
61    Contains,
62    /// Resolved call site: Function→Function or Method→Method.
63    Calls,
64    /// `impl Trait for Struct`, `class Foo implements Bar` — Struct→Trait/Interface.
65    Implements,
66    /// `class Foo extends Bar`, embedded struct in Go — subtype→supertype.
67    /// Distinct from `Implements`: this is "is-a" inheritance vs "can-do" interface
68    /// satisfaction.
69    Inherits,
70    /// A type appears as a parameter or return type: fn→Struct/Trait.
71    Uses,
72    /// `use path::to::Thing` import.
73    Imports,
74    /// A symbol is decorated/annotated by another (`@Override`, `@dataclass`,
75    /// `#[derive(Debug)]`).
76    Annotated,
77    /// Java `throws ExceptionType` — method→exception class.
78    Throws,
79}
80
81impl std::fmt::Display for EdgeKind {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        let s = match self {
84            EdgeKind::Contains => "contains",
85            EdgeKind::Calls => "calls",
86            EdgeKind::Implements => "implements",
87            EdgeKind::Inherits => "inherits",
88            EdgeKind::Uses => "uses",
89            EdgeKind::Imports => "imports",
90            EdgeKind::Annotated => "annotated",
91            EdgeKind::Throws => "throws",
92        };
93        f.write_str(s)
94    }
95}
96
97/// Symbol visibility in the source language.
98#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
99#[serde(rename_all = "snake_case")]
100pub enum Visibility {
101    #[default]
102    Private,
103    PubCrate,
104    Pub,
105}
106
107impl std::fmt::Display for Visibility {
108    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109        match self {
110            Visibility::Pub => f.write_str("pub"),
111            Visibility::PubCrate => f.write_str("pub_crate"),
112            Visibility::Private => f.write_str("private"),
113        }
114    }
115}
116
117// ── LLD labels ──────────────────────────────────────────────────────────────
118
119/// Which SOLID principle a node may be violating (populated in pass 2).
120#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
121#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
122pub enum SolidHint {
123    /// Too many responsibilities in one type.
124    Srp,
125    /// Logic closed for extension but open for modification.
126    Ocp,
127    /// Subtype breaks contract of supertype.
128    Lsp,
129    /// Interface has too many unrelated methods.
130    Isp,
131    /// Depends on concrete type instead of abstraction.
132    Dip,
133}
134
135/// Common design patterns detectable syntactically.
136#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
137#[serde(rename_all = "snake_case")]
138pub enum DesignPattern {
139    Builder,
140    Factory,
141    Observer,
142    Strategy,
143    Decorator,
144    Singleton,
145    Repository,
146}
147
148/// Code quality smells detectable without full type resolution.
149#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
150#[serde(rename_all = "snake_case")]
151pub enum CodeSmell {
152    /// Struct with too many methods or dependencies.
153    GodStruct,
154    /// Function body too long.
155    LongMethod,
156    /// Nesting depth exceeds threshold.
157    DeepNesting,
158    /// Trait with too many methods.
159    FatInterface,
160}