Repository: rolldown/rolldown
Pull request #3842: chore: generate EventKindSwitch converter from ChecksOption
Author: login: IWANABETHATGUY
Labels: name: needs-triage
Created: 2025-03-13T11:06:56Z | Merged: 2025-03-13T15:06:52Z

<!-- Thank you for contributing! -->

### Description

<!-- Please insert your description here and provide especially info about the "what" this PR is solving -->



Diff:
diff --git a/crates/rolldown/src/stages/link_stage/sort_modules.rs b/crates/rolldown/src/stages/link_stage/sort_modules.rs
index 2d82c9900608..aade033e2f8b 100644
--- a/crates/rolldown/src/stages/link_stage/sort_modules.rs
+++ b/crates/rolldown/src/stages/link_stage/sort_modules.rs
@@ -1,7 +1,7 @@
 use std::iter;
 
 use rolldown_common::{Module, ModuleIdx};
-use rolldown_error::BuildDiagnostic;
+use rolldown_error::{BuildDiagnostic, EventKindSwitcher};
 use rolldown_utils::rustc_hash::FxHashSetExt;
 use rustc_hash::{FxHashMap, FxHashSet};
 
@@ -52,7 +52,7 @@ impl LinkStage<'_> {
       match status {
         Status::ToBeExecuted(id) => {
           if executed_ids.contains(&id) {
-            if self.options.checks.circular_dependency.unwrap_or(false) {
+            if self.options.checks.contains(EventKindSwitcher::CircularDependency) {
               // Try to check if there is a circular dependency
               if let Some(index) = stack_indexes_of_executing_id.get(&id).copied() {
                 // Executing
diff --git a/crates/rolldown/src/utils/normalize_options.rs b/crates/rolldown/src/utils/normalize_options.rs
index 1cd06e676027..11b901f9df79 100644
--- a/crates/rolldown/src/utils/normalize_options.rs
+++ b/crates/rolldown/src/utils/normalize_options.rs
@@ -231,7 +231,7 @@ pub fn normalize_options(mut raw_options: crate::BundlerOptions) -> NormalizeOpt
     external_live_bindings: raw_options.external_live_bindings.unwrap_or(true),
     inline_dynamic_imports,
     advanced_chunks: raw_options.advanced_chunks,
-    checks: raw_options.checks.unwrap_or_default(),
+    checks: raw_options.checks.unwrap_or_default().into(),
     jsx: raw_options.jsx.unwrap_or_default(),
     watch: raw_options.watch.unwrap_or_default(),
     comments: raw_options.comments.unwrap_or(Comments::Preserve),
diff --git a/crates/rolldown_common/src/generated/checks_options.rs b/crates/rolldown_common/src/generated/checks_options.rs
index 51ab4435585c..8edae120efdd 100644
--- a/crates/rolldown_common/src/generated/checks_options.rs
+++ b/crates/rolldown_common/src/generated/checks_options.rs
@@ -23,3 +23,43 @@ pub struct ChecksOptions {
   pub common_js_variable_in_esm: Option<bool>,
   pub import_is_undefined: Option<bool>,
 }
+impl From<ChecksOptions> for rolldown_error::EventKindSwitcher {
+  fn from(value: ChecksOptions) -> Self {
+    let mut flag = rolldown_error::EventKindSwitcher::all();
+    flag.set(
+      rolldown_error::EventKindSwitcher::CircularDependency,
+      value.circular_dependency.unwrap_or(false),
+    );
+    flag.set(rolldown_error::EventKindSwitcher::Eval, value.eval.unwrap_or(true));
+    flag.set(
+      rolldown_error::EventKindSwitcher::MissingGlobalName,
+      value.missing_global_name.unwrap_or(true),
+    );
+    flag.set(
+      rolldown_error::EventKindSwitcher::MissingNameOptionForIifeExport,
+      value.missing_name_option_for_iife_export.unwrap_or(true),
+    );
+    flag.set(rolldown_error::EventKindSwitcher::MixedExport, value.mixed_export.unwrap_or(true));
+    flag.set(
+      rolldown_error::EventKindSwitcher::UnresolvedEntry,
+      value.unresolved_entry.unwrap_or(true),
+    );
+    flag.set(
+      rolldown_error::EventKindSwitcher::UnresolvedImport,
+      value.unresolved_import.unwrap_or(true),
+    );
+    flag.set(
+      rolldown_error::EventKindSwitcher::FilenameConflict,
+      value.filename_conflict.unwrap_or(true),
+    );
+    flag.set(
+      rolldown_error::EventKindSwitcher::CommonJsVariableInEsm,
+      value.common_js_variable_in_esm.unwrap_or(true),
+    );
+    flag.set(
+      rolldown_error::EventKindSwitcher::ImportIsUndefined,
+      value.import_is_undefined.unwrap_or(true),
+    );
+    flag
+  }
+}
diff --git a/crates/rolldown_common/src/inner_bundler_options/types/normalized_bundler_options.rs b/crates/rolldown_common/src/inner_bundler_options/types/normalized_bundler_options.rs
index 0bd0d3d2766c..8efcb020fd55 100644
--- a/crates/rolldown_common/src/inner_bundler_options/types/normalized_bundler_options.rs
+++ b/crates/rolldown_common/src/inner_bundler_options/types/normalized_bundler_options.rs
@@ -6,6 +6,7 @@ use std::sync::Arc;
 
 use arcstr::ArcStr;
 use oxc::transformer::{InjectGlobalVariablesConfig, JsxOptions, TransformOptions};
+use rolldown_error::EventKindSwitcher;
 use rustc_hash::{FxHashMap, FxHashSet};
 
 use super::advanced_chunks_options::AdvancedChunksOptions;
@@ -24,9 +25,9 @@ use super::{
   sourcemap_ignore_list::SourceMapIgnoreList, sourcemap_path_transform::SourceMapPathTransform,
 };
 use crate::{
-  ChecksOptions, DeferSyncScanDataOption, EmittedAsset, EsModuleFlag, FilenameTemplate,
-  GlobalsOutputOption, HashCharacters, InjectImport, InputItem, MakeAbsoluteExternalsRelative,
-  ModuleType, RollupPreRenderedAsset,
+  DeferSyncScanDataOption, EmittedAsset, EsModuleFlag, FilenameTemplate, GlobalsOutputOption,
+  HashCharacters, InjectImport, InputItem, MakeAbsoluteExternalsRelative, ModuleType,
+  RollupPreRenderedAsset,
 };
 
 #[allow(clippy::struct_excessive_bools)] // Using raw booleans is more clear in this case
@@ -78,7 +79,7 @@ pub struct NormalizedBundlerOptions {
   pub external_live_bindings: bool,
   pub inline_dynamic_imports: bool,
   pub advanced_chunks: Option<AdvancedChunksOptions>,
-  pub checks: ChecksOptions,
+  pub checks: EventKindSwitcher,
   pub profiler_names: bool,
   pub jsx: Jsx,
   pub watch: WatchOption,
diff --git a/crates/rolldown_error/src/generated/event_kind_switcher.rs b/crates/rolldown_error/src/generated/event_kind_switcher.rs
index 5e6de071d1a8..5146eefc02e5 100644
--- a/crates/rolldown_error/src/generated/event_kind_switcher.rs
+++ b/crates/rolldown_error/src/generated/event_kind_switcher.rs
@@ -3,7 +3,7 @@
 
 use bitflags::bitflags;
 bitflags! {
-  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
   pub struct EventKindSwitcher: u32 {
     const AmbiguousExternalNamespaceError = 1 << 0;
     const CircularDependency = 1 << 1;
diff --git a/crates/rolldown_error/src/lib.rs b/crates/rolldown_error/src/lib.rs
index f1227d957c27..58365985da43 100644
--- a/crates/rolldown_error/src/lib.rs
+++ b/crates/rolldown_error/src/lib.rs
@@ -18,6 +18,7 @@ pub use crate::{
   events::commonjs_variable_in_esm::CjsExportSpan,
   events::invalid_option::InvalidOptionType,
   events::unloadable_dependency::UnloadableDependencyContext,
+  generated::event_kind_switcher::EventKindSwitcher,
   locator::line_column_to_byte_offset,
   type_aliases::{BuildResult, SingleBuildResult},
   types::diagnostic_options::DiagnosticOptions,
diff --git a/crates/rolldown_error/src/types/diagnostic_container.rs b/crates/rolldown_error/src/types/diagnostic_container.rs
new file mode 100644
index 000000000000..077efa7208ef
--- /dev/null
+++ b/crates/rolldown_error/src/types/diagnostic_container.rs
@@ -0,0 +1,23 @@
+use crate::{BuildDiagnostic, EventKindSwitcher};
+
+#[allow(unused)]
+pub struct DiagnosticContainer {
+  pub diagnostics: Vec<BuildDiagnostic>,
+  pub event_kind_switcher: EventKindSwitcher,
+}
+
+#[allow(unused)]
+impl DiagnosticContainer {
+  pub fn new(switcher: EventKindSwitcher) -> Self {
+    Self { diagnostics: vec![], event_kind_switcher: switcher }
+  }
+
+  pub fn push(&mut self, diagnostic: BuildDiagnostic) {
+    if self
+      .event_kind_switcher
+      .contains(EventKindSwitcher::from_bits_truncate(1 << diagnostic.kind() as u32))
+    {
+      self.diagnostics.push(diagnostic);
+    }
+  }
+}
diff --git a/crates/rolldown_error/src/types/mod.rs b/crates/rolldown_error/src/types/mod.rs
index 8825a0aef1ba..607534a3a900 100644
--- a/crates/rolldown_error/src/types/mod.rs
+++ b/crates/rolldown_error/src/types/mod.rs
@@ -1,2 +1,3 @@
+pub mod diagnostic_container;
 pub mod diagnostic_options;
 pub mod result_ext;
diff --git a/tasks/gen_options/src/generators/checks.rs b/tasks/gen_options/src/generators/checks.rs
index 72e7469060ea..fff8b84517bd 100644
--- a/tasks/gen_options/src/generators/checks.rs
+++ b/tasks/gen_options/src/generators/checks.rs
@@ -12,7 +12,9 @@ use crate::{
 
 use super::{Context, Generator, Runner};
 
-pub struct CheckOptionsGenerator;
+pub struct CheckOptionsGenerator {
+  pub disabled_event: Vec<&'static str>,
+}
 
 define_generator!(CheckOptionsGenerator);
 
@@ -33,7 +35,7 @@ impl Generator for CheckOptionsGenerator {
       &validator_path.to_string_lossy(),
     );
     let (checks_binding_option_ts, checks_inner_option_ts) =
-      generate_check_inner_options_and_binding(&variant_and_number_pairs);
+      generate_check_inner_options_and_binding(&variant_and_number_pairs, self);
     Ok(vec![
       crate::output::Output::RustString {
         path: rust_output_path("crates/rolldown_error", "event_kind_switcher.rs"),
@@ -116,7 +118,7 @@ fn generate_event_kind_switch_config(variant_and_number_pairs: &Vec<(String, usi
     r"
 use bitflags::bitflags;
 bitflags! {{
-  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
   pub struct EventKindSwitcher: u{type_size} {{
     {}
   }}
@@ -128,20 +130,27 @@ bitflags! {{
 
 fn generate_check_inner_options_and_binding(
   variant_and_number_pairs: &Vec<(String, usize)>,
+  generator: &CheckOptionsGenerator,
 ) -> (TokenStream, TokenStream) {
   let mut struct_fields = vec![];
   let mut field_initializer_list = vec![];
+  let mut event_kind_switcher_initializer = vec![];
   for (variant, _) in variant_and_number_pairs {
     if variant.ends_with("Error") {
       continue;
     }
     let snake_case = quote::format_ident!("{}", variant.to_snake_case());
+    let ident = quote::format_ident!("{}", variant);
+    let default_status = !generator.disabled_event.contains(&variant.as_str());
     struct_fields.push(quote! {
       pub #snake_case: Option<bool>,
     });
     field_initializer_list.push(quote! {
       #snake_case: value.#snake_case,
     });
+    event_kind_switcher_initializer.push(quote! {
+        flag.set(rolldown_error::EventKindSwitcher::#ident, value.#snake_case.unwrap_or(#default_status));
+    });
   }
   let check_options_struct = quote! {
     #[napi_derive::napi(object)]
@@ -179,6 +188,13 @@ fn generate_check_inner_options_and_binding(
     pub struct ChecksOptions {
       #(#struct_fields)*
     }
+    impl From<ChecksOptions> for rolldown_error::EventKindSwitcher {
+      fn from(value: ChecksOptions) -> Self {
+        let mut flag = rolldown_error::EventKindSwitcher::all();
+        #(#event_kind_switcher_initializer)*
+        flag
+      }
+    }
   };
 
   (binding_ts, inner_option_ts)
diff --git a/tasks/gen_options/src/main.rs b/tasks/gen_options/src/main.rs
index 07a0eedeb80c..7f6e1ae6566f 100644
--- a/tasks/gen_options/src/main.rs
+++ b/tasks/gen_options/src/main.rs
@@ -1,7 +1,8 @@
 use gen_options::generators::{CheckOptionsGenerator, Context, Generator};
 fn main() -> anyhow::Result<()> {
   let ctx = Context { workspace_root: rolldown_workspace::root_dir() };
-  let generators: Vec<Box<dyn Generator>> = vec![Box::new(CheckOptionsGenerator)];
+  let generators: Vec<Box<dyn Generator>> =
+    vec![Box::new(CheckOptionsGenerator { disabled_event: vec!["CircularDependency"] })];
   for generator in generators {
     let outputs = generator.run(&ctx)?;
     for output in outputs {


Reviews:
user: login: IWANABETHATGUY
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-13T11:08:33Z
user: login: IWANABETHATGUY
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-13T11:08:48Z
user: login: hyf0
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-13T11:44:34Z

Review comments:
diff_hunk: @@ -0,0 +1,23 @@
+use crate::{BuildDiagnostic, EventKindSwitcher};
+
+#[allow(unused)]
+pub struct DiagnosticContainer {
path: crates/rolldown_error/src/types/diagnostic_container.rs
user: login: IWANABETHATGUY
body: This struct is used to auto filter disabled Diagnostic
created_at: 2025-03-13T11:08:32Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,23 @@
+use crate::{BuildDiagnostic, EventKindSwitcher};
+
+#[allow(unused)]
+pub struct DiagnosticContainer {
path: crates/rolldown_error/src/types/diagnostic_container.rs
user: login: IWANABETHATGUY
body: Will be used in rest pr.
created_at: 2025-03-13T11:08:48Z
author_association: MEMBER

PR comments:
user: login: IWANABETHATGUY
created_at: 2025-03-13T11:07:22Z
body: * **#3842** <a href="https://app.graphite.dev/github/pr/rolldown/rolldown/3842?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a> 👈 <a href="https://app.graphite.dev/github/pr/rolldown/rolldown/3842?utm_source=stack-comment-view-in-graphite" target="_blank">(View in Graphite)</a>
* `main`


<h2></h2>

This stack of pull requests is managed by <a href="https://graphite.dev?utm-source=stack-comment"><b>Graphite</b></a>. Learn more about <a href="https://stacking.dev/?utm_source=stack-comment">stacking</a>.
<!-- Current dependencies on/for this PR: -->
author_association: MEMBER
user: login: netlify[bot]
created_at: 2025-03-13T11:07:29Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *rolldown-rs* canceled.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | b4ea34c21d494f97bc42b0f219a5de3d00086b0d |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/rolldown-rs/deploys/67d2bc56075ffa000943afe0 |
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-13T11:21:26Z
body: ### Benchmarks Rust
- target: `main`(7b4d25e0e3ef42e6ef0559f0ac0770a7a9126db4)
- pr: `03-13-chore_generate_eventkindswitch_converter_from_checksoption`(b4ea34c21d494f97bc42b0f219a5de3d00086b0d)
```
group                                                               pr                                     target
-----                                                               --                                     ------
bundle/bundle@multi-duplicated-top-level-symbol                     1.00     76.3±3.41ms        ? ?/sec    1.13    86.2±11.13ms        ? ?/sec
bundle/bundle@multi-duplicated-top-level-symbol-minify              1.00     97.0±2.20ms        ? ?/sec    1.07    103.6±3.95ms        ? ?/sec
bundle/bundle@multi-duplicated-top-level-symbol-minify-sourcemap    1.00    112.0±3.91ms        ? ?/sec    1.00    111.9±2.91ms        ? ?/sec
bundle/bundle@multi-duplicated-top-level-symbol-sourcemap           1.00     88.3±2.35ms        ? ?/sec    1.08    95.5±12.03ms        ? ?/sec
bundle/bundle@rome-ts                                               1.00    140.0±3.72ms        ? ?/sec    1.01   141.1±18.13ms        ? ?/sec
bundle/bundle@rome-ts-minify                                        1.00    254.4±7.59ms        ? ?/sec    1.07   272.2±43.12ms        ? ?/sec
bundle/bundle@rome-ts-minify-sourcemap                              1.00   285.1±11.07ms        ? ?/sec    1.05   298.0±32.32ms        ? ?/sec
bundle/bundle@rome-ts-sourcemap                                     1.00    157.8±4.83ms        ? ?/sec    1.00   157.4±23.72ms        ? ?/sec
bundle/bundle@threejs                                               1.11     48.8±3.81ms        ? ?/sec    1.00     43.9±3.16ms        ? ?/sec
bundle/bundle@threejs-minify                                        1.07    113.5±1.75ms        ? ?/sec    1.00   105.8±14.46ms        ? ?/sec
bundle/bundle@threejs-minify-sourcemap                              1.13    141.1±3.26ms        ? ?/sec    1.00   125.0±12.54ms        ? ?/sec
bundle/bundle@threejs-sourcemap                                     1.03     54.2±1.45ms        ? ?/sec    1.00     52.5±1.20ms        ? ?/sec
bundle/bundle@threejs10x                                            1.00    479.9±7.57ms        ? ?/sec    1.01   483.9±22.83ms        ? ?/sec
bundle/bundle@threejs10x-minify                                     1.00   1189.0±9.65ms        ? ?/sec    1.01  1197.4±30.96ms        ? ?/sec
bundle/bundle@threejs10x-minify-sourcemap                           1.02  1382.9±19.75ms        ? ?/sec    1.00  1358.1±55.89ms        ? ?/sec
bundle/bundle@threejs10x-sourcemap                                  1.02   567.1±13.34ms        ? ?/sec    1.00   556.7±23.38ms        ? ?/sec
remapping/remapping                                                 1.01     27.2±1.29ms        ? ?/sec    1.00     26.9±2.26ms        ? ?/sec
remapping/render-chunk-remapping                                    1.00     64.4±3.17ms        ? ?/sec    1.02     65.9±0.50ms        ? ?/sec
scan/scan@rome-ts                                                   1.00     99.1±2.55ms        ? ?/sec    1.10    108.7±2.00ms        ? ?/sec
scan/scan@threejs                                                   1.00     31.7±0.38ms        ? ?/sec    1.07     33.9±0.63ms        ? ?/sec
scan/scan@threejs10x                                                1.00    323.2±3.97ms        ? ?/sec    1.05    339.8±6.52ms        ? ?/sec
```
author_association: CONTRIBUTOR