use std::collections::hash_map::Entry;
use rspack_core::DependencyRange;
use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
use swc_core::common::Span;
use super::plugin::TopLevelSymbol;
use crate::parser_plugin::inner_graph::plugin::{
InnerGraphMapSetValue, InnerGraphMapUsage, InnerGraphMapValue,
};
#[derive(Debug, Clone)]
pub enum InnerGraphUsageOperation {
PureExpression(DependencyRange),
ESMImportSpecifier(usize),
URLDependency(usize),
}
#[derive(Default)]
pub struct InnerGraphState {
pub(crate) inner_graph: HashMap<TopLevelSymbol, InnerGraphMapValue>,
pub(crate) usage_map: HashMap<TopLevelSymbol, Vec<InnerGraphUsageOperation>>,
current_top_level_symbol: Option<TopLevelSymbol>,
enable: bool,
pub(crate) statement_with_top_level_symbol: HashMap<Span, TopLevelSymbol>,
pub(crate) statement_pure_part: HashMap<Span, Span>,
pub(crate) class_with_top_level_symbol: HashMap<Span, TopLevelSymbol>,
pub(crate) decl_with_top_level_symbol: HashMap<Span, TopLevelSymbol>,
pub(crate) pure_declarators: HashSet<Span>,
}
impl InnerGraphState {
pub fn new() -> Self {
Self {
..Default::default()
}
}
pub fn enable(&mut self) {
self.enable = true;
}
pub fn bailout(&mut self) {
self.enable = false;
}
pub fn is_enabled(&self) -> bool {
self.enable
}
pub fn set_top_level_symbol(&mut self, symbol: Option<TopLevelSymbol>) {
self.current_top_level_symbol = symbol;
}
pub fn get_top_level_symbol(&self) -> Option<TopLevelSymbol> {
if self.is_enabled() {
self.current_top_level_symbol.clone()
} else {
None
}
}
pub fn add_usage(&mut self, symbol: TopLevelSymbol, usage: InnerGraphMapUsage) {
if !self.is_enabled() {
return;
}
match usage {
InnerGraphMapUsage::True => {
self.inner_graph.insert(symbol, InnerGraphMapValue::True);
}
InnerGraphMapUsage::Value(_) | InnerGraphMapUsage::TopLevel(_) => {
let set_value: InnerGraphMapSetValue = usage.into();
match self.inner_graph.entry(symbol) {
Entry::Occupied(mut occ) => {
let val = occ.get_mut();
match val {
InnerGraphMapValue::Set(set) => {
set.insert(set_value);
}
InnerGraphMapValue::True => {
}
InnerGraphMapValue::Nil => {
*val = InnerGraphMapValue::Set(HashSet::from_iter([set_value]));
}
}
}
Entry::Vacant(vac) => {
vac.insert(InnerGraphMapValue::Set(HashSet::from_iter([set_value])));
}
}
}
}
}
}