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 = 12;
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    /// A Markdown heading section (`## Installation`). File-level prose lives
32    /// directly on the synthesized `File` node; this kind only covers headings.
33    Section,
34}
35
36impl std::fmt::Display for NodeKind {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        let s = match self {
39            NodeKind::Folder => "folder",
40            NodeKind::File => "file",
41            NodeKind::Module => "module",
42            NodeKind::Struct => "struct",
43            NodeKind::Enum => "enum",
44            NodeKind::Trait => "trait",
45            NodeKind::Interface => "interface",
46            NodeKind::TypeAlias => "type_alias",
47            NodeKind::Function => "function",
48            NodeKind::Method => "method",
49            NodeKind::Property => "property",
50            NodeKind::Constant => "constant",
51            NodeKind::Macro => "macro",
52            NodeKind::Annotation => "annotation",
53            NodeKind::EnumMember => "enum_member",
54            NodeKind::Section => "section",
55        };
56        f.write_str(s)
57    }
58}
59
60impl std::str::FromStr for NodeKind {
61    type Err = ();
62    fn from_str(s: &str) -> Result<Self, Self::Err> {
63        match s {
64            "folder" => Ok(NodeKind::Folder),
65            "file" => Ok(NodeKind::File),
66            "module" => Ok(NodeKind::Module),
67            "struct" => Ok(NodeKind::Struct),
68            "enum" => Ok(NodeKind::Enum),
69            "trait" => Ok(NodeKind::Trait),
70            "interface" => Ok(NodeKind::Interface),
71            "type_alias" => Ok(NodeKind::TypeAlias),
72            "function" => Ok(NodeKind::Function),
73            "method" => Ok(NodeKind::Method),
74            "property" => Ok(NodeKind::Property),
75            "constant" => Ok(NodeKind::Constant),
76            "macro" => Ok(NodeKind::Macro),
77            "annotation" => Ok(NodeKind::Annotation),
78            "enum_member" | "enum-member" => Ok(NodeKind::EnumMember),
79            "section" => Ok(NodeKind::Section),
80            _ => Err(()),
81        }
82    }
83}
84
85/// Directed relationship between two nodes.
86#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
87#[serde(rename_all = "snake_case")]
88pub enum EdgeKind {
89    /// Parent–child containment: File→Module, Module→Struct, Struct→Method.
90    Contains,
91    /// Resolved call site: Function→Function or Method→Method.
92    Calls,
93    /// `impl Trait for Struct`, `class Foo implements Bar` — Struct→Trait/Interface.
94    Implements,
95    /// `class Foo extends Bar`, embedded struct in Go — subtype→supertype.
96    /// Distinct from `Implements`: this is "is-a" inheritance vs "can-do" interface
97    /// satisfaction.
98    Inherits,
99    /// A type appears as a parameter or return type: fn→Struct/Trait.
100    Uses,
101    /// `use path::to::Thing` import.
102    Imports,
103    /// A symbol is decorated/annotated by another (`@Override`, `@dataclass`,
104    /// `#[derive(Debug)]`).
105    Annotated,
106    /// Java `throws ExceptionType` — method→exception class.
107    Throws,
108    /// A Markdown section (or file-level prose) mentions a code symbol, via
109    /// an inline code-span or link text matching a known identifier.
110    /// Source can be cross-language by design (docs reference any language).
111    References,
112}
113
114impl std::fmt::Display for EdgeKind {
115    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116        let s = match self {
117            EdgeKind::Contains => "contains",
118            EdgeKind::Calls => "calls",
119            EdgeKind::Implements => "implements",
120            EdgeKind::Inherits => "inherits",
121            EdgeKind::Uses => "uses",
122            EdgeKind::Imports => "imports",
123            EdgeKind::Annotated => "annotated",
124            EdgeKind::Throws => "throws",
125            EdgeKind::References => "references",
126        };
127        f.write_str(s)
128    }
129}
130
131/// How confident the indexer is that an edge is real. Direct edges resolved
132/// within a single file are `Extracted`; cross-file edges resolved by matching
133/// an unqualified name against the symbol table are `Inferred` (a same-named
134/// symbol in another module could in principle be the true target).
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
136#[serde(rename_all = "snake_case")]
137pub enum EdgeConfidence {
138    /// Directly observed in the source (same-file resolution). High confidence.
139    #[default]
140    Extracted,
141    /// Resolved cross-file by name match. Lower confidence.
142    Inferred,
143}
144
145impl std::fmt::Display for EdgeConfidence {
146    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147        f.write_str(match self {
148            EdgeConfidence::Extracted => "extracted",
149            EdgeConfidence::Inferred => "inferred",
150        })
151    }
152}
153
154impl EdgeConfidence {
155    /// Parse from the stored string form; unknown/empty defaults to `Extracted`.
156    pub fn from_label(s: &str) -> Self {
157        match s {
158            "inferred" => EdgeConfidence::Inferred,
159            _ => EdgeConfidence::Extracted,
160        }
161    }
162}
163
164/// Symbol visibility in the source language.
165#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
166#[serde(rename_all = "snake_case")]
167pub enum Visibility {
168    #[default]
169    Private,
170    PubCrate,
171    Pub,
172}
173
174impl std::fmt::Display for Visibility {
175    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176        match self {
177            Visibility::Pub => f.write_str("pub"),
178            Visibility::PubCrate => f.write_str("pub_crate"),
179            Visibility::Private => f.write_str("private"),
180        }
181    }
182}
183
184impl std::str::FromStr for Visibility {
185    type Err = ();
186    fn from_str(s: &str) -> Result<Self, Self::Err> {
187        match s {
188            "pub" => Ok(Visibility::Pub),
189            "pub_crate" => Ok(Visibility::PubCrate),
190            "private" => Ok(Visibility::Private),
191            _ => Err(()),
192        }
193    }
194}
195
196// ── LLD labels ──────────────────────────────────────────────────────────────
197
198/// Which SOLID principle a node may be violating (populated in pass 2).
199#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
200#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
201pub enum SolidHint {
202    /// Too many responsibilities in one type.
203    Srp,
204    /// Logic closed for extension but open for modification.
205    Ocp,
206    /// Subtype breaks contract of supertype.
207    Lsp,
208    /// Interface has too many unrelated methods.
209    Isp,
210    /// Depends on concrete type instead of abstraction.
211    Dip,
212}
213
214/// Common design patterns detectable syntactically.
215#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
216#[serde(rename_all = "snake_case")]
217pub enum DesignPattern {
218    Builder,
219    Factory,
220    Observer,
221    Strategy,
222    Decorator,
223    Singleton,
224    Repository,
225}
226
227/// Code quality smells detectable without full type resolution.
228#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
229#[serde(rename_all = "snake_case")]
230pub enum CodeSmell {
231    /// Struct with too many methods or dependencies.
232    GodStruct,
233    /// Function body too long.
234    LongMethod,
235    /// Nesting depth exceeds threshold.
236    DeepNesting,
237    /// Trait with too many methods.
238    FatInterface,
239}