use super::{module::Module, Ident, ModuleName};
use crate::language::Visibility;
use rustc_hash::FxHasher;
use std::hash::BuildHasherDefault;
use sway_types::{span::Span, ProgramId};
#[derive(Clone, Debug)]
pub struct Package {
root_module: Module,
pub program_id: ProgramId,
is_contract_package: bool,
pub external_packages: im::HashMap<ModuleName, Package, BuildHasherDefault<FxHasher>>,
}
impl Package {
pub fn new(
package_name: Ident,
span: Option<Span>,
program_id: ProgramId,
is_contract_package: bool,
) -> Self {
let root_module = Module::new(package_name, Visibility::Public, span, &vec![]);
Self {
root_module,
program_id,
is_contract_package,
external_packages: Default::default(),
}
}
pub fn add_external(&mut self, package_name: String, external_package: Package) {
assert!(!self.external_packages.contains_key(&package_name));
self.external_packages
.insert(package_name, external_package);
}
pub fn root_module(&self) -> &Module {
&self.root_module
}
pub fn root_module_mut(&mut self) -> &mut Module {
&mut self.root_module
}
pub fn name(&self) -> &Ident {
self.root_module.name()
}
pub fn program_id(&self) -> ProgramId {
self.program_id
}
pub(crate) fn check_path_is_in_package(&self, mod_path: &[Ident]) -> bool {
!mod_path.is_empty() && mod_path[0] == *self.root_module.name()
}
pub(crate) fn package_relative_path(mod_path: &[Ident]) -> &[Ident] {
&mod_path[1..]
}
pub(super) fn is_contract_package(&self) -> bool {
self.is_contract_package
}
pub fn module_from_absolute_path(&self, mod_path: &[Ident]) -> Option<&Module> {
assert!(!mod_path.is_empty());
let package_relative_path = Self::package_relative_path(mod_path);
if mod_path[0] == *self.root_module.name() {
self.root_module.submodule(package_relative_path)
} else if let Some(external_package) = self.external_packages.get(mod_path[0].as_str()) {
external_package
.root_module()
.submodule(package_relative_path)
} else {
None
}
}
}