diff --git a/_fixtures/projects/java/multi_mod_maven_project/src/main/java/Hello.java b/_fixtures/projects/java/multi_mod_maven_project/src/main/java/Hello.java new file mode 100644 index 00000000..e69de29b diff --git a/_fixtures/projects/java/multi_mod_maven_project/src/main/resources/application.yml b/_fixtures/projects/java/multi_mod_maven_project/src/main/resources/application.yml new file mode 100644 index 00000000..e69de29b diff --git a/_fixtures/projects/java/multi_mod_maven_project/src/test/java/HelloTest.java b/_fixtures/projects/java/multi_mod_maven_project/src/test/java/HelloTest.java new file mode 100644 index 00000000..e69de29b diff --git a/_fixtures/projects/java/multi_mod_maven_project/src/test/resources/application.yml b/_fixtures/projects/java/multi_mod_maven_project/src/test/resources/application.yml new file mode 100644 index 00000000..e69de29b diff --git a/psa/src/files.rs b/psa/src/files.rs index 57495f32..2145510d 100644 --- a/psa/src/files.rs +++ b/psa/src/files.rs @@ -1,5 +1,7 @@ use std::path::Path; +use std::path::PathBuf; +use std::collections::HashSet; use walkdir::WalkDir; pub fn list_file_names>(path: P) -> Vec { @@ -18,6 +20,23 @@ pub fn list_file_names>(path: P) -> Vec { files } +pub fn list_all>(path: P) -> HashSet { + let mut dirs = HashSet::new(); + let walk_dir = WalkDir::new(path); + for dir_entry in walk_dir + .min_depth(1) + .sort_by(|a, b| a.file_name().cmp(b.file_name())) + .into_iter() + { + if dir_entry.is_err() { + panic!("{}", dir_entry.err().unwrap()); + } + + dirs.insert(dir_entry.unwrap().path().display().to_string()); + } + dirs +} + pub fn list_sub_dirs>(path: P) -> Vec { let mut dirs = Vec::new(); let walk_dir = WalkDir::new(path); @@ -38,3 +57,23 @@ pub fn list_sub_dirs>(path: P) -> Vec { } dirs } + +pub fn find_in_path(root_path: &str, file: Vec<&str>) -> Option { + let all_files = list_all(root_path); + let mut parent_path = PathBuf::from(root_path).to_path_buf(); + for each_part in file.into_iter() { + parent_path.push(each_part); + } + match all_files.contains(&parent_path.display().to_string()) { + true => Some(parent_path.display().to_string()), + _ => None, + } +} + +pub fn join_path(root_path: &str, file: Vec<&str>) -> String { + let mut parent_path = PathBuf::from(root_path).to_path_buf(); + for each_part in file.into_iter() { + parent_path.push(each_part); + } + parent_path.display().to_string() +} diff --git a/psa/src/jvm/maven_module.rs b/psa/src/jvm/maven_module.rs index 12839898..0ed715a0 100644 --- a/psa/src/jvm/maven_module.rs +++ b/psa/src/jvm/maven_module.rs @@ -1,12 +1,17 @@ use std::path::Path; -use crate::files::{list_file_names, list_sub_dirs}; +use crate::files::{find_in_path, list_file_names, list_sub_dirs}; use crate::jvm::psa_jvm::ModuleAnalyzer; use crate::{Module, Project}; pub struct MavenModuleAnalyzer {} impl MavenModuleAnalyzer { + fn detect_sub_modules(&self, module_path: &str, module: &mut Option) { + let sub_modules = &mut self.analysis_sub_modules(module_path); + module.as_mut().unwrap().add_sub_modules(sub_modules); + } + fn analysis_sub_modules(&self, module_path: &str) -> Vec { let mut sub_modules = Vec::new(); let sub_dirs = list_sub_dirs(Path::new(module_path)); @@ -19,14 +24,63 @@ impl MavenModuleAnalyzer { } sub_modules } + + fn detect_content_root(&self, module_path: &str, mut module: &mut Option) { + self.detect_source_root(module_path, &mut module); + self.detect_resource_root(module_path, &mut module); + self.detect_test_source_root(module_path, &mut module); + self.detect_test_resource_root(module_path, &mut module); + } + + fn detect_source_root(&self, module_path: &str, module: &mut Option) { + let path = module_path; + let source_root = find_in_path(path, vec!["src", "main", "java"]); + match source_root { + Some(source_root) => module.as_mut().unwrap().add_source_root(source_root), + _ => (), + } + } + + fn detect_resource_root(&self, module_path: &str, module: &mut Option) { + let path = module_path; + let resource_root = find_in_path(path, vec!["src", "main", "resources"]); + match resource_root { + Some(resource_root) => module.as_mut().unwrap().add_resource_root(resource_root), + _ => (), + } + } + + fn detect_test_source_root(&self, module_path: &str, module: &mut Option) { + let path = module_path; + let test_source_root = find_in_path(path, vec!["src", "test", "java"]); + match test_source_root { + Some(test_source_root) => module + .as_mut() + .unwrap() + .add_test_source_root(test_source_root), + _ => (), + } + } + + fn detect_test_resource_root(&self, module_path: &str, module: &mut Option) { + let path = module_path; + let test_resource_root = find_in_path(path, vec!["src", "test", "resources"]); + match test_resource_root { + Some(test_resource_root) => module + .as_mut() + .unwrap() + .add_test_resource_root(test_resource_root), + _ => (), + } + } } impl ModuleAnalyzer for MavenModuleAnalyzer { fn analysis(&self, module_path: &str) -> Option { let mut module = create_module(module_path); if !module.is_none() { - let sub_modules = &mut self.analysis_sub_modules(module_path); - module.as_mut().unwrap().add_sub_modules(sub_modules); + self.detect_sub_modules(&module_path, &mut module); + self.detect_content_root(module_path, &mut module); } module } diff --git a/psa/src/jvm/psa_jvm.rs b/psa/src/jvm/psa_jvm.rs index 7bfeb982..e2a070b6 100644 --- a/psa/src/jvm/psa_jvm.rs +++ b/psa/src/jvm/psa_jvm.rs @@ -99,24 +99,18 @@ fn is_build_file(file_name: &str) -> bool { mod tests { use std::path::PathBuf; + use crate::files::join_path; use crate::jvm::psa_jvm::JvmProjectStructureAnalyzer; - use crate::ProjectStructureAnalyzer; + use crate::{Project, ProjectStructureAnalyzer}; #[test] fn should_analysis_maven_project_sub_modules() { - let project_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .parent() - .unwrap() - .to_path_buf() - .join("_fixtures") - .join("projects") - .join("java") - .join("multi_mod_maven_project") - .clone(); - - let analyzer = JvmProjectStructureAnalyzer::default(); - - let project = analyzer.analysis(project_dir.display().to_string().as_str()); + let project = do_analysis(vec![ + "_fixtures", + "projects", + "java", + "multi_mod_maven_project", + ]); let modules = project.modules; let project_module = modules.get(0).unwrap(); @@ -129,4 +123,67 @@ mod tests { assert_eq!(module1.name, "module1"); assert_eq!(module2.name, "module2"); } + + #[test] + fn should_detect_project_model_content_root() { + let project = do_analysis(vec![ + "_fixtures", + "projects", + "java", + "multi_mod_maven_project", + ]); + let modules = project.modules; + let project_module = modules.get(0).unwrap(); + let project_content_root = &project_module.content_root; + + let expect_source_path = + join_path(project_module.path.as_str(), vec!["src", "main", "java"]); + assert_eq!( + project_content_root.source_root.get(0).unwrap().as_str(), + expect_source_path.as_str() + ); + + let expect_resource_path = join_path( + project_module.path.as_str(), + vec!["src", "main", "resources"], + ); + assert_eq!( + project_content_root.resource_root.get(0).unwrap().as_str(), + expect_resource_path.as_str() + ); + + let expect_test_source_root = + join_path(project_module.path.as_str(), vec!["src", "test", "java"]); + assert_eq!( + project_content_root + .test_source_root + .get(0) + .unwrap() + .as_str(), + expect_test_source_root.as_str() + ); + + let expect_test_resources_root = join_path( + project_module.path.as_str(), + vec!["src", "test", "resources"], + ); + assert_eq!( + project_content_root.test_resource_root.get(0).unwrap(), + expect_test_resources_root.as_str() + ); + } + + fn do_analysis(path: Vec<&str>) -> Project { + let mut project_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .to_path_buf(); + + for path in path.into_iter() { + project_dir.push(path); + } + + let analyzer = JvmProjectStructureAnalyzer::default(); + analyzer.analysis(project_dir.display().to_string().as_str()) + } } diff --git a/psa/src/psa_module.rs b/psa/src/psa_module.rs index 23e5f527..c21c3399 100644 --- a/psa/src/psa_module.rs +++ b/psa/src/psa_module.rs @@ -28,6 +28,24 @@ impl Module { self.sub_modules.append(sub_modules); } + pub fn add_source_root(&mut self, source_root: String) { + self.content_root.add_source_root(source_root.as_str()); + } + + pub fn add_resource_root(&mut self, resource_root: String) { + self.content_root.add_resource_root(resource_root.as_str()); + } + + pub fn add_test_source_root(&mut self, test_source_root: String) { + self.content_root + .add_test_source_root(test_source_root.as_str()); + } + + pub(crate) fn add_test_resource_root(&mut self, test_resource_root: String) { + self.content_root + .add_test_resource_root(test_resource_root.as_str()); + } + pub fn new(name: &str, path: &str) -> Self { Module { name: name.to_string(),