Skip to content

Commit

Permalink
feat(psa): maven project sub modules analysis.
Browse files Browse the repository at this point in the history
  • Loading branch information
ynfeng committed Feb 24, 2021
1 parent 276cc98 commit 32abe0b
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 69 deletions.
Empty file.
39 changes: 39 additions & 0 deletions psa/src/files.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::path::Path;

use walkdir::WalkDir;

pub fn list_file_names<P: AsRef<Path>>(path: P) -> Vec<String> {
let mut files = Vec::new();
let walk_dir = WalkDir::new(path);
for dir_entry in walk_dir.max_depth(1).into_iter() {
if dir_entry.is_err() {
panic!("{}", dir_entry.err().unwrap());
}

let entry = dir_entry.unwrap();
if entry.metadata().unwrap().is_file() {
files.push(entry.file_name().to_os_string().into_string().unwrap());
}
}
files
}

pub fn list_dirs<P: AsRef<Path>>(path: P) -> Vec<String> {
let mut dirs = Vec::new();
let walk_dir = WalkDir::new(path);
for dir_entry in walk_dir
.max_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());
}

let entry = dir_entry.unwrap();
if entry.metadata().unwrap().is_dir() {
dirs.push(entry.path().display().to_string())
}
}
dirs
}
41 changes: 41 additions & 0 deletions psa/src/jvm/maven_module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::path::Path;

use crate::files::list_file_names;
use crate::jvm::psa_jvm::ModuleAnalyzer;
use crate::{Module, Project};

pub struct MavenModuleAnalyzer {}

impl ModuleAnalyzer for MavenModuleAnalyzer {
fn analysis(&self, module_path: &str) -> Option<Module> {
let module_name = get_module_name(module_path);
match has_build_file(module_path) {
true => Some(Module::new(module_name.as_str(), module_path)),
_ => None,
}
}

fn is_related(&self, project: &Project) -> bool {
project.project_type == "maven"
}
}

fn has_build_file(module_path: &str) -> bool {
let file_names = list_file_names(module_path);
for file_name in file_names.iter() {
return match file_name.as_str() {
"pom.xml" => true,
_ => continue,
};
}
false
}

fn get_module_name(project_path: &str) -> String {
Path::new(project_path)
.file_name()
.unwrap()
.to_os_string()
.into_string()
.unwrap()
}
1 change: 1 addition & 0 deletions psa/src/jvm/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod maven_module;
pub mod psa_jvm;
102 changes: 48 additions & 54 deletions psa/src/jvm/psa_jvm.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,65 @@
use crate::project_structure_analyzer::StructureAnalyzer;
use crate::psa_project::Project;
use crate::Module;
use std::path::Path;
use walkdir::WalkDir;

