11use hashbrown:: HashMap ;
22
33use rowan:: { TextRange , TextSize } ;
4+ use smol_str:: SmolStr ;
5+ use std:: sync:: Arc ;
46
5- use crate :: { GenericParam , GenericTplId , LuaType } ;
7+ use crate :: { GenericParam , GenericTpl , GenericTplId , LuaType } ;
68
79pub trait GenericIndex : std:: fmt:: Debug {
810 fn add_generic_scope ( & mut self , ranges : Vec < TextRange > , is_func : bool ) -> GenericScopeId ;
@@ -15,10 +17,6 @@ pub trait GenericIndex: std::fmt::Debug {
1517 }
1618 }
1719
18- fn append_pending_type_param ( & mut self , _param : GenericParam ) { }
19-
20- fn clear_pending_type_params ( & mut self ) { }
21-
2220 fn find_generic (
2321 & self ,
2422 position : TextSize ,
@@ -29,42 +27,11 @@ pub trait GenericIndex: std::fmt::Debug {
2927#[ derive( Debug , Clone ) ]
3028pub struct FileGenericIndex {
3129 scopes : Vec < FileGenericScope > ,
32- pending_type_params : Vec < GenericParam > ,
3330}
3431
3532impl FileGenericIndex {
3633 pub fn new ( ) -> Self {
37- Self {
38- scopes : Vec :: new ( ) ,
39- pending_type_params : Vec :: new ( ) ,
40- }
41- }
42-
43- pub fn add_generic_scope ( & mut self , ranges : Vec < TextRange > , is_func : bool ) -> GenericScopeId {
44- let scope_id = GenericScopeId :: new ( self . scopes . len ( ) ) ;
45- let next_tpl_id = self . next_tpl_id ( & ranges, is_func) ;
46- self . scopes . push ( FileGenericScope :: new ( ranges, next_tpl_id) ) ;
47- scope_id
48- }
49-
50- pub fn append_generic_param ( & mut self , scope_id : GenericScopeId , param : GenericParam ) {
51- if let Some ( scope) = self . scopes . get_mut ( scope_id. id ) {
52- scope. insert_param ( param) ;
53- }
54- }
55-
56- pub fn append_generic_params ( & mut self , scope_id : GenericScopeId , params : Vec < GenericParam > ) {
57- for param in params {
58- self . append_generic_param ( scope_id, param) ;
59- }
60- }
61-
62- pub fn append_pending_type_param ( & mut self , param : GenericParam ) {
63- self . pending_type_params . push ( param) ;
64- }
65-
66- pub fn clear_pending_type_params ( & mut self ) {
67- self . pending_type_params . clear ( ) ;
34+ Self { scopes : Vec :: new ( ) }
6835 }
6936
7037 fn next_tpl_id ( & self , ranges : & [ TextRange ] , is_func : bool ) -> GenericTplId {
@@ -86,10 +53,31 @@ impl FileGenericIndex {
8653 . sum ( ) ,
8754 )
8855 }
56+ }
57+
58+ impl GenericIndex for FileGenericIndex {
59+ fn add_generic_scope ( & mut self , ranges : Vec < TextRange > , is_func : bool ) -> GenericScopeId {
60+ let scope_id = GenericScopeId :: new ( self . scopes . len ( ) ) ;
61+ let next_tpl_id = self . next_tpl_id ( & ranges, is_func) ;
62+ self . scopes . push ( FileGenericScope :: new ( ranges, next_tpl_id) ) ;
63+ scope_id
64+ }
65+
66+ fn append_generic_param ( & mut self , scope_id : GenericScopeId , param : GenericParam ) {
67+ if let Some ( scope) = self . scopes . get_mut ( scope_id. id ) {
68+ scope. insert_param ( param) ;
69+ }
70+ }
71+
72+ fn append_generic_params ( & mut self , scope_id : GenericScopeId , params : Vec < GenericParam > ) {
73+ for param in params {
74+ self . append_generic_param ( scope_id, param) ;
75+ }
76+ }
8977
9078 /// Find generic parameter by position and name.
9179 /// return (GenericTplId, constraint, default)
92- pub fn find_generic (
80+ fn find_generic (
9381 & self ,
9482 position : TextSize ,
9583 name : & str ,
@@ -108,49 +96,7 @@ impl FileGenericIndex {
10896 }
10997 }
11098
111- // 搜索前置类型参数, 例如 ---@alias Pick<T, K extends keyof T>
112- self . pending_type_params
113- . iter ( )
114- . enumerate ( )
115- . rev ( )
116- . find ( |( _, param) | param. name == name)
117- . map ( |( idx, param) | {
118- (
119- GenericTplId :: Type ( idx as u32 ) ,
120- param. type_constraint . clone ( ) ,
121- param. default_type . clone ( ) ,
122- )
123- } )
124- }
125- }
126-
127- impl GenericIndex for FileGenericIndex {
128- fn add_generic_scope ( & mut self , ranges : Vec < TextRange > , is_func : bool ) -> GenericScopeId {
129- FileGenericIndex :: add_generic_scope ( self , ranges, is_func)
130- }
131-
132- fn append_generic_param ( & mut self , scope_id : GenericScopeId , param : GenericParam ) {
133- FileGenericIndex :: append_generic_param ( self , scope_id, param) ;
134- }
135-
136- fn append_generic_params ( & mut self , scope_id : GenericScopeId , params : Vec < GenericParam > ) {
137- FileGenericIndex :: append_generic_params ( self , scope_id, params) ;
138- }
139-
140- fn append_pending_type_param ( & mut self , param : GenericParam ) {
141- FileGenericIndex :: append_pending_type_param ( self , param) ;
142- }
143-
144- fn clear_pending_type_params ( & mut self ) {
145- FileGenericIndex :: clear_pending_type_params ( self ) ;
146- }
147-
148- fn find_generic (
149- & self ,
150- position : TextSize ,
151- name : & str ,
152- ) -> Option < ( GenericTplId , Option < LuaType > , Option < LuaType > ) > {
153- FileGenericIndex :: find_generic ( self , position, name)
99+ None
154100 }
155101}
156102
@@ -195,3 +141,86 @@ impl FileGenericScope {
195141 self . ranges . iter ( ) . any ( |range| range. contains ( position) )
196142 }
197143}
144+
145+ #[ derive( Debug , Clone , Default ) ]
146+ pub struct ConditionalInferIndex {
147+ scopes : Vec < ConditionalInferScope > ,
148+ next_infer_id : u32 ,
149+ }
150+
151+ impl ConditionalInferIndex {
152+ pub fn new ( ) -> Self {
153+ Self :: default ( )
154+ }
155+
156+ pub fn enter_scope ( & mut self ) {
157+ self . scopes . push ( ConditionalInferScope :: new ( ) ) ;
158+ }
159+
160+ pub fn leave_scope ( & mut self ) -> Option < ConditionalInferScope > {
161+ self . scopes . pop ( )
162+ }
163+
164+ pub fn set_current_refs_visible ( & mut self , visible : bool ) {
165+ if let Some ( scope) = self . scopes . last_mut ( ) {
166+ scope. refs_visible = visible;
167+ }
168+ }
169+
170+ pub fn declare ( & mut self , name : & str ) -> Option < Arc < GenericTpl > > {
171+ let scope_idx = self . scopes . len ( ) . checked_sub ( 1 ) ?;
172+ if let Some ( tpl) = self . scopes [ scope_idx] . bindings . get ( name) {
173+ return Some ( tpl. clone ( ) ) ;
174+ }
175+
176+ let tpl_id = GenericTplId :: ConditionalInfer ( self . next_infer_id ) ;
177+ self . next_infer_id += 1 ;
178+ let tpl = Arc :: new ( GenericTpl :: new (
179+ tpl_id,
180+ SmolStr :: new ( name) . into ( ) ,
181+ None ,
182+ None ,
183+ ) ) ;
184+
185+ let scope = & mut self . scopes [ scope_idx] ;
186+ scope. bindings . insert ( name. to_string ( ) , tpl. clone ( ) ) ;
187+ scope
188+ . params
189+ . push ( GenericParam :: new ( SmolStr :: new ( name) , None , None , None ) ) ;
190+ Some ( tpl)
191+ }
192+
193+ pub fn find_ref ( & self , name : & str ) -> Option < Arc < GenericTpl > > {
194+ self . scopes
195+ . iter ( )
196+ . rev ( )
197+ . filter ( |scope| scope. refs_visible )
198+ . find_map ( |scope| scope. bindings . get ( name) . cloned ( ) )
199+ }
200+ }
201+
202+ #[ derive( Debug , Clone ) ]
203+ pub struct ConditionalInferScope {
204+ /// 是否允许在当前阶段把普通名字解析为 conditional infer 引用.
205+ /// condition 阶段只声明 `infer P`, true 分支阶段才允许引用 `P`.
206+ refs_visible : bool ,
207+ /// 当前 conditional 作用域内的 `infer` 名字到实际模板的绑定.
208+ /// 同名 `infer P` 会复用同一个 `GenericTplId::ConditionalInfer`.
209+ bindings : HashMap < String , Arc < GenericTpl > > ,
210+ /// 当前 conditional 声明过的 infer 参数元数据, 保留给 `LuaConditionalType`.
211+ params : Vec < GenericParam > ,
212+ }
213+
214+ impl ConditionalInferScope {
215+ fn new ( ) -> Self {
216+ Self {
217+ refs_visible : false ,
218+ bindings : HashMap :: new ( ) ,
219+ params : Vec :: new ( ) ,
220+ }
221+ }
222+
223+ pub fn into_params ( self ) -> Vec < GenericParam > {
224+ self . params
225+ }
226+ }
0 commit comments