Skip to content

Commit dd5e631

Browse files
committed
update goto_def_definition
不再追溯到最初的定义
1 parent 1efb2e2 commit dd5e631

File tree

5 files changed

+108
-75
lines changed

5 files changed

+108
-75
lines changed

crates/emmylua_ls/src/handlers/definition/goto_def_definition.rs

Lines changed: 87 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
use std::{collections::HashSet, str::FromStr};
1+
use std::str::FromStr;
22

33
use emmylua_code_analysis::{
44
LuaDeclId, LuaMemberId, LuaMemberInfo, LuaMemberKey, LuaSemanticDeclId, LuaType, LuaTypeDeclId,
55
SemanticDeclLevel, SemanticModel,
66
};
77
use emmylua_parser::{
88
LuaAstNode, LuaAstToken, LuaCallExpr, LuaExpr, LuaIndexExpr, LuaStringToken, LuaSyntaxToken,
9-
LuaTableExpr,
9+
LuaTableExpr, LuaTableField,
1010
};
11+
use itertools::Itertools;
1112
use lsp_types::{GotoDefinitionResponse, Location, Position, Range, Uri};
1213

13-
use crate::handlers::hover::find_member_origin_owner;
14+
use crate::handlers::hover::find_all_same_named_members;
1415

1516
pub fn goto_def_definition(
1617
semantic_model: &SemanticModel,
1718
property_owner: LuaSemanticDeclId,
1819
trigger_token: &LuaSyntaxToken,
19-
guard: &mut GotoDefGuard,
2020
) -> Option<GotoDefinitionResponse> {
2121
if let Some(property) = semantic_model
2222
.get_db()
@@ -41,48 +41,59 @@ pub fn goto_def_definition(
4141
return Some(GotoDefinitionResponse::Scalar(location));
4242
}
4343
LuaSemanticDeclId::Member(member_id) => {
44-
if let Some(origin_property_owner) = find_member_origin_owner(semantic_model, member_id)
45-
{
46-
if guard.check(&origin_property_owner) {
47-
return goto_def_definition(
48-
semantic_model,
49-
origin_property_owner,
50-
trigger_token,
51-
guard,
52-
);
53-
}
54-
}
55-
56-
let member_key = semantic_model
57-
.get_db()
58-
.get_member_index()
59-
.get_member(&member_id)?
60-
.get_key();
44+
let same_named_members = find_all_same_named_members(
45+
semantic_model,
46+
&Some(LuaSemanticDeclId::Member(member_id)),
47+
)?;
6148

6249
let mut locations: Vec<Location> = Vec::new();
6350

6451
// 添加原始成员的位置
65-
if let Some(location) = get_member_location(semantic_model, &member_id) {
66-
locations.push(location);
52+
for member in same_named_members {
53+
match member {
54+
LuaSemanticDeclId::Member(member_id) => {
55+
if let Some(location) = get_member_location(semantic_model, &member_id) {
56+
locations.push(location);
57+
}
58+
}
59+
_ => {}
60+
}
6761
}
6862

69-
// 查找实体的定义, 例如在 ---@field 时声明, obj = {} 时实际定义
70-
if let Some(table_field_info) =
71-
find_table_member_definition(semantic_model, trigger_token, member_key)
63+
/* 对于实例的处理, 对于实例 obj
64+
```lua
65+
---@class T
66+
---@field func fun(a: int)
67+
---@field func fun(a: string)
68+
69+
---@type T
70+
local obj = {
71+
func = function() end -- 点击`func`时需要寻找`T`的定义
72+
}
73+
obj:func(1) -- 点击`func`时, 不止需要寻找`T`的定义也需要寻找`obj`实例化时赋值的`func`
74+
```
75+
76+
*/
77+
if let Some(table_field_infos) =
78+
find_table_member_definition(semantic_model, trigger_token, &member_id)
7279
{
73-
if let Some(LuaSemanticDeclId::Member(table_member_id)) =
74-
table_field_info.property_owner_id
75-
{
76-
if let Some(location) = get_member_location(semantic_model, &table_member_id) {
77-
if !locations.contains(&location) {
80+
for table_field_info in table_field_infos {
81+
if let Some(LuaSemanticDeclId::Member(table_member_id)) =
82+
table_field_info.property_owner_id
83+
{
84+
if let Some(location) =
85+
get_member_location(semantic_model, &table_member_id)
86+
{
7887
locations.push(location);
7988
}
8089
}
8190
}
8291
}
8392

8493
if !locations.is_empty() {
85-
return Some(GotoDefinitionResponse::Array(locations));
94+
return Some(GotoDefinitionResponse::Array(
95+
locations.into_iter().unique().collect(),
96+
));
8697
}
8798
}
8899
LuaSemanticDeclId::TypeDecl(type_decl_id) => {
@@ -191,28 +202,53 @@ pub fn goto_str_tpl_ref_definition(
191202
pub fn find_table_member_definition(
192203
semantic_model: &SemanticModel,
193204
trigger_token: &LuaSyntaxToken,
194-
member_key: &LuaMemberKey,
195-
) -> Option<LuaMemberInfo> {
196-
let index_expr = trigger_token.parent().and_then(LuaIndexExpr::cast)?;
197-
let prefix_expr = index_expr.get_prefix_expr()?;
205+
member_id: &LuaMemberId,
206+
) -> Option<Vec<LuaMemberInfo>> {
207+
let member_key = semantic_model
208+
.get_db()
209+
.get_member_index()
210+
.get_member(&member_id)?
211+
.get_key();
212+
let parent = trigger_token.parent()?;
213+
214+
match parent {
215+
expr_node if LuaIndexExpr::can_cast(expr_node.kind().into()) => {
216+
let index_expr = LuaIndexExpr::cast(expr_node)?;
217+
let prefix_expr = index_expr.get_prefix_expr()?;
198218

199-
let decl = semantic_model.find_decl(
200-
prefix_expr.syntax().clone().into(),
201-
SemanticDeclLevel::default(),
202-
);
219+
let decl = semantic_model.find_decl(
220+
prefix_expr.syntax().clone().into(),
221+
SemanticDeclLevel::default(),
222+
);
203223

204-
if let Some(LuaSemanticDeclId::LuaDecl(decl_id)) = decl {
205-
return find_member_in_table_decl(semantic_model, &decl_id, member_key);
224+
if let Some(LuaSemanticDeclId::LuaDecl(decl_id)) = decl {
225+
return find_member_in_table_const(semantic_model, &decl_id, member_key);
226+
}
227+
}
228+
table_field_node if LuaTableField::can_cast(table_field_node.kind().into()) => {
229+
let table_field = LuaTableField::cast(table_field_node)?;
230+
let table_expr = table_field.get_parent::<LuaTableExpr>()?;
231+
let typ = semantic_model.infer_table_should_be(table_expr)?;
232+
let member_infos = semantic_model.get_member_infos(&typ)?;
233+
return Some(
234+
member_infos
235+
.iter()
236+
.filter(|m| m.key == *member_key)
237+
.cloned()
238+
.collect(),
239+
);
240+
}
241+
_ => {}
206242
}
207243

208244
None
209245
}
210246

211-
fn find_member_in_table_decl(
247+
fn find_member_in_table_const(
212248
semantic_model: &SemanticModel,
213249
decl_id: &LuaDeclId,
214250
member_key: &LuaMemberKey,
215-
) -> Option<LuaMemberInfo> {
251+
) -> Option<Vec<LuaMemberInfo>> {
216252
let root = semantic_model
217253
.get_db()
218254
.get_vfs()
@@ -232,7 +268,13 @@ fn find_member_in_table_decl(
232268
.ok()?;
233269

234270
let member_infos = semantic_model.get_member_infos(&typ)?;
235-
member_infos.iter().find(|m| m.key == *member_key).cloned()
271+
Some(
272+
member_infos
273+
.iter()
274+
.filter(|m| m.key == *member_key)
275+
.cloned()
276+
.collect(),
277+
)
236278
}
237279

238280
fn get_member_location(
@@ -242,24 +284,3 @@ fn get_member_location(
242284
let document = semantic_model.get_document_by_file_id(member_id.file_id)?;
243285
document.to_lsp_location(member_id.get_syntax_id().get_range())
244286
}
245-
246-
#[derive(Debug, Clone)]
247-
pub struct GotoDefGuard {
248-
ids: HashSet<LuaSemanticDeclId>,
249-
}
250-
251-
impl GotoDefGuard {
252-
pub fn new(first: LuaSemanticDeclId) -> Self {
253-
Self {
254-
ids: HashSet::from([first]),
255-
}
256-
}
257-
258-
pub fn check(&mut self, id: &LuaSemanticDeclId) -> bool {
259-
if self.ids.contains(id) {
260-
return false;
261-
}
262-
self.ids.insert(id.clone());
263-
true
264-
}
265-
}

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ use lsp_types::{
1717
use rowan::TokenAtOffset;
1818
use tokio_util::sync::CancellationToken;
1919

20-
use crate::{
21-
context::ServerContextSnapshot, handlers::definition::goto_def_definition::GotoDefGuard,
22-
};
20+
use crate::context::ServerContextSnapshot;
2321

2422
use super::RegisterCapabilities;
2523

@@ -69,8 +67,7 @@ pub fn definition(
6967
if let Some(semantic_decl) =
7068
semantic_model.find_decl(token.clone().into(), SemanticDeclLevel::default())
7169
{
72-
let mut guard = GotoDefGuard::new(semantic_decl.clone());
73-
return goto_def_definition(&semantic_model, semantic_decl, &token, &mut guard);
70+
return goto_def_definition(&semantic_model, semantic_decl, &token);
7471
} else if let Some(string_token) = LuaStringToken::cast(token.clone()) {
7572
if let Some(module_response) = goto_module_file(&semantic_model, string_token.clone()) {
7673
return Some(module_response);

crates/emmylua_ls/src/handlers/hover/find_origin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ pub fn find_member_origin_owner(
124124
find_member_origin_owners(semantic_model, member_id).get_first()
125125
}
126126

127-
fn find_all_same_named_members(
127+
pub fn find_all_same_named_members(
128128
semantic_model: &SemanticModel,
129129
final_owner: &Option<LuaSemanticDeclId>,
130130
) -> Option<Vec<LuaSemanticDeclId>> {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub use build_hover::build_hover_content_for_completion;
1010
use build_hover::build_semantic_info_hover;
1111
use emmylua_code_analysis::{EmmyLuaAnalysis, FileId};
1212
use emmylua_parser::LuaAstNode;
13-
pub use find_origin::find_member_origin_owner;
13+
pub use find_origin::{find_member_origin_owner, find_all_same_named_members};
1414
pub use hover_builder::HoverBuilder;
1515
pub use hover_humanize::infer_prefix_global_name;
1616
use keyword_hover::{hover_keyword, is_keyword};

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod tests {
77
let mut ws = ProviderVirtualWorkspace::new();
88
ws.check_definition(
99
r#"
10-
---@generic T: string
10+
---@generic T
1111
---@param name `T`
1212
---@return T
1313
local function new(name)
@@ -27,7 +27,7 @@ mod tests {
2727
ws.check_definition(
2828
r#"
2929
---@class T
30-
---@field func fun(self:string) 注释注释
30+
---@field func fun(self:string)
3131
3232
---@type T
3333
local t = {
@@ -57,4 +57,19 @@ mod tests {
5757
"#,
5858
);
5959
}
60+
61+
#[test]
62+
fn test_goto_field() {
63+
let mut ws = ProviderVirtualWorkspace::new();
64+
ws.check_definition(
65+
r#"
66+
local t = {}
67+
function t:test(a)
68+
self.abc = a
69+
end
70+
71+
print(t.abc<??>)
72+
"#,
73+
);
74+
}
6075
}

0 commit comments

Comments
 (0)