1- use std:: { collections:: HashSet , fmt:: Write } ;
1+ use std:: { collections:: HashSet , fmt:: Write , sync :: Arc } ;
22
33use emmylua_code_analysis:: {
44 AsyncState , DbIndex , LuaDocReturnInfo , LuaDocReturnOverloadInfo , LuaFunctionType , LuaMember ,
5- LuaMemberOwner , LuaSemanticDeclId , LuaType , RenderLevel , VariadicType , humanize_type,
5+ LuaMemberOwner , LuaSemanticDeclId , LuaSignature , LuaType , RenderLevel , VariadicType ,
6+ humanize_type, infer_call_generic,
67} ;
8+ use emmylua_parser:: LuaCallExpr ;
79
810use crate :: handlers:: hover:: {
911 HoverBuilder ,
@@ -29,14 +31,16 @@ pub(super) fn process_function_type(
2931 typ : & LuaType ,
3032 semantic_decl : & LuaSemanticDeclId ,
3133 function_member : Option < & LuaMember > ,
34+ call_expr : Option < & LuaCallExpr > ,
3235) -> Option < Vec < String > > {
3336 match typ {
3437 LuaType :: DocFunction ( lua_func) => {
38+ let lua_func = instantiate_function_for_call ( builder, db, lua_func, call_expr) ;
3539 let ctx = FunctionRenderContext {
36- func : lua_func,
40+ func : lua_func. as_ref ( ) ,
3741 semantic_decl,
3842 owner_member : function_member,
39- return_docs : convert_function_return_to_docs ( lua_func) ,
43+ return_docs : convert_function_return_to_docs ( lua_func. as_ref ( ) ) ,
4044 ret_detail : None ,
4145 } ;
4246 let content = render_function ( builder, db, ctx) ?;
@@ -46,31 +50,24 @@ pub(super) fn process_function_type(
4650 let signature = db. get_signature_index ( ) . get ( & signature_id) ?;
4751 let fake_doc_function = signature. to_doc_func_type ( ) ;
4852 let mut contents = Vec :: with_capacity ( signature. overloads . len ( ) + 1 ) ;
49- for ( i, overload) in std:: iter:: once ( fake_doc_function. as_ref ( ) )
50- . chain ( signature. overloads . iter ( ) . map ( |overload| overload . as_ref ( ) ) )
53+ for ( i, overload) in std:: iter:: once ( & fake_doc_function)
54+ . chain ( signature. overloads . iter ( ) )
5155 . enumerate ( )
5256 {
57+ let overload = instantiate_function_for_call ( builder, db, overload, call_expr) ;
5358 // 提前计算 return_docs 和 ret_detail 的差异, 免重复的 hover_doc_function_type 调用
5459 let ( return_docs, ret_detail) = if i == 0 && !signature. return_overloads . is_empty ( )
5560 {
5661 let detail =
57- build_function_return_overload_rows ( builder, & signature. return_overloads ) ;
62+ build_signature_return_overload_rows ( builder, db , signature, call_expr ) ;
5863 ( Vec :: new ( ) , Some ( detail) )
5964 } else {
60- let docs = if i == 0 {
61- if signature. return_docs . is_empty ( ) {
62- convert_function_return_to_docs ( overload)
63- } else {
64- signature. return_docs . clone ( )
65- }
66- } else {
67- convert_function_return_to_docs ( overload)
68- } ;
65+ let docs = signature_return_docs ( signature, i, overload. as_ref ( ) , call_expr) ;
6966 ( docs, None )
7067 } ;
7168
7269 let ctx = FunctionRenderContext {
73- func : overload,
70+ func : overload. as_ref ( ) ,
7471 semantic_decl,
7572 owner_member : function_member,
7673 return_docs,
@@ -83,9 +80,14 @@ pub(super) fn process_function_type(
8380 LuaType :: Union ( union) => {
8481 let mut contents = Vec :: new ( ) ;
8582 for typ in union. into_vec ( ) {
86- if let Some ( content) =
87- process_function_type ( builder, db, & typ, semantic_decl, function_member)
88- {
83+ if let Some ( content) = process_function_type (
84+ builder,
85+ db,
86+ & typ,
87+ semantic_decl,
88+ function_member,
89+ call_expr,
90+ ) {
8991 contents. extend ( content) ;
9092 }
9193 }
@@ -95,6 +97,111 @@ pub(super) fn process_function_type(
9597 }
9698}
9799
100+ fn instantiate_function_for_call (
101+ builder : & HoverBuilder ,
102+ db : & DbIndex ,
103+ func : & Arc < LuaFunctionType > ,
104+ call_expr : Option < & LuaCallExpr > ,
105+ ) -> Arc < LuaFunctionType > {
106+ let Some ( call_expr) = call_expr else {
107+ return func. clone ( ) ;
108+ } ;
109+ if !func. contain_tpl ( ) {
110+ return func. clone ( ) ;
111+ }
112+
113+ infer_call_generic (
114+ db,
115+ & mut builder. semantic_model . get_cache ( ) . borrow_mut ( ) ,
116+ func. as_ref ( ) ,
117+ call_expr. clone ( ) ,
118+ )
119+ . map ( Arc :: new)
120+ . unwrap_or_else ( |_| func. clone ( ) )
121+ }
122+
123+ fn build_signature_return_overload_rows (
124+ builder : & mut HoverBuilder ,
125+ db : & DbIndex ,
126+ signature : & LuaSignature ,
127+ call_expr : Option < & LuaCallExpr > ,
128+ ) -> String {
129+ if let Some ( call_expr) = call_expr {
130+ let return_overloads = instantiate_call_return_overloads ( builder, db, call_expr, signature) ;
131+ build_function_return_overload_rows ( builder, & return_overloads)
132+ } else {
133+ build_function_return_overload_rows ( builder, & signature. return_overloads )
134+ }
135+ }
136+
137+ fn signature_return_docs (
138+ signature : & LuaSignature ,
139+ index : usize ,
140+ func : & LuaFunctionType ,
141+ call_expr : Option < & LuaCallExpr > ,
142+ ) -> Vec < LuaDocReturnInfo > {
143+ if index == 0 && !signature. return_docs . is_empty ( ) {
144+ if call_expr. is_none ( ) {
145+ return signature. return_docs . clone ( ) ;
146+ }
147+
148+ let mut return_docs = signature. return_docs . clone ( ) ;
149+ for ( return_doc, inferred_doc) in return_docs
150+ . iter_mut ( )
151+ . zip ( convert_function_return_to_docs ( func) )
152+ {
153+ return_doc. type_ref = inferred_doc. type_ref ;
154+ }
155+ return return_docs;
156+ }
157+
158+ convert_function_return_to_docs ( func)
159+ }
160+
161+ pub ( super ) fn instantiate_call_return_overloads (
162+ builder : & HoverBuilder ,
163+ db : & DbIndex ,
164+ call_expr : & LuaCallExpr ,
165+ signature : & LuaSignature ,
166+ ) -> Vec < LuaDocReturnOverloadInfo > {
167+ let mut cache = builder. semantic_model . get_cache ( ) . borrow_mut ( ) ;
168+
169+ signature
170+ . return_overloads
171+ . iter ( )
172+ . map ( |row| {
173+ let row_return_type = match row. type_refs . len ( ) {
174+ 0 => LuaType :: Nil ,
175+ 1 => row. type_refs [ 0 ] . clone ( ) ,
176+ _ => LuaType :: Variadic ( VariadicType :: Multi ( row. type_refs . clone ( ) ) . into ( ) ) ,
177+ } ;
178+ let row_function = LuaFunctionType :: new (
179+ signature. async_state ,
180+ signature. is_colon_define ,
181+ signature. is_vararg ,
182+ signature. get_type_params ( ) ,
183+ row_return_type,
184+ Some ( signature. get_function_generic_params ( ) ) ,
185+ ) ;
186+ let type_refs = infer_call_generic ( db, & mut cache, & row_function, call_expr. clone ( ) )
187+ . ok ( )
188+ . map ( |func| match func. get_ret ( ) {
189+ LuaType :: Variadic ( variadic) => match variadic. as_ref ( ) {
190+ VariadicType :: Multi ( types) => types. clone ( ) ,
191+ VariadicType :: Base ( _) => vec ! [ LuaType :: Variadic ( variadic. clone( ) ) ] ,
192+ } ,
193+ typ => vec ! [ typ. clone( ) ] ,
194+ } )
195+ . unwrap_or_else ( || row. type_refs . clone ( ) ) ;
196+
197+ LuaDocReturnOverloadInfo {
198+ type_refs,
199+ description : row. description . clone ( ) ,
200+ }
201+ } )
202+ . collect ( )
203+ }
204+
98205/// 渲染单个函数签名的完整 hover 文本
99206pub ( super ) fn render_function (
100207 builder : & mut HoverBuilder ,
0 commit comments