use oxc_index::IndexVec;
use rolldown_common::PluginIdx;
use crate::{
__inner::SharedPluginable, HookUsage, PluginHookMeta, PluginOrder, type_aliases::IndexPluginable,
};
#[expect(clippy::struct_field_names)] #[derive(Clone)]
pub struct PluginHookOrders {
pub order_by_build_start_meta: Vec<PluginIdx>,
pub order_by_resolve_id_meta: Vec<PluginIdx>,
pub order_by_resolve_dynamic_import_meta: Vec<PluginIdx>,
pub order_by_load_meta: Vec<PluginIdx>,
pub order_by_transform_meta: Vec<PluginIdx>,
pub order_by_module_parsed_meta: Vec<PluginIdx>,
pub order_by_build_end_meta: Vec<PluginIdx>,
pub order_by_render_start_meta: Vec<PluginIdx>,
pub order_by_banner_meta: Vec<PluginIdx>,
pub order_by_footer_meta: Vec<PluginIdx>,
pub order_by_intro_meta: Vec<PluginIdx>,
pub order_by_outro_meta: Vec<PluginIdx>,
pub order_by_render_chunk_meta: Vec<PluginIdx>,
pub order_by_augment_chunk_hash_meta: Vec<PluginIdx>,
pub order_by_render_error_meta: Vec<PluginIdx>,
pub order_by_generate_bundle_meta: Vec<PluginIdx>,
pub order_by_write_bundle_meta: Vec<PluginIdx>,
pub order_by_close_bundle_meta: Vec<PluginIdx>,
pub order_by_watch_change_meta: Vec<PluginIdx>,
pub order_by_close_watcher_meta: Vec<PluginIdx>,
pub order_by_transform_ast_meta: Vec<PluginIdx>,
}
impl PluginHookOrders {
pub fn new(
index_plugins: &IndexPluginable,
plugin_usage_vec: &IndexVec<PluginIdx, HookUsage>,
) -> Self {
Self {
order_by_build_start_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::BuildStart).then(|| p.call_build_start_meta())
}),
order_by_resolve_id_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::ResolveId).then(|| p.call_resolve_id_meta())
}),
order_by_resolve_dynamic_import_meta: Self::sort_plugins_by_hook_meta(
index_plugins,
|i, p| {
plugin_usage_vec[i]
.contains(HookUsage::ResolveDynamicImport)
.then(|| p.call_resolve_dynamic_import_meta())
},
),
order_by_load_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::Load).then(|| p.call_load_meta())
}),
order_by_transform_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::Transform).then(|| p.call_transform_meta())
}),
order_by_module_parsed_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::ModuleParsed).then(|| p.call_module_parsed_meta())
}),
order_by_build_end_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::BuildEnd).then(|| p.call_build_end_meta())
}),
order_by_render_start_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::RenderStart).then(|| p.call_render_start_meta())
}),
order_by_banner_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::Banner).then(|| p.call_banner_meta())
}),
order_by_footer_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::Footer).then(|| p.call_footer_meta())
}),
order_by_intro_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::Intro).then(|| p.call_intro_meta())
}),
order_by_outro_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::Outro).then(|| p.call_outro_meta())
}),
order_by_render_chunk_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::RenderChunk).then(|| p.call_render_chunk_meta())
}),
order_by_augment_chunk_hash_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i]
.contains(HookUsage::AugmentChunkHash)
.then(|| p.call_augment_chunk_hash_meta())
}),
order_by_render_error_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::RenderError).then(|| p.call_render_error_meta())
}),
order_by_generate_bundle_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i]
.contains(HookUsage::GenerateBundle)
.then(|| p.call_generate_bundle_meta())
}),
order_by_write_bundle_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::WriteBundle).then(|| p.call_write_bundle_meta())
}),
order_by_close_bundle_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::CloseBundle).then(|| p.call_close_bundle_meta())
}),
order_by_watch_change_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::WatchChange).then(|| p.call_watch_change_meta())
}),
order_by_close_watcher_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::CloseWatcher).then(|| p.call_close_watcher_meta())
}),
order_by_transform_ast_meta: Self::sort_plugins_by_hook_meta(index_plugins, |i, p| {
plugin_usage_vec[i].contains(HookUsage::TransformAst).then(|| p.call_transform_ast_meta())
}),
}
}
fn sort_plugins_by_hook_meta(
index_plugins: &IndexPluginable,
get_hook_meta: impl Fn(PluginIdx, &SharedPluginable) -> Option<Option<PluginHookMeta>>,
) -> Vec<PluginIdx> {
let mut pre_plugins = Vec::new();
let mut post_plugins = Vec::new();
let mut normal_plugins = Vec::with_capacity(index_plugins.len());
for (idx, plugin) in index_plugins.iter_enumerated() {
let Some(meta) = get_hook_meta(idx, plugin) else { continue };
match meta {
None => normal_plugins.push(idx),
Some(meta) => match meta.order {
Some(PluginOrder::Pre) => pre_plugins.push(idx),
Some(PluginOrder::Post) => post_plugins.push(idx),
None => normal_plugins.push(idx),
},
}
}
[pre_plugins, normal_plugins, post_plugins].concat()
}
}