Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions tasks/ast_tools/src/generators/estree_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use oxc_index::{IndexVec, define_index_type};

use crate::{
Codegen, Generator, NAPI_PARSER_PACKAGE_PATH, OXLINT_APP_PATH,
output::{Output, javascript::VariantGenerator},
output::{Output, javascript::generate_variants},
schema::Schema,
utils::{FxIndexMap, string, write_it},
};
Expand Down Expand Up @@ -127,7 +127,6 @@ struct NodeKeys {
/// * Visitor keys.
/// * `Map` from node type name to node type ID.
/// * Visitor type definition.
#[expect(clippy::items_after_statements)]
fn generate(codegen: &Codegen) -> Codes {
// Run `napi/parser/scripts/visitor-keys.js` to get visitor keys from TS-ESLint
let script_path = codegen.root_path().join("napi/parser/scripts/visitor-keys.js");
Expand Down Expand Up @@ -377,15 +376,7 @@ fn generate(codegen: &Codegen) -> Codes {

// Create 2 walker variants for parser and oxlint, by setting `ANCESTORS` const,
// and running through minifier to shake out irrelevant code
struct WalkVariantGenerator;
impl VariantGenerator<1> for WalkVariantGenerator {
const FLAG_NAMES: [&str; 1] = ["ANCESTORS"];
}

let mut walk_variants = WalkVariantGenerator.generate(&walk).into_iter();
assert!(walk_variants.len() == 2);
let walk_parser = walk_variants.next().unwrap();
let walk_oxlint = walk_variants.next().unwrap();
let [walk_parser, walk_oxlint] = generate_variants!(&walk, ["ANCESTORS"]);

let leaf_nodes_count = leaf_nodes_count.unwrap();

Expand Down
47 changes: 47 additions & 0 deletions tasks/ast_tools/src/output/javascript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,54 @@ pub trait VariantGenerator<const FLAG_COUNT: usize>: Sync {
})
.collect()
}

/// Generate variants as an array.
///
/// Useful when you want to destructure into multiple variables.
///
/// ```ignore
/// struct Gen;
/// impl VariantGenerator<1> for Gen {
/// const FLAG_NAMES: [&str; 1] = ["ENABLED"];
/// }
/// let [disabled, enabled] = Gen.generate_array(code);
/// ```
///
/// # Panics
/// Panics if `N` is not equal to the number of variants.
fn generate_array<const N: usize>(&mut self, code: &str) -> [String; N] {
let variants = self.generate(code);

assert_eq!(
variants.len(),
N,
"Wrong number of variants - expected {N}, got {}",
variants.len()
);

variants.try_into().unwrap()
}
}

/// Macro to generate variants where all you want is all the possible permutations of a set of flags.
///
/// ```ignore
/// let [disabled, enabled] = generate_variants!(code, ["ENABLED"]);
/// ```
macro_rules! generate_variants {
($code:expr, [$($variant:literal),+]) => {{
use $crate::output::javascript::VariantGenerator;
const FLAG_COUNT: usize = [$($variant),+].len();
const VARIANT_COUNT: usize = 1 << FLAG_COUNT;

struct Gen;
impl VariantGenerator<FLAG_COUNT> for Gen {
const FLAG_NAMES: [&str; FLAG_COUNT] = [$($variant),+];
}
Gen.generate_array::<VARIANT_COUNT>($code)
}};
}
pub(crate) use generate_variants;

/// Parse file.
pub fn parse_js<'a>(source_text: &'a str, allocator: &'a Allocator) -> Program<'a> {
Expand Down
Loading