1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
4#[serde(rename_all = "lowercase")]
5pub enum ChangeType {
6 Added,
7 Modified,
8 Deleted,
9 Moved,
10 Renamed,
11 Reordered,
12}
13
14impl std::fmt::Display for ChangeType {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 match self {
17 ChangeType::Added => write!(f, "added"),
18 ChangeType::Modified => write!(f, "modified"),
19 ChangeType::Deleted => write!(f, "deleted"),
20 ChangeType::Moved => write!(f, "moved"),
21 ChangeType::Renamed => write!(f, "renamed"),
22 ChangeType::Reordered => write!(f, "reordered"),
23 }
24 }
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28#[serde(rename_all = "camelCase")]
29#[non_exhaustive]
30pub struct SemanticChange {
31 pub id: String,
32 pub entity_id: String,
33 pub change_type: ChangeType,
34 pub entity_type: String,
35 pub entity_name: String,
36 #[serde(default)]
37 pub entity_line: usize,
38 #[serde(default)]
39 pub start_line: usize,
40 #[serde(default)]
41 pub end_line: usize,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub old_start_line: Option<usize>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub old_end_line: Option<usize>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub parent_name: Option<String>,
48 pub file_path: String,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub old_entity_name: Option<String>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub old_file_path: Option<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub old_parent_id: Option<String>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub before_content: Option<String>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub after_content: Option<String>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub commit_sha: Option<String>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub author: Option<String>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub timestamp: Option<String>,
65 #[serde(skip_serializing_if = "Option::is_none")]
68 pub structural_change: Option<bool>,
69}
70
71impl SemanticChange {
72 pub fn has_content_change(&self) -> bool {
73 match (&self.before_content, &self.after_content) {
74 (Some(before), Some(after)) => before != after,
75 _ => false,
76 }
77 }
78}