1- use std:: collections:: HashMap ;
1+ use std:: collections:: { HashMap , HashSet } ;
22
33use emmylua_code_analysis:: {
4- LuaCompilation , LuaDeclId , LuaMemberId , LuaMemberKey , LuaSemanticDeclId , LuaTypeDeclId ,
5- SemanticDeclLevel , SemanticModel ,
4+ DeclReference , LuaCompilation , LuaDeclId , LuaMemberId , LuaMemberKey , LuaSemanticDeclId ,
5+ LuaTypeDeclId , SemanticDeclLevel , SemanticModel ,
66} ;
77use emmylua_parser:: {
8- LuaAst , LuaAstNode , LuaAstToken , LuaNameToken , LuaStringToken , LuaSyntaxNode , LuaSyntaxToken ,
8+ LuaAssignStat , LuaAst , LuaAstNode , LuaAstToken , LuaNameToken , LuaStringToken , LuaSyntaxNode ,
9+ LuaSyntaxToken ,
910} ;
1011use lsp_types:: Location ;
1112
@@ -20,7 +21,7 @@ pub fn search_references(
2021 {
2122 match semantic_decl {
2223 LuaSemanticDeclId :: LuaDecl ( decl_id) => {
23- search_decl_references ( semantic_model, decl_id, & mut result) ;
24+ search_decl_references ( semantic_model, compilation , decl_id, & mut result) ;
2425 }
2526 LuaSemanticDeclId :: Member ( member_id) => {
2627 search_member_references ( semantic_model, compilation, member_id, & mut result) ;
@@ -36,11 +37,16 @@ pub fn search_references(
3637 fuzzy_search_references ( compilation, token, & mut result) ;
3738 }
3839
40+ // 简单过滤, 同行的多个引用只保留一个
41+ // let filtered_result = filter_duplicate_and_covered_locations(result);
42+ // Some(filtered_result)
43+
3944 Some ( result)
4045}
4146
4247pub fn search_decl_references (
4348 semantic_model : & SemanticModel ,
49+ compilation : & LuaCompilation ,
4450 decl_id : LuaDeclId ,
4551 result : & mut Vec < Location > ,
4652) -> Option < ( ) > {
@@ -58,9 +64,15 @@ pub fn search_decl_references(
5864 if let Some ( location) = document. to_lsp_location ( decl. get_range ( ) ) {
5965 result. push ( location) ;
6066 }
67+ let typ = semantic_model. get_type ( decl. get_id ( ) . into ( ) ) ;
68+ let is_signature = typ. is_signature ( ) ;
69+
6170 for decl_ref in decl_refs {
6271 let location = document. to_lsp_location ( decl_ref. range . clone ( ) ) ?;
6372 result. push ( location) ;
73+ if is_signature {
74+ get_signature_decl_member_references ( semantic_model, compilation, result, decl_ref) ;
75+ }
6476 }
6577
6678 return Some ( ( ) ) ;
@@ -119,7 +131,7 @@ pub fn search_member_references(
119131 let range = in_filed_syntax_id. value . get_range ( ) ;
120132 let location = document. to_lsp_location ( range) ?;
121133 result. push ( location) ;
122- search_member_secondary_references ( semantic_model, node, result) ;
134+ search_member_secondary_references ( semantic_model, compilation , node, result) ;
123135 }
124136 }
125137
@@ -128,6 +140,7 @@ pub fn search_member_references(
128140
129141fn search_member_secondary_references (
130142 semantic_model : & SemanticModel ,
143+ compilation : & LuaCompilation ,
131144 node : LuaSyntaxNode ,
132145 result : & mut Vec < Location > ,
133146) -> Option < ( ) > {
@@ -141,7 +154,7 @@ fn search_member_secondary_references(
141154 . position ( |value| value. get_position ( ) == position) ?;
142155 let var = vars. get ( idx) ?;
143156 let decl_id = LuaDeclId :: new ( semantic_model. get_file_id ( ) , var. get_position ( ) ) ;
144- search_decl_references ( semantic_model, decl_id, result) ;
157+ search_decl_references ( semantic_model, compilation , decl_id, result) ;
145158 let document = semantic_model. get_document ( ) ;
146159 let range = document. to_lsp_location ( var. get_range ( ) ) ?;
147160 result. push ( range) ;
@@ -152,7 +165,7 @@ fn search_member_secondary_references(
152165 let idx = values. position ( |value| value. get_position ( ) == position) ?;
153166 let name = local_names. get ( idx) ?;
154167 let decl_id = LuaDeclId :: new ( semantic_model. get_file_id ( ) , name. get_position ( ) ) ;
155- search_decl_references ( semantic_model, decl_id, result) ;
168+ search_decl_references ( semantic_model, compilation , decl_id, result) ;
156169 let document = semantic_model. get_document ( ) ;
157170 let range = document. to_lsp_location ( name. get_range ( ) ) ?;
158171 result. push ( range) ;
@@ -241,3 +254,80 @@ fn search_type_decl_references(
241254
242255 Some ( ( ) )
243256}
257+
258+ fn get_signature_decl_member_references (
259+ semantic_model : & SemanticModel ,
260+ compilation : & LuaCompilation ,
261+ result : & mut Vec < Location > ,
262+ decl_ref : & DeclReference ,
263+ ) -> Option < Vec < Location > > {
264+ let root = semantic_model. get_root ( ) ;
265+ let position = decl_ref. range . start ( ) ;
266+ let token = root. syntax ( ) . token_at_offset ( position) . right_biased ( ) ?;
267+ let parent = token. parent ( ) ?;
268+
269+ match parent. parent ( ) ? {
270+ assign_stat_node if LuaAssignStat :: can_cast ( assign_stat_node. kind ( ) . into ( ) ) => {
271+ let assign_stat = LuaAssignStat :: cast ( assign_stat_node) ?;
272+ let ( vars, values) = assign_stat. get_var_and_expr_list ( ) ;
273+ let idx = values
274+ . iter ( )
275+ . position ( |value| value. get_position ( ) == position) ?;
276+ let var = vars. get ( idx) ?;
277+ let decl_id = semantic_model
278+ . find_decl ( var. syntax ( ) . clone ( ) . into ( ) , SemanticDeclLevel :: default ( ) ) ?;
279+ if let LuaSemanticDeclId :: Member ( member_id) = decl_id {
280+ search_member_references ( semantic_model, compilation, member_id, result) ;
281+ }
282+ }
283+
284+ _ => { }
285+ }
286+ None
287+ }
288+
289+ #[ allow( unused) ]
290+ fn filter_duplicate_and_covered_locations ( locations : Vec < Location > ) -> Vec < Location > {
291+ if locations. is_empty ( ) {
292+ return locations;
293+ }
294+ let mut sorted_locations = locations;
295+ sorted_locations. sort_by ( |a, b| {
296+ a. uri
297+ . to_string ( )
298+ . cmp ( & b. uri . to_string ( ) )
299+ . then_with ( || a. range . start . line . cmp ( & b. range . start . line ) )
300+ . then_with ( || b. range . end . line . cmp ( & a. range . end . line ) )
301+ } ) ;
302+
303+ let mut result = Vec :: new ( ) ;
304+ let mut seen_lines_by_uri: HashMap < String , HashSet < u32 > > = HashMap :: new ( ) ;
305+
306+ for location in sorted_locations {
307+ let uri_str = location. uri . to_string ( ) ;
308+ let seen_lines = seen_lines_by_uri. entry ( uri_str) . or_default ( ) ;
309+
310+ let start_line = location. range . start . line ;
311+ let end_line = location. range . end . line ;
312+
313+ let is_covered = ( start_line..=end_line) . any ( |line| seen_lines. contains ( & line) ) ;
314+
315+ if !is_covered {
316+ for line in start_line..=end_line {
317+ seen_lines. insert ( line) ;
318+ }
319+ result. push ( location) ;
320+ }
321+ }
322+
323+ // 最终按位置排序
324+ result. sort_by ( |a, b| {
325+ a. uri
326+ . to_string ( )
327+ . cmp ( & b. uri . to_string ( ) )
328+ . then_with ( || a. range . start . line . cmp ( & b. range . start . line ) )
329+ . then_with ( || a. range . start . character . cmp ( & b. range . start . character ) )
330+ } ) ;
331+
332+ result
333+ }
0 commit comments