Skip to main content

kiss/
check_cache.rs

1use crate::duplication::CodeChunk;
2use crate::test_refs::CodeDefinition;
3use crate::units::CodeUnitKind;
4use crate::violation::Violation;
5use serde::{Deserialize, Serialize};
6use std::path::{Path, PathBuf};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct CachedViolation {
10    pub file: String,
11    pub line: usize,
12    pub unit_name: String,
13    pub metric: String,
14    pub value: usize,
15    pub threshold: usize,
16    pub message: String,
17    pub suggestion: String,
18}
19
20impl CachedViolation {
21    pub fn into_violation(self) -> Violation {
22        Violation {
23            file: PathBuf::from(self.file),
24            line: self.line,
25            unit_name: self.unit_name,
26            metric: self.metric,
27            value: self.value,
28            threshold: self.threshold,
29            message: self.message,
30            suggestion: self.suggestion,
31        }
32    }
33}
34
35impl From<&Violation> for CachedViolation {
36    fn from(v: &Violation) -> Self {
37        Self {
38            file: v.file.to_string_lossy().to_string(),
39            line: v.line,
40            unit_name: v.unit_name.clone(),
41            metric: v.metric.clone(),
42            value: v.value,
43            threshold: v.threshold,
44            message: v.message.clone(),
45            suggestion: v.suggestion.clone(),
46        }
47    }
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct CachedCodeChunk {
52    pub file: String,
53    pub name: String,
54    pub start_line: usize,
55    pub end_line: usize,
56    pub normalized: String,
57}
58
59impl CachedCodeChunk {
60    pub fn into_chunk(self) -> CodeChunk {
61        CodeChunk {
62            file: PathBuf::from(self.file),
63            name: self.name,
64            start_line: self.start_line,
65            end_line: self.end_line,
66            normalized: self.normalized,
67        }
68    }
69}
70
71impl From<&CodeChunk> for CachedCodeChunk {
72    fn from(c: &CodeChunk) -> Self {
73        Self {
74            file: c.file.to_string_lossy().to_string(),
75            name: c.name.clone(),
76            start_line: c.start_line,
77            end_line: c.end_line,
78            normalized: c.normalized.clone(),
79        }
80    }
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct CachedCodeDefinition {
85    pub name: String,
86    pub kind: String,
87    pub file: String,
88    pub line: usize,
89    pub containing_class: Option<String>,
90}
91
92const fn kind_to_str(k: CodeUnitKind) -> &'static str {
93    match k {
94        CodeUnitKind::Function => "function",
95        CodeUnitKind::Method => "method",
96        CodeUnitKind::Class => "class",
97        CodeUnitKind::Module => "module",
98        CodeUnitKind::Struct => "struct",
99        CodeUnitKind::Enum => "enum",
100        CodeUnitKind::TraitImplMethod => "trait_impl_method",
101    }
102}
103
104fn kind_from_str(s: &str) -> CodeUnitKind {
105    match s {
106        "method" => CodeUnitKind::Method,
107        "class" => CodeUnitKind::Class,
108        "module" => CodeUnitKind::Module,
109        "struct" => CodeUnitKind::Struct,
110        "enum" => CodeUnitKind::Enum,
111        "trait_impl_method" => CodeUnitKind::TraitImplMethod,
112        _ => CodeUnitKind::Function,
113    }
114}
115
116impl From<&CodeDefinition> for CachedCodeDefinition {
117    fn from(d: &CodeDefinition) -> Self {
118        Self {
119            name: d.name.clone(),
120            kind: kind_to_str(d.kind).to_string(),
121            file: d.file.to_string_lossy().to_string(),
122            line: d.line,
123            containing_class: d.containing_class.clone(),
124        }
125    }
126}
127
128impl CachedCodeDefinition {
129    pub fn into_definition(self) -> CodeDefinition {
130        CodeDefinition {
131            name: self.name,
132            kind: kind_from_str(&self.kind),
133            file: PathBuf::from(self.file),
134            line: self.line,
135            containing_class: self.containing_class,
136        }
137    }
138}
139
140pub fn cache_dir() -> PathBuf {
141    // Prefer user cache dir; fall back to temp.
142    if let Some(home) = std::env::var_os("HOME") {
143        return Path::new(&home).join(".cache").join("kiss");
144    }
145    std::env::temp_dir().join("kiss-cache")
146}
147
148#[cfg(test)]
149mod tests {
150    use super::*;
151
152    #[test]
153    fn test_cached_violation_roundtrip() {
154        let v = Violation::builder("foo.py")
155            .line(12)
156            .unit_name("f")
157            .metric("m")
158            .value(2)
159            .threshold(1)
160            .message("msg")
161            .suggestion("sugg")
162            .build();
163        let cached = CachedViolation::from(&v);
164        let v2 = cached.into_violation();
165        assert_eq!(v2.file, PathBuf::from("foo.py"));
166        assert_eq!(v2.line, 12);
167        assert_eq!(v2.unit_name, "f");
168    }
169
170    #[test]
171    fn test_cached_chunk_roundtrip() {
172        let c = CodeChunk {
173            file: PathBuf::from("a.py"),
174            name: "x".to_string(),
175            start_line: 1,
176            end_line: 2,
177            normalized: "norm".to_string(),
178        };
179        let cached = CachedCodeChunk::from(&c);
180        let c2 = cached.into_chunk();
181        assert_eq!(c2.file, PathBuf::from("a.py"));
182        assert_eq!(c2.name, "x");
183    }
184
185    #[test]
186    fn test_cached_definition_roundtrip() {
187        let d = CodeDefinition {
188            name: "C".to_string(),
189            kind: CodeUnitKind::Class,
190            file: PathBuf::from("x.py"),
191            line: 3,
192            containing_class: None,
193        };
194        let cached = CachedCodeDefinition::from(&d);
195        let d2 = cached.into_definition();
196        assert_eq!(d2.name, "C");
197        assert_eq!(d2.kind, CodeUnitKind::Class);
198        assert_eq!(d2.file, PathBuf::from("x.py"));
199    }
200
201    #[test]
202    fn test_cache_dir_smoke() {
203        // Full-run cache uses this directory; keep it stable and non-panicking.
204        let _ = cache_dir();
205
206        // Touch helpers for the static test-reference gate.
207        let _ = kind_to_str(CodeUnitKind::Function);
208        let _ = kind_from_str("class");
209    }
210}