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: deps_core::PackageName,
12 pub name_range: Range,
13 pub version_req: Option<deps_core::VersionReq>,
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: deps_core::ConcreteVersion,
47 pub published_at: Option<deps_core::PublishTime>,
53}
54
55#[derive(Debug, Clone)]
56pub struct ArtifactInfo {
57 pub group_id: String,
58 pub artifact_id: String,
59 pub name: deps_core::PackageName,
61 pub description: Option<String>,
62 pub latest_version: deps_core::ConcreteVersion,
63 pub repository: Option<String>,
64}
65
66impl deps_core::Dependency for MavenDependency {
69 fn name(&self) -> &deps_core::PackageName {
70 &self.name
71 }
72
73 fn name_range(&self) -> Range {
74 self.name_range
75 }
76
77 fn version_requirement(&self) -> Option<&deps_core::VersionReq> {
78 self.version_req.as_ref()
79 }
80
81 fn version_range(&self) -> Option<Range> {
82 self.version_range
83 }
84
85 fn source(&self) -> deps_core::parser::DependencySource {
86 deps_core::parser::DependencySource::Registry
87 }
88
89 fn features(&self) -> &[String] {
90 &[]
91 }
92
93 fn as_any(&self) -> &dyn Any {
94 self
95 }
96}
97
98impl deps_core::Version for MavenVersion {
99 fn version_string(&self) -> &deps_core::ConcreteVersion {
100 &self.version
101 }
102
103 fn is_prerelease(&self) -> bool {
106 crate::version::is_prerelease(self.version.as_str())
107 }
108
109 fn features(&self) -> Vec<String> {
110 vec![]
111 }
112
113 fn as_any(&self) -> &dyn Any {
114 self
115 }
116
117 fn published_at(&self) -> Option<deps_core::PublishTime> {
118 self.published_at
119 }
120}
121
122impl deps_core::Metadata for ArtifactInfo {
123 fn name(&self) -> &deps_core::PackageName {
124 &self.name
125 }
126
127 fn description(&self) -> Option<&str> {
128 self.description.as_deref()
129 }
130
131 fn repository(&self) -> Option<&str> {
132 self.repository.as_deref()
133 }
134
135 fn documentation(&self) -> Option<&str> {
136 None
137 }
138
139 fn latest_version(&self) -> &deps_core::ConcreteVersion {
140 &self.latest_version
141 }
142
143 fn as_any(&self) -> &dyn Any {
144 self
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151 use std::assert_matches;
152 use tower_lsp_server::ls_types::Position;
153
154 fn test_dep() -> MavenDependency {
155 MavenDependency {
156 group_id: "org.apache.commons".into(),
157 artifact_id: "commons-lang3".into(),
158 name: "org.apache.commons:commons-lang3".into(),
159 name_range: Range::new(Position::new(5, 4), Position::new(5, 17)),
160 version_req: Some("3.14.0".into()),
161 version_range: Some(Range::new(Position::new(7, 13), Position::new(7, 19))),
162 scope: MavenScope::Compile,
163 }
164 }
165
166 #[test]
167 fn test_scope_variants() {
168 use std::str::FromStr;
169 assert_matches!("test".parse::<MavenScope>().unwrap(), MavenScope::Test);
170 assert_matches!(
171 "runtime".parse::<MavenScope>().unwrap(),
172 MavenScope::Runtime
173 );
174 assert_matches!(
175 "provided".parse::<MavenScope>().unwrap(),
176 MavenScope::Provided
177 );
178 assert_matches!("system".parse::<MavenScope>().unwrap(), MavenScope::System);
179 assert_matches!("import".parse::<MavenScope>().unwrap(), MavenScope::Import);
180 assert_matches!(
181 "compile".parse::<MavenScope>().unwrap(),
182 MavenScope::Compile
183 );
184 assert_matches!(
185 "unknown".parse::<MavenScope>().unwrap(),
186 MavenScope::Compile
187 );
188 let _ = MavenScope::from_str; }
190
191 #[test]
192 fn test_scope_default() {
193 assert_matches!(MavenScope::default(), MavenScope::Compile);
194 }
195
196 #[test]
197 fn test_dependency_trait() {
198 use deps_core::Dependency;
199
200 let dep = test_dep();
201 assert_eq!(dep.name(), "org.apache.commons:commons-lang3");
202 assert_eq!(
203 dep.version_requirement().map(deps_core::VersionReq::as_str),
204 Some("3.14.0")
205 );
206 assert!(dep.features().is_empty());
207 assert!(dep.as_any().is::<MavenDependency>());
208 assert_matches!(dep.source(), deps_core::parser::DependencySource::Registry);
209 }
210
211 #[test]
212 fn test_dependency_info_trait() {
213 use deps_core::Dependency;
214
215 let dep = test_dep();
216 assert_eq!(dep.name(), "org.apache.commons:commons-lang3");
217 assert!(dep.version_range().is_some());
218 assert_matches!(dep.source(), deps_core::parser::DependencySource::Registry);
219 }
220
221 #[test]
222 fn test_dependency_without_version() {
223 use deps_core::Dependency;
224
225 let dep = MavenDependency {
226 group_id: "com.example".into(),
227 artifact_id: "test".into(),
228 name: "com.example:test".into(),
229 name_range: Range::default(),
230 version_req: None,
231 version_range: None,
232 scope: MavenScope::Compile,
233 };
234 assert!(dep.version_requirement().is_none());
235 assert!(dep.version_range().is_none());
236 }
237
238 #[test]
239 fn test_version_trait() {
240 use deps_core::Version;
241
242 let ver = MavenVersion {
243 version: "3.14.0".into(),
244 published_at: Some(deps_core::PublishTime::from_unix_secs(1_699_000_000)),
245 };
246 assert_eq!(ver.version_string(), "3.14.0");
247 assert!(!ver.removal_status().blocks_resolution());
248 assert!(!ver.is_prerelease());
249 assert!(ver.features().is_empty());
250 assert!(ver.as_any().is::<MavenVersion>());
251 assert_eq!(
252 ver.published_at(),
253 Some(deps_core::PublishTime::from_unix_secs(1_699_000_000))
254 );
255 }
256
257 #[test]
258 fn test_version_prerelease() {
259 use deps_core::Version;
260
261 let ver = MavenVersion {
262 version: "1.0.0-SNAPSHOT".into(),
263 published_at: None,
264 };
265 assert!(ver.is_prerelease());
266
267 let ver = MavenVersion {
268 version: "2.0.0-M1".into(),
269 published_at: None,
270 };
271 assert!(ver.is_prerelease());
272 }
273
274 #[test]
275 fn test_metadata_trait() {
276 use deps_core::Metadata;
277
278 let info = ArtifactInfo {
279 group_id: "org.apache.commons".into(),
280 artifact_id: "commons-lang3".into(),
281 name: deps_core::PackageName::new("org.apache.commons:commons-lang3"),
282 description: Some("Apache Commons Lang".into()),
283 latest_version: "3.14.0".into(),
284 repository: None,
285 };
286 assert_eq!(info.name(), "org.apache.commons:commons-lang3");
287 assert_eq!(info.description(), Some("Apache Commons Lang"));
288 assert_eq!(info.latest_version(), "3.14.0");
289 assert!(info.repository().is_none());
290 assert!(info.documentation().is_none());
291 assert!(info.as_any().is::<ArtifactInfo>());
292 }
293}