1use std::any::Any;
4use tower_lsp_server::ls_types::Range;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct MavenDependency {
8 pub group_id: String,
9 pub artifact_id: String,
10 pub name: String,
12 pub name_range: Range,
13 pub version_req: Option<String>,
14 pub version_range: Option<Range>,
15 pub scope: MavenScope,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Default)]
19pub enum MavenScope {
20 #[default]
21 Compile,
22 Test,
23 Runtime,
24 Provided,
25 System,
26 Import,
27}
28
29impl std::str::FromStr for MavenScope {
30 type Err = std::convert::Infallible;
31
32 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
33 Ok(match s.to_lowercase().as_str() {
34 "test" => Self::Test,
35 "runtime" => Self::Runtime,
36 "provided" => Self::Provided,
37 "system" => Self::System,
38 "import" => Self::Import,
39 _ => Self::Compile,
40 })
41 }
42}
43
44#[derive(Debug, Clone)]
45pub struct MavenVersion {
46 pub version: String,
47 pub timestamp: Option<u64>,
48}
49
50#[derive(Debug, Clone)]
51pub struct ArtifactInfo {
52 pub group_id: String,
53 pub artifact_id: String,
54 pub name: String,
56 pub description: Option<String>,
57 pub latest_version: String,
58 pub repository: Option<String>,
59}
60
61impl deps_core::DependencyInfo for MavenDependency {
64 fn name(&self) -> &str {
65 &self.name
66 }
67
68 fn name_range(&self) -> Range {
69 self.name_range
70 }
71
72 fn version_requirement(&self) -> Option<&str> {
73 self.version_req.as_deref()
74 }
75
76 fn version_range(&self) -> Option<Range> {
77 self.version_range
78 }
79
80 fn source(&self) -> deps_core::parser::DependencySource {
81 deps_core::parser::DependencySource::Registry
82 }
83
84 fn features(&self) -> &[String] {
85 &[]
86 }
87}
88
89impl deps_core::Dependency for MavenDependency {
90 fn name(&self) -> &str {
91 &self.name
92 }
93
94 fn name_range(&self) -> Range {
95 self.name_range
96 }
97
98 fn version_requirement(&self) -> Option<&str> {
99 self.version_req.as_deref()
100 }
101
102 fn version_range(&self) -> Option<Range> {
103 self.version_range
104 }
105
106 fn source(&self) -> deps_core::parser::DependencySource {
107 deps_core::parser::DependencySource::Registry
108 }
109
110 fn features(&self) -> &[String] {
111 &[]
112 }
113
114 fn as_any(&self) -> &dyn Any {
115 self
116 }
117}
118
119impl deps_core::Version for MavenVersion {
120 fn version_string(&self) -> &str {
121 &self.version
122 }
123
124 fn is_yanked(&self) -> bool {
125 false
127 }
128
129 fn is_prerelease(&self) -> bool {
130 crate::version::is_prerelease(&self.version)
131 }
132
133 fn features(&self) -> Vec<String> {
134 vec![]
135 }
136
137 fn as_any(&self) -> &dyn Any {
138 self
139 }
140}
141
142impl deps_core::Metadata for ArtifactInfo {
143 fn name(&self) -> &str {
144 &self.name
145 }
146
147 fn description(&self) -> Option<&str> {
148 self.description.as_deref()
149 }
150
151 fn repository(&self) -> Option<&str> {
152 self.repository.as_deref()
153 }
154
155 fn documentation(&self) -> Option<&str> {
156 None
157 }
158
159 fn latest_version(&self) -> &str {
160 &self.latest_version
161 }
162
163 fn as_any(&self) -> &dyn Any {
164 self
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171 use tower_lsp_server::ls_types::Position;
172
173 fn test_dep() -> MavenDependency {
174 MavenDependency {
175 group_id: "org.apache.commons".into(),
176 artifact_id: "commons-lang3".into(),
177 name: "org.apache.commons:commons-lang3".into(),
178 name_range: Range::new(Position::new(5, 4), Position::new(5, 17)),
179 version_req: Some("3.14.0".into()),
180 version_range: Some(Range::new(Position::new(7, 13), Position::new(7, 19))),
181 scope: MavenScope::Compile,
182 }
183 }
184
185 #[test]
186 fn test_scope_variants() {
187 use std::str::FromStr;
188 assert!(matches!(
189 "test".parse::<MavenScope>().unwrap(),
190 MavenScope::Test
191 ));
192 assert!(matches!(
193 "runtime".parse::<MavenScope>().unwrap(),
194 MavenScope::Runtime
195 ));
196 assert!(matches!(
197 "provided".parse::<MavenScope>().unwrap(),
198 MavenScope::Provided
199 ));
200 assert!(matches!(
201 "system".parse::<MavenScope>().unwrap(),
202 MavenScope::System
203 ));
204 assert!(matches!(
205 "import".parse::<MavenScope>().unwrap(),
206 MavenScope::Import
207 ));
208 assert!(matches!(
209 "compile".parse::<MavenScope>().unwrap(),
210 MavenScope::Compile
211 ));
212 assert!(matches!(
213 "unknown".parse::<MavenScope>().unwrap(),
214 MavenScope::Compile
215 ));
216 let _ = MavenScope::from_str; }
218
219 #[test]
220 fn test_scope_default() {
221 assert!(matches!(MavenScope::default(), MavenScope::Compile));
222 }
223
224 #[test]
225 fn test_dependency_trait() {
226 use deps_core::Dependency;
227
228 let dep = test_dep();
229 assert_eq!(dep.name(), "org.apache.commons:commons-lang3");
230 assert_eq!(dep.version_requirement(), Some("3.14.0"));
231 assert!(dep.features().is_empty());
232 assert!(dep.as_any().is::<MavenDependency>());
233 assert!(matches!(
234 dep.source(),
235 deps_core::parser::DependencySource::Registry
236 ));
237 }
238
239 #[test]
240 fn test_dependency_info_trait() {
241 use deps_core::DependencyInfo;
242
243 let dep = test_dep();
244 assert_eq!(dep.name(), "org.apache.commons:commons-lang3");
245 assert!(dep.version_range().is_some());
246 assert!(matches!(
247 dep.source(),
248 deps_core::parser::DependencySource::Registry
249 ));
250 }
251
252 #[test]
253 fn test_dependency_without_version() {
254 use deps_core::Dependency;
255
256 let dep = MavenDependency {
257 group_id: "com.example".into(),
258 artifact_id: "test".into(),
259 name: "com.example:test".into(),
260 name_range: Range::default(),
261 version_req: None,
262 version_range: None,
263 scope: MavenScope::Compile,
264 };
265 assert!(dep.version_requirement().is_none());
266 assert!(dep.version_range().is_none());
267 }
268
269 #[test]
270 fn test_version_trait() {
271 use deps_core::Version;
272
273 let ver = MavenVersion {
274 version: "3.14.0".into(),
275 timestamp: Some(1_699_000_000),
276 };
277 assert_eq!(ver.version_string(), "3.14.0");
278 assert!(!ver.is_yanked());
279 assert!(!ver.is_prerelease());
280 assert!(ver.features().is_empty());
281 assert!(ver.as_any().is::<MavenVersion>());
282 }
283
284 #[test]
285 fn test_version_prerelease() {
286 use deps_core::Version;
287
288 let ver = MavenVersion {
289 version: "1.0.0-SNAPSHOT".into(),
290 timestamp: None,
291 };
292 assert!(ver.is_prerelease());
293
294 let ver = MavenVersion {
295 version: "2.0.0-M1".into(),
296 timestamp: None,
297 };
298 assert!(ver.is_prerelease());
299 }
300
301 #[test]
302 fn test_metadata_trait() {
303 use deps_core::Metadata;
304
305 let info = ArtifactInfo {
306 group_id: "org.apache.commons".into(),
307 artifact_id: "commons-lang3".into(),
308 name: "org.apache.commons:commons-lang3".into(),
309 description: Some("Apache Commons Lang".into()),
310 latest_version: "3.14.0".into(),
311 repository: None,
312 };
313 assert_eq!(info.name(), "org.apache.commons:commons-lang3");
314 assert_eq!(info.description(), Some("Apache Commons Lang"));
315 assert_eq!(info.latest_version(), "3.14.0");
316 assert!(info.repository().is_none());
317 assert!(info.documentation().is_none());
318 assert!(info.as_any().is::<ArtifactInfo>());
319 }
320}