Skip to main content

null_e/plugins/
java.rs

1//! Java plugin (Maven and Gradle)
2
3use crate::core::{Artifact, ArtifactKind, ArtifactMetadata, MarkerKind, ProjectKind, ProjectMarker};
4use crate::error::Result;
5use crate::plugins::Plugin;
6use std::path::Path;
7
8/// Plugin for Maven projects
9pub struct MavenPlugin;
10
11impl Plugin for MavenPlugin {
12    fn id(&self) -> &'static str {
13        "maven"
14    }
15
16    fn name(&self) -> &'static str {
17        "Java (Maven)"
18    }
19
20    fn supported_kinds(&self) -> &[ProjectKind] {
21        &[ProjectKind::JavaMaven]
22    }
23
24    fn markers(&self) -> Vec<ProjectMarker> {
25        vec![ProjectMarker {
26            indicator: MarkerKind::File("pom.xml"),
27            kind: ProjectKind::JavaMaven,
28            priority: 60,
29        }]
30    }
31
32    fn detect(&self, path: &Path) -> Option<ProjectKind> {
33        if path.join("pom.xml").is_file() {
34            Some(ProjectKind::JavaMaven)
35        } else {
36            None
37        }
38    }
39
40    fn find_artifacts(&self, project_root: &Path) -> Result<Vec<Artifact>> {
41        let mut artifacts = Vec::new();
42
43        // target directory
44        let target = project_root.join("target");
45        if target.exists() {
46            artifacts.push(Artifact {
47                path: target,
48                kind: ArtifactKind::BuildOutput,
49                size: 0,
50                file_count: 0,
51                age: None,
52                metadata: ArtifactMetadata {
53                    restorable: true,
54                    restore_command: Some("mvn compile".into()),
55                    lockfile: Some(project_root.join("pom.xml")),
56                    restore_time_estimate: Some(60),
57                    ..Default::default()
58                },
59            });
60        }
61
62        Ok(artifacts)
63    }
64
65    fn cleanable_dirs(&self) -> &[&'static str] {
66        &["target"]
67    }
68
69    fn priority(&self) -> u8 {
70        60
71    }
72}
73
74/// Plugin for Gradle projects
75pub struct GradlePlugin;
76
77impl Plugin for GradlePlugin {
78    fn id(&self) -> &'static str {
79        "gradle"
80    }
81
82    fn name(&self) -> &'static str {
83        "Java (Gradle)"
84    }
85
86    fn supported_kinds(&self) -> &[ProjectKind] {
87        &[ProjectKind::JavaGradle]
88    }
89
90    fn markers(&self) -> Vec<ProjectMarker> {
91        vec![
92            ProjectMarker {
93                indicator: MarkerKind::File("build.gradle"),
94                kind: ProjectKind::JavaGradle,
95                priority: 60,
96            },
97            ProjectMarker {
98                indicator: MarkerKind::File("build.gradle.kts"),
99                kind: ProjectKind::JavaGradle,
100                priority: 60,
101            },
102            ProjectMarker {
103                indicator: MarkerKind::File("settings.gradle"),
104                kind: ProjectKind::JavaGradle,
105                priority: 55,
106            },
107            ProjectMarker {
108                indicator: MarkerKind::File("settings.gradle.kts"),
109                kind: ProjectKind::JavaGradle,
110                priority: 55,
111            },
112        ]
113    }
114
115    fn detect(&self, path: &Path) -> Option<ProjectKind> {
116        if path.join("build.gradle").is_file()
117            || path.join("build.gradle.kts").is_file()
118            || path.join("settings.gradle").is_file()
119            || path.join("settings.gradle.kts").is_file()
120        {
121            Some(ProjectKind::JavaGradle)
122        } else {
123            None
124        }
125    }
126
127    fn find_artifacts(&self, project_root: &Path) -> Result<Vec<Artifact>> {
128        let mut artifacts = Vec::new();
129
130        // build directory
131        let build = project_root.join("build");
132        if build.exists() {
133            artifacts.push(Artifact {
134                path: build,
135                kind: ArtifactKind::BuildOutput,
136                size: 0,
137                file_count: 0,
138                age: None,
139                metadata: ArtifactMetadata {
140                    restorable: true,
141                    restore_command: Some("./gradlew build".into()),
142                    ..Default::default()
143                },
144            });
145        }
146
147        // .gradle directory (local cache)
148        let gradle_cache = project_root.join(".gradle");
149        if gradle_cache.exists() {
150            artifacts.push(Artifact {
151                path: gradle_cache,
152                kind: ArtifactKind::Cache,
153                size: 0,
154                file_count: 0,
155                age: None,
156                metadata: ArtifactMetadata::default(),
157            });
158        }
159
160        // out directory (IntelliJ IDEA)
161        let out = project_root.join("out");
162        if out.exists() {
163            artifacts.push(Artifact {
164                path: out,
165                kind: ArtifactKind::BuildOutput,
166                size: 0,
167                file_count: 0,
168                age: None,
169                metadata: ArtifactMetadata::restorable("./gradlew build"),
170            });
171        }
172
173        Ok(artifacts)
174    }
175
176    fn cleanable_dirs(&self) -> &[&'static str] {
177        &["build", ".gradle", "out"]
178    }
179
180    fn priority(&self) -> u8 {
181        60
182    }
183}
184
185#[cfg(test)]
186mod tests {
187    use super::*;
188    use tempfile::TempDir;
189
190    #[test]
191    fn test_detect_maven() {
192        let temp = TempDir::new().unwrap();
193        std::fs::write(
194            temp.path().join("pom.xml"),
195            r#"<project></project>"#,
196        )
197        .unwrap();
198
199        let plugin = MavenPlugin;
200        assert_eq!(plugin.detect(temp.path()), Some(ProjectKind::JavaMaven));
201    }
202
203    #[test]
204    fn test_detect_gradle() {
205        let temp = TempDir::new().unwrap();
206        std::fs::write(temp.path().join("build.gradle"), "").unwrap();
207
208        let plugin = GradlePlugin;
209        assert_eq!(plugin.detect(temp.path()), Some(ProjectKind::JavaGradle));
210    }
211
212    #[test]
213    fn test_detect_gradle_kts() {
214        let temp = TempDir::new().unwrap();
215        std::fs::write(temp.path().join("build.gradle.kts"), "").unwrap();
216
217        let plugin = GradlePlugin;
218        assert_eq!(plugin.detect(temp.path()), Some(ProjectKind::JavaGradle));
219    }
220
221    #[test]
222    fn test_find_gradle_artifacts() {
223        let temp = TempDir::new().unwrap();
224        std::fs::write(temp.path().join("build.gradle"), "").unwrap();
225        std::fs::create_dir(temp.path().join("build")).unwrap();
226        std::fs::create_dir(temp.path().join(".gradle")).unwrap();
227
228        let plugin = GradlePlugin;
229        let artifacts = plugin.find_artifacts(temp.path()).unwrap();
230
231        assert_eq!(artifacts.len(), 2);
232    }
233}