use std::{collections::HashMap, sync::Arc};
use genotype_parser::tree::{GTIdentifier, GTImportName, GTImportReference, GTPath};
use super::{GTProjectModuleParse, GTProjectModulePath};
#[derive(Debug, PartialEq, Clone)]
pub struct GTProjectModuleResolve {
pub deps: HashMap<GTPath, Arc<GTProjectModulePath>>,
pub references: HashMap<GTIdentifier, GTProjectModuleReference>,
}
impl GTProjectModuleResolve {
pub fn try_new(
modules: &Vec<GTProjectModuleParse>,
parse: >ProjectModuleParse,
) -> Result<Self, Box<dyn std::error::Error>> {
let mut deps = HashMap::new();
for local_path in parse.1.resolve.deps.iter() {
if deps.contains_key(local_path) {
continue;
}
let path = Arc::new(parse.0.resolve(local_path)?);
deps.insert(local_path.clone(), path);
}
let mut references = HashMap::new();
for reference in parse.1.resolve.references.iter() {
if references.contains_key(reference) {
continue;
};
if parse.1.resolve.exports.contains(reference) {
references.insert(reference.clone(), GTProjectModuleReference::Local);
continue;
}
let (local_path, _) = deps
.iter()
.find(|(local_path, path)| {
let import = parse.1.module.imports.iter().find(|import| {
if import.path != **local_path {
return false;
}
match &import.reference {
GTImportReference::Glob => {
let module =
modules.iter().find(|module| module.0 == ***path).unwrap();
module.1.resolve.exports.contains(reference)
}
GTImportReference::Name(name) => *name == *reference,
GTImportReference::Names(names) => {
names.iter().any(|name| match name {
GTImportName::Name(name) => name == reference,
GTImportName::Alias(_, alias) => alias == reference,
})
}
}
});
!import.is_none()
})
.unwrap();
references.insert(
reference.clone(),
GTProjectModuleReference::External(local_path.clone()),
);
}
Ok(GTProjectModuleResolve { deps, references })
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum GTProjectModuleReference {
Local,
External(GTPath),
}