@@ -4,8 +4,8 @@ use biome_js_semantic::{SemanticEvent, SemanticEventExtractor};
44use biome_js_syntax:: {
55 AnyJsCombinedSpecifier , AnyJsDeclaration , AnyJsExportDefaultDeclaration , AnyJsExpression ,
66 AnyJsImportClause , JsForVariableDeclaration , JsFormalParameter , JsIdentifierBinding ,
7- JsSyntaxKind , JsSyntaxNode , JsSyntaxToken , JsVariableDeclaration , TsIdentifierBinding ,
8- TsTypeParameter , TsTypeParameterName , inner_string_text,
7+ JsRestParameter , JsSyntaxKind , JsSyntaxNode , JsSyntaxToken , JsVariableDeclaration ,
8+ TsIdentifierBinding , TsTypeParameter , TsTypeParameterName , inner_string_text,
99} ;
1010use biome_js_type_info:: {
1111 BindingId , FunctionParameter , GLOBAL_RESOLVER , GLOBAL_UNKNOWN_ID , GenericTypeParameter ,
@@ -52,8 +52,8 @@ pub(super) struct JsModuleInfoCollector {
5252 /// Re-used from the semantic model in `biome_js_semantic`.
5353 extractor : SemanticEventExtractor ,
5454
55- /// Formal parameters.
56- formal_parameters : FxHashMap < JsSyntaxNode , FunctionParameter > ,
55+ /// Function parameters, both formal parameters as well as rest parameters.
56+ function_parameters : FxHashMap < JsSyntaxNode , FunctionParameter > ,
5757
5858 /// Variable declarations.
5959 variable_declarations : FxHashMap < JsSyntaxNode , Box < [ ( Text , TypeReference ) ] > > ,
@@ -174,7 +174,12 @@ impl JsModuleInfoCollector {
174174 } else if let Some ( param) = JsFormalParameter :: cast_ref ( node) {
175175 let scope_id = * self . scope_stack . last ( ) . expect ( "there must be a scope" ) ;
176176 let parsed_param = FunctionParameter :: from_js_formal_parameter ( self , scope_id, & param) ;
177- self . formal_parameters
177+ self . function_parameters
178+ . insert ( param. syntax ( ) . clone ( ) , parsed_param) ;
179+ } else if let Some ( param) = JsRestParameter :: cast_ref ( node) {
180+ let scope_id = * self . scope_stack . last ( ) . expect ( "there must be a scope" ) ;
181+ let parsed_param = FunctionParameter :: from_js_rest_parameter ( self , scope_id, & param) ;
182+ self . function_parameters
178183 . insert ( param. syntax ( ) . clone ( ) , parsed_param) ;
179184 } else if let Some ( decl) = JsVariableDeclaration :: cast_ref ( node) {
180185 let scope_id = * self . scope_stack . last ( ) . expect ( "there must be a scope" ) ;
@@ -543,6 +548,10 @@ impl JsModuleInfoCollector {
543548
544549 self . infer_all_types ( & scope_by_range) ;
545550 self . resolve_all_and_downgrade_project_references ( ) ;
551+
552+ // Purging before flattening will save us from duplicate work during
553+ // flattening. We'll purge again after for a final cleanup.
554+ self . purge_redundant_types ( ) ;
546555 self . flatten_all ( ) ;
547556 self . purge_redundant_types ( ) ;
548557
@@ -553,13 +562,12 @@ impl JsModuleInfoCollector {
553562
554563 fn infer_all_types ( & mut self , scope_by_range : & Lapper < u32 , ScopeId > ) {
555564 for index in 0 ..self . bindings . len ( ) {
556- let binding_id = BindingId :: new ( index) ;
557- let binding = & self . bindings [ binding_id. index ( ) ] ;
565+ let binding = & self . bindings [ index] ;
558566 if let Some ( node) = self . binding_node_by_start . get ( & binding. range . start ( ) ) {
559567 let name = binding. name . clone ( ) ;
560568 let scope_id = scope_id_for_range ( scope_by_range, binding. range ) ;
561569 let ty = self . infer_type ( & node. clone ( ) , & name, scope_id) ;
562- self . bindings [ binding_id . index ( ) ] . ty = ty;
570+ self . bindings [ index] . ty = ty;
563571 }
564572 }
565573 }
@@ -596,7 +604,11 @@ impl JsModuleInfoCollector {
596604 . find_map ( |( name, ty) | ( name == binding_name) . then ( || ty. clone ( ) ) )
597605 . unwrap_or_default ( ) ;
598606 } else if let Some ( param) = JsFormalParameter :: cast_ref ( & ancestor)
599- . and_then ( |param| self . formal_parameters . get ( param. syntax ( ) ) )
607+ . and_then ( |param| self . function_parameters . get ( param. syntax ( ) ) )
608+ . or_else ( || {
609+ JsRestParameter :: cast_ref ( & ancestor)
610+ . and_then ( |param| self . function_parameters . get ( param. syntax ( ) ) )
611+ } )
600612 {
601613 return match param {
602614 FunctionParameter :: Named ( named) => named. ty . clone ( ) ,
@@ -1031,10 +1043,10 @@ impl JsModuleInfo {
10311043 static_import_paths : collector. static_import_paths ,
10321044 dynamic_import_paths : collector. dynamic_import_paths ,
10331045 exports : Exports ( exports) ,
1034- blanket_reexports : collector. blanket_reexports . into ( ) ,
1035- bindings : collector. bindings . into ( ) ,
1046+ blanket_reexports : collector. blanket_reexports ,
1047+ bindings : collector. bindings ,
10361048 expressions : collector. parsed_expressions ,
1037- scopes : collector. scopes . into ( ) ,
1049+ scopes : collector. scopes ,
10381050 scope_by_range,
10391051 types : collector. types . into ( ) ,
10401052 } ) )
0 commit comments