trait ModuleAnalyzer {
fn analysis(module_path: &str) -> Option<Module>;
use crate::jvm::maven_module::MavenModuleAnalyzer;
use crate::psa_project::Project;
use crate::{files, Module, ProjectStructureAnalyzer};

pub trait ModuleAnalyzer {
fn analysis(&self, module_path: &str) -> Option<Module>;
fn is_related(&self, project: &Project) -> bool;
}

pub struct JvmProjectStructureAnalyzer {}
pub struct JvmProjectStructureAnalyzer {
module_analyzers: Vec<Box<dyn ModuleAnalyzer>>,
}

impl JvmProjectStructureAnalyzer {
fn analysis_modules(&self) -> Vec<Module> {
vec![
Module::new("multi_mod_maven_project", "foo"),
Module::new("module1", "foo"),
Module::new("module2", "foo"),
]
fn analysis_modules(&self, project: &Project) -> Vec<Module> {
let mut modules = Vec::new();
let dirs = files::list_dirs(Path::new(&project.path));
for each_dir in dirs.iter() {
let module = self.analysis_module(project, each_dir);
match module {
Some(module) => modules.push(module),
_ => continue,
}
}
modules
}

fn analysis_module(&self, project: &Project, module_path: &String) -> Option<Module> {
for module_analyzer in self.module_analyzers.iter() {
return match module_analyzer.is_related(project) {
true => module_analyzer.analysis(module_path),
_ => continue,
};
}
None
}
}

impl Default for JvmProjectStructureAnalyzer {
fn default() -> Self {
JvmProjectStructureAnalyzer {}
JvmProjectStructureAnalyzer {
module_analyzers: vec![Box::new(MavenModuleAnalyzer {})],
}
}
}

impl StructureAnalyzer for JvmProjectStructureAnalyzer {
impl ProjectStructureAnalyzer for JvmProjectStructureAnalyzer {
fn analysis(&self, project_path: &str) -> Project {
let project_name = get_project_name(project_path);
let build_file = get_build_file(project_path).unwrap();
let project_type = get_project_type(build_file);

let mut project = Project::new(project_name.as_str(), project_path, project_type.as_str());
let modules = &mut self.analysis_modules();
let modules = &mut self.analysis_modules(&project);
project.add_modules(modules);
project
}

fn is_related(&self, project_path: &str) -> bool {
let files = list_file_names(project_path);
let files = files::list_file_names(project_path);
for file_name in files.iter() {
if is_build_file(file_name) {
return true;
Expand All @@ -58,7 +77,7 @@ fn get_project_type(build_file: String) -> String {
}

fn get_build_file(path: &str) -> Option<String> {
let files = list_file_names(Path::new(path));
let files = files::list_file_names(Path::new(path));
files.into_iter().find(|file| is_build_file(file))
}

Expand All @@ -79,45 +98,13 @@ fn is_build_file(file_name: &str) -> bool {
}
}

fn list_file_names<P: AsRef<Path>>(path: P) -> Vec<String> {
let mut files = Vec::new();
let walk_dir = WalkDir::new(path);
for dir_entry in walk_dir.max_depth(1).into_iter() {
if dir_entry.is_err() {
panic!("{}", dir_entry.err().unwrap());
}

let entry = dir_entry.unwrap();
if entry.metadata().unwrap().is_file() {
files.push(entry.file_name().to_os_string().into_string().unwrap());
}
}
files
}

#[allow(dead_code)]
fn first_level_dirs<P: AsRef<Path>>(path: P) -> Vec<String> {
let mut dirs = Vec::new();
let walk_dir = WalkDir::new(path);
for dir_entry in walk_dir.max_depth(1).into_iter() {
if dir_entry.is_err() {
panic!("{}", dir_entry.err().unwrap());
}

let entry = dir_entry.unwrap();
if entry.metadata().unwrap().is_dir() {
dirs.push(entry.path().display().to_string())
}
}
dirs
}

#[cfg(test)]
mod tests {
use crate::jvm::psa_jvm::JvmProjectStructureAnalyzer;
use crate::project_structure_analyzer::StructureAnalyzer;
use std::path::PathBuf;

use crate::jvm::psa_jvm::JvmProjectStructureAnalyzer;
use crate::ProjectStructureAnalyzer;

#[test]
fn should_analysis_maven_project_sub_modules() {
let project_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
Expand All @@ -134,7 +121,14 @@ mod tests {

let project = analyzer.analysis(project_dir.display().to_string().as_str());

let modules = project.modules;
let project_module = modules.get(0).unwrap();
let module1 = modules.get(1).unwrap();
let module2 = modules.get(2).unwrap();
assert_eq!(modules.len(), 3);
assert_eq!(project.project_type, "maven");
assert_eq!(project.modules.len(), 3);
assert_eq!(project_module.name, "multi_mod_maven_project");
assert_eq!(module1.name, "module1");
assert_eq!(module2.name, "module2");
}
}
23 changes: 14 additions & 9 deletions psa/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
pub mod pas_content_root;
pub mod project_structure_analyzer;
pub mod psa_facet;
pub mod psa_library;
pub mod psa_module;
pub mod psa_project;

pub mod jvm;

pub use pas_content_root::ContentRoot;
pub use project_structure_analyzer::ProjectAnalyzer;
pub use psa_facet::Facet;
pub use psa_library::Library;
pub use psa_library::LibraryScope;
pub use psa_module::Module;
pub use psa_project::Project;

pub mod files;
pub mod jvm;
pub mod pas_content_root;
pub mod project_structure_analyzer;
pub mod psa_facet;
pub mod psa_library;
pub mod psa_module;
pub mod psa_project;

pub trait ProjectStructureAnalyzer {
fn analysis(&self, project_path: &str) -> Project;
fn is_related(&self, project_path: &str) -> bool;
}
8 changes: 2 additions & 6 deletions psa/src/project_structure_analyzer.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
use crate::jvm::psa_jvm::JvmProjectStructureAnalyzer;
use crate::psa_project::Project;

pub trait StructureAnalyzer {
fn analysis(&self, project_path: &str) -> Project;
fn is_related(&self, project_path: &str) -> bool;
}
use crate::ProjectStructureAnalyzer;

pub struct ProjectAnalyzer {
analyzers: Vec<Box<dyn StructureAnalyzer>>,
analyzers: Vec<Box<dyn ProjectStructureAnalyzer>>,
}

impl ProjectAnalyzer {
Expand Down

0 comments on commit 32abe0b

Please sign in to comment.