@@ -5,8 +5,6 @@ use std::{
55 mem,
66} ;
77
8- use num_bigint:: BigInt ;
9-
108use rustc_hash:: FxHashMap ;
119
1210use oxc_allocator:: Address ;
@@ -29,11 +27,11 @@ use oxc_syntax::{
2927#[ cfg( feature = "linter" ) ]
3028use crate :: jsdoc:: JSDocBuilder ;
3129use crate :: {
32- const_enum:: { ConstEnumTable , ConstEnumMemberValue , ConstEnumMemberInfo , ConstEnumInfo } ,
3330 Semantic ,
3431 binder:: { Binder , ModuleInstanceState } ,
3532 checker,
3633 class:: ClassTableBuilder ,
34+ const_enum:: ConstEnumTable ,
3735 diagnostics:: redeclaration,
3836 label:: UnusedLabels ,
3937 node:: AstNodes ,
@@ -112,7 +110,7 @@ pub struct SemanticBuilder<'a> {
112110 pub ( crate ) class_table_builder : ClassTableBuilder < ' a > ,
113111
114112 /// Table for storing const enum information
115- pub ( crate ) const_enum_table : ConstEnumTable < ' a > ,
113+ pub ( crate ) const_enum_table : ConstEnumTable ,
116114
117115 #[ cfg( feature = "cfg" ) ]
118116 ast_node_records : Vec < NodeId > ,
@@ -2154,11 +2152,6 @@ impl<'a> SemanticBuilder<'a> {
21542152 }
21552153 AstKind :: TSEnumDeclaration ( enum_declaration) => {
21562154 enum_declaration. bind ( self ) ;
2157-
2158- // Process const enums
2159- if enum_declaration. r#const {
2160- self . process_const_enum ( enum_declaration) ;
2161- }
21622155 }
21632156 AstKind :: TSEnumMember ( enum_member) => {
21642157 enum_member. bind ( self ) ;
@@ -2223,6 +2216,15 @@ impl<'a> SemanticBuilder<'a> {
22232216 // Clear the reference flags that may have been set when entering the node.
22242217 self . current_reference_flags = ReferenceFlags :: empty ( ) ;
22252218 }
2219+ AstKind :: TSEnumDeclaration ( enum_declaration) => {
2220+ if enum_declaration. r#const {
2221+ crate :: const_enum:: process_const_enum (
2222+ enum_declaration,
2223+ & self . scoping ,
2224+ & mut self . const_enum_table ,
2225+ ) ;
2226+ }
2227+ }
22262228 _ => { }
22272229 }
22282230 }
@@ -2244,209 +2246,4 @@ impl<'a> SemanticBuilder<'a> {
22442246 mem:: take ( & mut self . current_reference_flags )
22452247 }
22462248 }
2247-
2248- /// Process a const enum declaration and evaluate its members
2249- fn process_const_enum ( & mut self , enum_declaration : & TSEnumDeclaration < ' a > ) {
2250- // 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 ( ) ;
2254- let mut current_value: f64 = -1.0 ; // Start at -1, first auto-increment will make it 0
2255-
2256- for member in & enum_declaration. body . members {
2257- let member_name = match & member. id {
2258- TSEnumMemberName :: Identifier ( ident) => ident. name . as_str ( ) ,
2259- TSEnumMemberName :: String ( string) => string. value . as_str ( ) ,
2260- TSEnumMemberName :: ComputedString ( string) => string. value . as_str ( ) ,
2261- TSEnumMemberName :: ComputedTemplateString ( template) => {
2262- // For computed template strings, we need to evaluate them
2263- if template. expressions . is_empty ( ) {
2264- if let Some ( quasi) = template. quasis . first ( ) {
2265- quasi. value . raw . as_str ( )
2266- } else {
2267- continue ;
2268- }
2269- } else {
2270- // Skip template literals with expressions for now
2271- continue ;
2272- }
2273- }
2274- } ;
2275-
2276- 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- }
2291- } else {
2292- // Auto-increment the value
2293- current_value += 1.0 ;
2294- ConstEnumMemberValue :: Number ( current_value)
2295- } ;
2296-
2297- let member_info = ConstEnumMemberInfo {
2298- name : member_name,
2299- value,
2300- span : member. span ,
2301- has_initializer : member. initializer . is_some ( ) ,
2302- } ;
2303-
2304- members. insert ( member_name, member_info) ;
2305- }
2306-
2307- let enum_info = ConstEnumInfo {
2308- symbol_id,
2309- members,
2310- span : enum_declaration. span ,
2311- } ;
2312-
2313- self . const_enum_table . add_enum ( symbol_id, enum_info) ;
2314- }
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- }
24522249}
0 commit comments