Skip to content

Commit ea11c5f

Browse files
chore: 🤖 update
1 parent 17597d7 commit ea11c5f

File tree

5 files changed

+489
-577
lines changed

5 files changed

+489
-577
lines changed

‎crates/oxc_semantic/src/builder.rs‎

Lines changed: 34 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ use std::{
55
mem,
66
};
77

8-
use num_bigint::BigInt;
9-
108
use rustc_hash::FxHashMap;
119

1210
use oxc_allocator::Address;
13-
use oxc_ast::{AstKind, ast::*};
11+
use oxc_ast::{AstBuilder, AstKind, ast::*};
1412
use oxc_ast_visit::Visit;
1513
#[cfg(feature = "cfg")]
1614
use oxc_cfg::{
@@ -29,18 +27,22 @@ use oxc_syntax::{
2927
#[cfg(feature = "linter")]
3028
use crate::jsdoc::JSDocBuilder;
3129
use crate::{
32-
const_enum::{ConstEnumTable, ConstEnumMemberValue, ConstEnumMemberInfo, ConstEnumInfo},
3330
Semantic,
3431
binder::{Binder, ModuleInstanceState},
3532
checker,
3633
class::ClassTableBuilder,
34+
const_enum::{
35+
ConstEnumMemberInfo, ConstEnumTable, ConstantEnumCtx, NormalizedConstEnumInfo,
36+
NormalizedConstEnumMemberInfo,
37+
},
3738
diagnostics::redeclaration,
3839
label::UnusedLabels,
3940
node::AstNodes,
4041
scoping::{Bindings, Scoping},
4142
stats::Stats,
4243
unresolved_stack::UnresolvedReferencesStack,
4344
};
45+
use oxc_ecmascript::constant_evaluation::{ConstantEvaluation, ConstantValue};
4446

4547
#[cfg(feature = "cfg")]
4648
macro_rules! control_flow {
@@ -112,7 +114,7 @@ pub struct SemanticBuilder<'a> {
112114
pub(crate) class_table_builder: ClassTableBuilder<'a>,
113115

114116
/// Table for storing const enum information
115-
pub(crate) const_enum_table: ConstEnumTable<'a>,
117+
pub(crate) const_enum_table: ConstEnumTable,
116118

117119
#[cfg(feature = "cfg")]
118120
ast_node_records: Vec<NodeId>,
@@ -2154,11 +2156,6 @@ impl<'a> SemanticBuilder<'a> {
21542156
}
21552157
AstKind::TSEnumDeclaration(enum_declaration) => {
21562158
enum_declaration.bind(self);
2157-
2158-
// Process const enums
2159-
if enum_declaration.r#const {
2160-
self.process_const_enum(enum_declaration);
2161-
}
21622159
}
21632160
AstKind::TSEnumMember(enum_member) => {
21642161
enum_member.bind(self);
@@ -2223,6 +2220,11 @@ impl<'a> SemanticBuilder<'a> {
22232220
// Clear the reference flags that may have been set when entering the node.
22242221
self.current_reference_flags = ReferenceFlags::empty();
22252222
}
2223+
AstKind::TSEnumDeclaration(enum_declaration) => {
2224+
if enum_declaration.r#const {
2225+
self.process_const_enum(enum_declaration);
2226+
}
2227+
}
22262228
_ => {}
22272229
}
22282230
}
@@ -2248,16 +2250,19 @@ impl<'a> SemanticBuilder<'a> {
22482250
/// Process a const enum declaration and evaluate its members
22492251
fn process_const_enum(&mut self, enum_declaration: &TSEnumDeclaration<'a>) {
22502252
// Get the symbol ID for this enum
2251-
let symbol_id = enum_declaration.id.symbol_id.get().expect("enum should have symbol ID");
2252-
2253-
let mut members = std::collections::HashMap::new();
2253+
let symbol_id = enum_declaration.id.symbol_id();
2254+
let current_scope = enum_declaration.scope_id();
2255+
let allocator = oxc_allocator::Allocator::default();
2256+
let ast_builder = AstBuilder::new(&allocator);
2257+
let mut members = FxHashMap::default();
22542258
let mut current_value: f64 = -1.0; // Start at -1, first auto-increment will make it 0
22552259

22562260
for member in &enum_declaration.body.members {
22572261
let member_name = match &member.id {
22582262
TSEnumMemberName::Identifier(ident) => ident.name.as_str(),
2259-
TSEnumMemberName::String(string) => string.value.as_str(),
2260-
TSEnumMemberName::ComputedString(string) => string.value.as_str(),
2263+
TSEnumMemberName::String(string) | TSEnumMemberName::ComputedString(string) => {
2264+
string.value.as_str()
2265+
}
22612266
TSEnumMemberName::ComputedTemplateString(template) => {
22622267
// For computed template strings, we need to evaluate them
22632268
if template.expressions.is_empty() {
@@ -2272,181 +2277,36 @@ impl<'a> SemanticBuilder<'a> {
22722277
}
22732278
}
22742279
};
2275-
2280+
let Some(member_symbol_id) = self.scoping.get_binding(current_scope, member_name)
2281+
else {
2282+
continue;
2283+
};
22762284
let value = if let Some(initializer) = &member.initializer {
2277-
// Evaluate the initializer expression
2278-
let mut visited = std::vec::Vec::new();
2279-
if let Some(evaluated_value) = self.evaluate_const_enum_member(initializer, Some(symbol_id), &mut visited) {
2280-
// Update current_value based on the evaluated value
2281-
match &evaluated_value {
2282-
ConstEnumMemberValue::Number(n) => current_value = *n,
2283-
_ => {} // Don't change current_value for non-numeric values
2284-
}
2285-
evaluated_value
2286-
} else {
2287-
// If evaluation fails, fall back to current_value + 1
2288-
current_value += 1.0;
2289-
ConstEnumMemberValue::Number(current_value)
2290-
}
2285+
let ctx = ConstantEnumCtx::new(&members, &self.scoping, ast_builder);
2286+
initializer.evaluate_value(&ctx).unwrap_or(ConstantValue::Undefined)
22912287
} else {
22922288
// Auto-increment the value
22932289
current_value += 1.0;
2294-
ConstEnumMemberValue::Number(current_value)
2290+
ConstantValue::Number(current_value)
22952291
};
22962292

22972293
let member_info = ConstEnumMemberInfo {
22982294
name: member_name,
22992295
value,
23002296
span: member.span,
23012297
has_initializer: member.initializer.is_some(),
2298+
symbol_id: member_symbol_id,
23022299
};
23032300

2304-
members.insert(member_name, member_info);
2301+
members.insert(member_symbol_id, member_info);
23052302
}
23062303

2307-
let enum_info = ConstEnumInfo {
2308-
symbol_id,
2309-
members,
2310-
span: enum_declaration.span,
2311-
};
2304+
let members = members
2305+
.into_iter()
2306+
.map(|(symbol_id, member)| (symbol_id, member.into()))
2307+
.collect::<FxHashMap<SymbolId, NormalizedConstEnumMemberInfo>>();
2308+
let enum_info = NormalizedConstEnumInfo { symbol_id, members, span: enum_declaration.span };
23122309

23132310
self.const_enum_table.add_enum(symbol_id, enum_info);
23142311
}
2315-
2316-
/// Evaluate a const enum member's value with improved JavaScript semantics
2317-
fn evaluate_const_enum_member(
2318-
&self,
2319-
expression: &Expression<'a>,
2320-
current_enum: Option<SymbolId>,
2321-
_visited: &mut std::vec::Vec<&'a str>,
2322-
) -> Option<ConstEnumMemberValue<'a>> {
2323-
match expression {
2324-
Expression::StringLiteral(string) => Some(ConstEnumMemberValue::String(string.value.as_str())),
2325-
Expression::NumericLiteral(number) => Some(ConstEnumMemberValue::Number(number.value)),
2326-
Expression::BooleanLiteral(boolean) => Some(ConstEnumMemberValue::Boolean(boolean.value)),
2327-
Expression::BigIntLiteral(bigint) => {
2328-
bigint.value.parse::<BigInt>().ok().map(ConstEnumMemberValue::BigInt)
2329-
}
2330-
Expression::UnaryExpression(unary) => {
2331-
if let Some(argument) = self.evaluate_const_enum_member(&unary.argument, current_enum, _visited) {
2332-
self.evaluate_unary_operation(unary, argument)
2333-
} else {
2334-
None
2335-
}
2336-
}
2337-
Expression::BinaryExpression(binary) => {
2338-
if let (Some(left), Some(right)) = (
2339-
self.evaluate_const_enum_member(&binary.left, current_enum, _visited),
2340-
self.evaluate_const_enum_member(&binary.right, current_enum, _visited),
2341-
) {
2342-
self.evaluate_binary_operation(binary, left, right)
2343-
} else {
2344-
None
2345-
}
2346-
}
2347-
Expression::Identifier(ident) => {
2348-
// Try to resolve this as a reference to another const enum member
2349-
let name = ident.name.as_str();
2350-
2351-
if let Some(current_enum_id) = current_enum {
2352-
if let Some(enum_info) = self.const_enum_table.get_enum(current_enum_id) {
2353-
if let Some(member_info) = enum_info.members.get(name) {
2354-
return Some(member_info.value.clone());
2355-
}
2356-
}
2357-
}
2358-
None
2359-
}
2360-
_ => None,
2361-
}
2362-
}
2363-
2364-
/// Evaluate unary operations with proper JavaScript semantics
2365-
fn evaluate_unary_operation(
2366-
&self,
2367-
unary: &UnaryExpression<'a>,
2368-
argument: ConstEnumMemberValue<'a>,
2369-
) -> Option<ConstEnumMemberValue<'a>> {
2370-
match unary.operator {
2371-
UnaryOperator::UnaryNegation => {
2372-
match argument {
2373-
ConstEnumMemberValue::Number(n) => Some(ConstEnumMemberValue::Number(-n)),
2374-
_ => None,
2375-
}
2376-
}
2377-
UnaryOperator::UnaryPlus => {
2378-
match argument {
2379-
ConstEnumMemberValue::Number(n) => Some(ConstEnumMemberValue::Number(n)),
2380-
_ => None,
2381-
}
2382-
}
2383-
UnaryOperator::LogicalNot => {
2384-
match argument {
2385-
ConstEnumMemberValue::Boolean(b) => Some(ConstEnumMemberValue::Boolean(!b)),
2386-
_ => None,
2387-
}
2388-
}
2389-
_ => None,
2390-
}
2391-
}
2392-
2393-
/// Evaluate binary operations with proper JavaScript semantics
2394-
fn evaluate_binary_operation(
2395-
&self,
2396-
binary: &BinaryExpression<'a>,
2397-
left: ConstEnumMemberValue<'a>,
2398-
right: ConstEnumMemberValue<'a>,
2399-
) -> Option<ConstEnumMemberValue<'a>> {
2400-
match binary.operator {
2401-
BinaryOperator::Addition => {
2402-
match (&left, &right) {
2403-
(ConstEnumMemberValue::Number(l), ConstEnumMemberValue::Number(r)) => {
2404-
Some(ConstEnumMemberValue::Number(l + r))
2405-
}
2406-
_ => None,
2407-
}
2408-
}
2409-
BinaryOperator::Subtraction => {
2410-
match (&left, &right) {
2411-
(ConstEnumMemberValue::Number(l), ConstEnumMemberValue::Number(r)) => {
2412-
Some(ConstEnumMemberValue::Number(l - r))
2413-
}
2414-
_ => None,
2415-
}
2416-
}
2417-
BinaryOperator::Multiplication => {
2418-
match (&left, &right) {
2419-
(ConstEnumMemberValue::Number(l), ConstEnumMemberValue::Number(r)) => {
2420-
Some(ConstEnumMemberValue::Number(l * r))
2421-
}
2422-
_ => None,
2423-
}
2424-
}
2425-
BinaryOperator::Division => {
2426-
match (&left, &right) {
2427-
(ConstEnumMemberValue::Number(l), ConstEnumMemberValue::Number(r)) => {
2428-
if *r == 0.0 { None } else { Some(ConstEnumMemberValue::Number(l / r)) }
2429-
}
2430-
_ => None,
2431-
}
2432-
}
2433-
BinaryOperator::ShiftLeft => {
2434-
match (&left, &right) {
2435-
(ConstEnumMemberValue::Number(l), ConstEnumMemberValue::Number(r)) => {
2436-
Some(ConstEnumMemberValue::Number(((*l as i64) << (*r as i64)) as f64))
2437-
}
2438-
_ => None,
2439-
}
2440-
}
2441-
BinaryOperator::BitwiseOR => {
2442-
match (&left, &right) {
2443-
(ConstEnumMemberValue::Number(l), ConstEnumMemberValue::Number(r)) => {
2444-
Some(ConstEnumMemberValue::Number(((*l as i64) | (*r as i64)) as f64))
2445-
}
2446-
_ => None,
2447-
}
2448-
}
2449-
_ => None,
2450-
}
2451-
}
24522312
}

0 commit comments

Comments
 (0)