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 = 11;
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/// How confident the indexer is that an edge is real. Direct edges resolved
98/// within a single file are `Extracted`; cross-file edges resolved by matching
99/// an unqualified name against the symbol table are `Inferred` (a same-named
100/// symbol in another module could in principle be the true target).
101#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
102#[serde(rename_all = "snake_case")]
103pub enum EdgeConfidence {
104    /// Directly observed in the source (same-file resolution). High confidence.
105    #[default]
106    Extracted,
107    /// Resolved cross-file by name match. Lower confidence.
108    Inferred,
109}
110
111impl std::fmt::Display for EdgeConfidence {
112    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113        f.write_str(match self {
114            EdgeConfidence::Extracted => "extracted",
115            EdgeConfidence::Inferred => "inferred",
116        })
117    }
118}
119
120impl EdgeConfidence {
121    /// Parse from the stored string form; unknown/empty defaults to `Extracted`.
122    pub fn from_label(s: &str) -> Self {
123        match s {
124            "inferred" => EdgeConfidence::Inferred,
125            _ => EdgeConfidence::Extracted,
126        }
127    }
128}
129
130/// Symbol visibility in the source language.
131#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
132#[serde(rename_all = "snake_case")]
133pub enum Visibility {
134    #[default]
135    Private,
136    PubCrate,
137    Pub,
138}
139
140impl std::fmt::Display for Visibility {
141    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142        match self {
143            Visibility::Pub => f.write_str("pub"),
144            Visibility::PubCrate => f.write_str("pub_crate"),
145            Visibility::Private => f.write_str("private"),
146        }
147    }
148}
149
150// ── LLD labels ──────────────────────────────────────────────────────────────
151
152/// Which SOLID principle a node may be violating (populated in pass 2).
153#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
154#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
155pub enum SolidHint {
156    /// Too many responsibilities in one type.
157    Srp,
158    /// Logic closed for extension but open for modification.
159    Ocp,
160    /// Subtype breaks contract of supertype.
161    Lsp,
162    /// Interface has too many unrelated methods.
163    Isp,
164    /// Depends on concrete type instead of abstraction.
165    Dip,
166}
167
168/// Common design patterns detectable syntactically.
169#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
170#[serde(rename_all = "snake_case")]
171pub enum DesignPattern {
172    Builder,
173    Factory,
174    Observer,
175    Strategy,
176    Decorator,
177    Singleton,
178    Repository,
179}
180
181/// Code quality smells detectable without full type resolution.
182#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
183#[serde(rename_all = "snake_case")]
184pub enum CodeSmell {
185    /// Struct with too many methods or dependencies.
186    GodStruct,
187    /// Function body too long.
188    LongMethod,
189    /// Nesting depth exceeds threshold.
190    DeepNesting,
191    /// Trait with too many methods.
192    FatInterface,
193}