use std::sync::{Arc, Weak};
use arcstr::ArcStr;
use dashmap::DashMap;
use oxc_index::IndexVec;
use rolldown_common::{
ModuleIdx, SharedFileEmitter, SharedModuleInfoDashMap, SharedNormalizedBundlerOptions,
};
use rolldown_resolver::Resolver;
use rolldown_utils::dashmap::FxDashSet;
use crate::{
__inner::SharedPluginable,
PluginContext,
plugin_context::{NativePluginContextImpl, PluginContextMeta},
plugin_driver::{ContextLoadCompletionManager, hook_orders::PluginHookOrders},
type_aliases::{IndexPluginContext, IndexPluginable},
types::hook_timing::HookTimingCollector,
};
use rolldown_error::EventKindSwitcher;
pub struct PluginDriverFactory {
plugins: Vec<SharedPluginable>,
resolver: Arc<Resolver>,
}
impl PluginDriverFactory {
pub fn new(plugins: Vec<SharedPluginable>, resolver: &Arc<Resolver>) -> Self {
Self { plugins, resolver: Arc::clone(resolver) }
}
pub fn create_plugin_driver(
&self,
file_emitter: &SharedFileEmitter,
options: &SharedNormalizedBundlerOptions,
session: &rolldown_devtools::Session,
initial_bundle_span: &Arc<tracing::Span>,
module_infos: SharedModuleInfoDashMap,
transform_dependencies: Arc<DashMap<ModuleIdx, Arc<FxDashSet<ArcStr>>>>,
) -> Arc<crate::plugin_driver::PluginDriver> {
let watch_files = Arc::new(FxDashSet::default());
let meta = Arc::new(PluginContextMeta::default());
let tx = Arc::new(std::sync::Mutex::new(None));
let mut plugin_usage_vec = IndexVec::new();
let bundle_span_arc = Arc::clone(initial_bundle_span);
let manual_resolve_span_arc = Arc::new(tracing::debug_span!(
parent: bundle_span_arc.as_ref(),
"plugin_context_resolve",
CONTEXT_hook_resolve_id_trigger = "manual"
));
let hook_timing_collector = if options.checks.contains(EventKindSwitcher::PluginTimings) {
Some(Arc::new(HookTimingCollector::default()))
} else {
None
};
Arc::new_cyclic(|plugin_driver| {
let mut index_plugins = IndexPluginable::with_capacity(self.plugins.len());
let mut index_contexts = IndexPluginContext::with_capacity(self.plugins.len());
self.plugins.iter().for_each(|plugin| {
let plugin_idx = index_plugins.push(Arc::clone(plugin));
plugin_usage_vec.push(plugin.call_hook_usage());
let plugin_name = plugin.call_name();
if let Some(ref collector) = hook_timing_collector {
if !plugin_name.starts_with("builtin:") {
collector.register_plugin(plugin_idx, ArcStr::from(plugin_name.as_ref()));
}
}
index_contexts.push(PluginContext::Native(Arc::new(NativePluginContextImpl {
plugin_name,
skipped_resolve_calls: vec![],
plugin_idx,
plugin_driver: Weak::clone(plugin_driver),
meta: Arc::clone(&meta),
resolver: Arc::clone(&self.resolver),
file_emitter: Arc::clone(file_emitter),
module_infos: Arc::clone(&module_infos),
options: Arc::clone(options),
watch_files: Arc::clone(&watch_files),
tx: Arc::clone(&tx),
session: session.clone(),
bundle_span: Arc::clone(&bundle_span_arc),
manual_resolve_span: Arc::clone(&manual_resolve_span_arc),
})));
});
crate::plugin_driver::PluginDriver {
hook_orders: PluginHookOrders::new(&index_plugins, &plugin_usage_vec),
plugins: index_plugins,
contexts: index_contexts,
file_emitter: Arc::clone(file_emitter),
watch_files,
module_infos,
transform_dependencies,
context_load_completion_manager: ContextLoadCompletionManager::default(),
tx,
hook_timing_collector: hook_timing_collector.clone(),
}
})
}
}