1use std::path::PathBuf;
5
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
10pub enum ModificationKind {
11 Logic,
13 WhitespaceOnly,
15 ImportsOnly,
17 CommentsOnly,
19 FormattingOnly,
21 Mixed,
23}
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
27pub enum ChangeImportance {
28 Noise,
30 Low,
32 Medium,
34 High,
36}
37
38#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
40pub enum SemanticChange {
41 FileAdded { path: PathBuf },
43 FileDeleted { path: PathBuf },
45 FileModified {
47 path: PathBuf,
48 #[serde(default)]
49 classification: Option<ModificationKind>,
50 #[serde(default)]
51 importance: Option<ChangeImportance>,
52 #[serde(default)]
54 confidence: Option<f64>,
55 },
56 FileRenamed { from: PathBuf, to: PathBuf },
58 FunctionAdded {
60 file: PathBuf,
61 name: String,
62 #[serde(default)]
63 importance: Option<ChangeImportance>,
64 },
65 FunctionExtracted {
67 file: PathBuf,
68 name: String,
69 #[serde(default)]
70 source_file: Option<PathBuf>,
71 #[serde(default)]
72 source_name: Option<String>,
73 #[serde(default)]
74 importance: Option<ChangeImportance>,
75 },
76 FunctionDeleted {
78 file: PathBuf,
79 name: String,
80 #[serde(default)]
81 importance: Option<ChangeImportance>,
82 },
83 FunctionRenamed {
85 file: PathBuf,
86 old_name: String,
87 new_name: String,
88 #[serde(default)]
89 importance: Option<ChangeImportance>,
90 },
91 FunctionModified {
93 file: PathBuf,
94 name: String,
95 #[serde(default)]
96 importance: Option<ChangeImportance>,
97 },
98 FunctionMoved {
100 file: PathBuf,
101 name: String,
102 old_start_line: usize,
103 new_start_line: usize,
104 #[serde(default)]
105 importance: Option<ChangeImportance>,
106 },
107 SignatureChanged {
109 file: PathBuf,
110 name: String,
111 old_signature: String,
112 new_signature: String,
113 #[serde(default)]
114 importance: Option<ChangeImportance>,
115 },
116 DependencyAdded { name: String, version: String },
118 DependencyRemoved { name: String },
120 Custom {
122 change_type: String,
123 data: serde_json::Value,
124 },
125}
126
127impl SemanticChange {
128 pub fn description(&self) -> String {
130 match self {
131 SemanticChange::FileAdded { path } => format!("add {}", path.display()),
132 SemanticChange::FileDeleted { path } => format!("delete {}", path.display()),
133 SemanticChange::FileModified {
134 path,
135 classification,
136 ..
137 } => {
138 if let Some(kind) = classification {
139 format!("modify {} ({:?})", path.display(), kind)
140 } else {
141 format!("modify {}", path.display())
142 }
143 }
144 SemanticChange::FileRenamed { from, to } => {
145 format!("rename {} -> {}", from.display(), to.display())
146 }
147 SemanticChange::FunctionAdded { file, name, .. } => {
148 format!("add function {} in {}", name, file.display())
149 }
150 SemanticChange::FunctionExtracted {
151 file,
152 name,
153 source_file,
154 source_name,
155 ..
156 } => {
157 if let Some(source_name) = source_name {
158 let source_file = source_file.as_ref().unwrap_or(file);
159 format!(
160 "extract function {} from {} in {}",
161 name,
162 source_name,
163 source_file.display()
164 )
165 } else {
166 format!("extract function {} in {}", name, file.display())
167 }
168 }
169 SemanticChange::FunctionDeleted { file, name, .. } => {
170 format!("delete function {} in {}", name, file.display())
171 }
172 SemanticChange::FunctionRenamed {
173 file,
174 old_name,
175 new_name,
176 ..
177 } => {
178 format!("rename {} -> {} in {}", old_name, new_name, file.display())
179 }
180 SemanticChange::FunctionModified { file, name, .. } => {
181 format!("modify function {} in {}", name, file.display())
182 }
183 SemanticChange::FunctionMoved {
184 file,
185 name,
186 old_start_line,
187 new_start_line,
188 ..
189 } => {
190 format!(
191 "move function {} in {} ({} -> {})",
192 name,
193 file.display(),
194 old_start_line + 1,
195 new_start_line + 1
196 )
197 }
198 SemanticChange::SignatureChanged { file, name, .. } => {
199 format!("change signature of {} in {}", name, file.display())
200 }
201 SemanticChange::DependencyAdded { name, version } => {
202 format!("add dependency {}@{}", name, version)
203 }
204 SemanticChange::DependencyRemoved { name } => {
205 format!("remove dependency {}", name)
206 }
207 SemanticChange::Custom { change_type, .. } => {
208 format!("custom: {}", change_type)
209 }
210 }
211 }
212}