Skip to content

Commit a455778

Browse files
committed
update references: 本地函数现在能够搜索导出的引用
1 parent 39fff0c commit a455778

7 files changed

Lines changed: 103 additions & 11 deletions

File tree

crates/emmylua_ls/src/handlers/call_hierarchy/build_call_hierarchy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub fn build_incoming_hierarchy(
100100
let mut locations = vec![];
101101
match semantic_decl {
102102
LuaSemanticDeclId::LuaDecl(decl_id) => {
103-
search_decl_references(semantic_model, decl_id, &mut locations);
103+
search_decl_references(semantic_model, compilation, decl_id, &mut locations);
104104
}
105105
LuaSemanticDeclId::Member(member_id) => {
106106
search_member_references(semantic_model, compilation, member_id, &mut locations);

crates/emmylua_ls/src/handlers/code_lens/resolve_code_lens.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub fn resolve_code_lens(
4444
let file_id = decl_id.file_id;
4545
let mut semantic_model = compilation.get_semantic_model(file_id)?;
4646
let mut results = Vec::new();
47-
search_decl_references(&mut semantic_model, decl_id, &mut results);
47+
search_decl_references(&mut semantic_model, compilation, decl_id, &mut results);
4848
let ref_count = results.len();
4949
let uri = semantic_model.get_document().get_uri();
5050
let command = make_usage_command(uri, code_lens.range, ref_count, client_id, results);

crates/emmylua_ls/src/handlers/references/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
mod reference_seacher;
22

33
use crate::context::ServerContextSnapshot;
4+
use emmylua_code_analysis::{EmmyLuaAnalysis, FileId};
45
use emmylua_parser::{LuaAstNode, LuaTokenKind};
5-
use lsp_types::{ClientCapabilities, Location, OneOf, ReferenceParams, ServerCapabilities};
6+
use lsp_types::{ClientCapabilities, Location, OneOf, Position, ReferenceParams, ServerCapabilities};
67
use reference_seacher::search_references;
78
pub use reference_seacher::{search_decl_references, search_member_references};
89
use rowan::TokenAtOffset;
@@ -19,6 +20,15 @@ pub async fn on_references_handler(
1920
let analysis = context.analysis.read().await;
2021
let file_id = analysis.get_file_id(&uri)?;
2122
let position = params.text_document_position.position;
23+
24+
references(&analysis, file_id, position)
25+
}
26+
27+
pub fn references(
28+
analysis: &EmmyLuaAnalysis,
29+
file_id: FileId,
30+
position: Position,
31+
) -> Option<Vec<Location>> {
2232
let mut semantic_model = analysis.compilation.get_semantic_model(file_id)?;
2333
if !semantic_model.get_emmyrc().references.enable {
2434
return None;

crates/emmylua_ls/src/handlers/references/reference_seacher.rs

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use std::collections::HashMap;
22

33
use 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
};
77
use emmylua_parser::{
8-
LuaAst, LuaAstNode, LuaAstToken, LuaNameToken, LuaStringToken, LuaSyntaxNode, LuaSyntaxToken,
8+
LuaAssignStat, LuaAst, LuaAstNode, LuaAstToken, LuaNameToken, LuaStringToken, LuaSyntaxNode,
9+
LuaSyntaxToken,
910
};
1011
use 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);
@@ -41,6 +42,7 @@ pub fn search_references(
4142

4243
pub fn search_decl_references(
4344
semantic_model: &SemanticModel,
45+
compilation: &LuaCompilation,
4446
decl_id: LuaDeclId,
4547
result: &mut Vec<Location>,
4648
) -> Option<()> {
@@ -58,9 +60,15 @@ pub fn search_decl_references(
5860
if let Some(location) = document.to_lsp_location(decl.get_range()) {
5961
result.push(location);
6062
}
63+
let typ = semantic_model.get_type(decl.get_id().into());
64+
let is_signature = typ.is_signature();
65+
6166
for decl_ref in decl_refs {
6267
let location = document.to_lsp_location(decl_ref.range.clone())?;
6368
result.push(location);
69+
if is_signature {
70+
get_signature_decl_member_references(semantic_model, compilation, result, decl_ref);
71+
}
6472
}
6573

6674
return Some(());
@@ -119,7 +127,7 @@ pub fn search_member_references(
119127
let range = in_filed_syntax_id.value.get_range();
120128
let location = document.to_lsp_location(range)?;
121129
result.push(location);
122-
search_member_secondary_references(semantic_model, node, result);
130+
search_member_secondary_references(semantic_model, compilation, node, result);
123131
}
124132
}
125133

@@ -128,6 +136,7 @@ pub fn search_member_references(
128136

129137
fn search_member_secondary_references(
130138
semantic_model: &SemanticModel,
139+
compilation: &LuaCompilation,
131140
node: LuaSyntaxNode,
132141
result: &mut Vec<Location>,
133142
) -> Option<()> {
@@ -141,7 +150,7 @@ fn search_member_secondary_references(
141150
.position(|value| value.get_position() == position)?;
142151
let var = vars.get(idx)?;
143152
let decl_id = LuaDeclId::new(semantic_model.get_file_id(), var.get_position());
144-
search_decl_references(semantic_model, decl_id, result);
153+
search_decl_references(semantic_model, compilation, decl_id, result);
145154
let document = semantic_model.get_document();
146155
let range = document.to_lsp_location(var.get_range())?;
147156
result.push(range);
@@ -152,7 +161,7 @@ fn search_member_secondary_references(
152161
let idx = values.position(|value| value.get_position() == position)?;
153162
let name = local_names.get(idx)?;
154163
let decl_id = LuaDeclId::new(semantic_model.get_file_id(), name.get_position());
155-
search_decl_references(semantic_model, decl_id, result);
164+
search_decl_references(semantic_model, compilation, decl_id, result);
156165
let document = semantic_model.get_document();
157166
let range = document.to_lsp_location(name.get_range())?;
158167
result.push(range);
@@ -241,3 +250,34 @@ fn search_type_decl_references(
241250

242251
Some(())
243252
}
253+
254+
fn get_signature_decl_member_references(
255+
semantic_model: &SemanticModel,
256+
compilation: &LuaCompilation,
257+
result: &mut Vec<Location>,
258+
decl_ref: &DeclReference,
259+
) -> Option<Vec<Location>> {
260+
let root = semantic_model.get_root();
261+
let position = decl_ref.range.start();
262+
let token = root.syntax().token_at_offset(position).right_biased()?;
263+
let parent = token.parent()?;
264+
265+
match parent.parent()? {
266+
assign_stat_node if LuaAssignStat::can_cast(assign_stat_node.kind().into()) => {
267+
let assign_stat = LuaAssignStat::cast(assign_stat_node)?;
268+
let (vars, values) = assign_stat.get_var_and_expr_list();
269+
let idx = values
270+
.iter()
271+
.position(|value| value.get_position() == position)?;
272+
let var = vars.get(idx)?;
273+
let decl_id = semantic_model
274+
.find_decl(var.syntax().clone().into(), SemanticDeclLevel::default())?;
275+
if let LuaSemanticDeclId::Member(member_id) = decl_id {
276+
search_member_references(semantic_model, compilation, member_id, result);
277+
}
278+
}
279+
280+
_ => {}
281+
}
282+
None
283+
}

crates/emmylua_ls/src/handlers/test/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod hover_function_test;
66
mod hover_test;
77
mod implementation_test;
88
mod inlay_hint_test;
9+
mod references_test;
910
mod rename_test;
1011
mod semantic_token_test;
1112
mod signature_helper_test;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#[cfg(test)]
2+
mod tests {
3+
4+
use crate::handlers::test_lib::ProviderVirtualWorkspace;
5+
6+
#[test]
7+
fn test_function_references() {
8+
let mut ws = ProviderVirtualWorkspace::new();
9+
ws.def_file(
10+
"1.lua",
11+
r#"
12+
local flush = require("virtual_0").flush
13+
flush()
14+
"#,
15+
);
16+
let result = ws.check_references(
17+
r#"
18+
local export = {}
19+
local function fl<??>ush()
20+
end
21+
export.flush = flush
22+
return export
23+
"#,
24+
);
25+
assert!(result.is_some());
26+
let locations = result.unwrap();
27+
assert!(locations.len() >= 4);
28+
}
29+
}

crates/emmylua_ls/src/handlers/test_lib/mod.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::{
2020
},
2121
};
2222

23-
use super::{hover::hover, implementation::implementation};
23+
use super::{hover::hover, implementation::implementation, references::references};
2424

2525
/// A virtual workspace for testing.
2626
#[allow(unused)]
@@ -375,4 +375,16 @@ impl ProviderVirtualWorkspace {
375375

376376
true
377377
}
378+
379+
pub fn check_references(&mut self, block_str: &str) -> Option<Vec<lsp_types::Location>> {
380+
let content = Self::handle_file_content(block_str);
381+
let Some((content, position)) = content else {
382+
return None;
383+
};
384+
let file_id = self.def(&content);
385+
let result = references(&self.analysis, file_id, position);
386+
// dbg!(&result);
387+
dbg!(&result.as_ref().unwrap().len());
388+
result
389+
}
378390
}

0 commit comments

Comments
 (0)