Skip to content

Commit e845acd

Browse files
committed
optimize definition
1 parent 70e21b7 commit e845acd

File tree

2 files changed

+303
-229
lines changed

2 files changed

+303
-229
lines changed

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

Lines changed: 161 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ use itertools::Itertools;
1212
use lsp_types::{GotoDefinitionResponse, Location, Position, Range, Uri};
1313

1414
use crate::handlers::{
15-
definition::goto_function::{
16-
find_call_expr_origin_for_decl, find_call_match_function_for_member,
17-
},
15+
definition::goto_function::{find_function_call_origin, find_matching_function_definitions},
1816
hover::{find_all_same_named_members, find_member_origin_owner},
1917
};
2018

@@ -24,6 +22,7 @@ pub fn goto_def_definition(
2422
property_owner: LuaSemanticDeclId,
2523
trigger_token: &LuaSyntaxToken,
2624
) -> Option<GotoDefinitionResponse> {
25+
// 首先检查属性源位置
2726
if let Some(property) = semantic_model
2827
.get_db()
2928
.get_property_index()
@@ -35,154 +34,191 @@ pub fn goto_def_definition(
3534
}
3635
}
3736
}
37+
38+
// 根据不同的语义声明类型处理
3839
match property_owner {
39-
LuaSemanticDeclId::LuaDecl(decl_id) => {
40-
if let Some(match_semantic_decl) = find_call_expr_origin_for_decl(
40+
LuaSemanticDeclId::LuaDecl(decl_id) => handle_decl_definition(
41+
semantic_model,
42+
compilation,
43+
trigger_token,
44+
&property_owner,
45+
&decl_id,
46+
),
47+
LuaSemanticDeclId::Member(member_id) => {
48+
handle_member_definition(semantic_model, compilation, trigger_token, &member_id)
49+
}
50+
LuaSemanticDeclId::TypeDecl(type_decl_id) => {
51+
handle_type_decl_definition(semantic_model, &type_decl_id)
52+
}
53+
_ => None,
54+
}
55+
}
56+
57+
fn handle_decl_definition(
58+
semantic_model: &SemanticModel,
59+
compilation: &LuaCompilation,
60+
trigger_token: &LuaSyntaxToken,
61+
property_owner: &LuaSemanticDeclId,
62+
decl_id: &LuaDeclId,
63+
) -> Option<GotoDefinitionResponse> {
64+
// 尝试查找函数调用的原始定义
65+
if let Some(match_semantic_decl) =
66+
find_function_call_origin(semantic_model, compilation, trigger_token, property_owner)
67+
{
68+
if let LuaSemanticDeclId::LuaDecl(matched_decl_id) = match_semantic_decl {
69+
return Some(GotoDefinitionResponse::Scalar(get_decl_location(
4170
semantic_model,
42-
compilation,
43-
trigger_token,
44-
&property_owner,
45-
) {
46-
match match_semantic_decl {
47-
LuaSemanticDeclId::LuaDecl(decl_id) => {
48-
return Some(GotoDefinitionResponse::Scalar(get_decl_location(
49-
semantic_model,
50-
&decl_id,
51-
)?));
52-
}
53-
_ => {}
54-
};
55-
}
71+
&matched_decl_id,
72+
)?));
73+
}
74+
}
75+
76+
// 返回声明的位置
77+
let location = get_decl_location(semantic_model, decl_id)?;
78+
Some(GotoDefinitionResponse::Scalar(location))
79+
}
5680

57-
let location = get_decl_location(semantic_model, &decl_id)?;
58-
return Some(GotoDefinitionResponse::Scalar(location));
81+
fn handle_member_definition(
82+
semantic_model: &SemanticModel,
83+
compilation: &LuaCompilation,
84+
trigger_token: &LuaSyntaxToken,
85+
member_id: &LuaMemberId,
86+
) -> Option<GotoDefinitionResponse> {
87+
let same_named_members =
88+
find_all_same_named_members(semantic_model, &Some(LuaSemanticDeclId::Member(*member_id)))?;
89+
90+
let mut locations: Vec<Location> = Vec::new();
91+
92+
// 尝试寻找函数调用时最匹配的定义
93+
if let Some(match_members) = find_matching_function_definitions(
94+
semantic_model,
95+
compilation,
96+
trigger_token,
97+
&same_named_members,
98+
) {
99+
process_matched_members(semantic_model, compilation, &match_members, &mut locations);
100+
if !locations.is_empty() {
101+
return Some(GotoDefinitionResponse::Array(locations));
59102
}
60-
LuaSemanticDeclId::Member(member_id) => {
61-
let same_named_members = find_all_same_named_members(
62-
semantic_model,
63-
&Some(LuaSemanticDeclId::Member(member_id)),
64-
)?;
103+
}
65104

66-
let mut locations: Vec<Location> = Vec::new();
67-
// 如果是函数调用, 则尝试寻找最匹配的定义
68-
if let Some(match_members) = find_call_match_function_for_member(
69-
semantic_model,
70-
compilation,
71-
trigger_token,
72-
&same_named_members,
73-
) {
74-
for member in match_members {
75-
match member {
76-
LuaSemanticDeclId::Member(member_id) => {
77-
if should_trace_member(semantic_model, &member_id).unwrap_or(false) {
78-
// 尝试搜索这个成员最原始的定义
79-
match find_member_origin_owner(
80-
compilation,
81-
semantic_model,
82-
member_id,
83-
) {
84-
Some(LuaSemanticDeclId::Member(member_id)) => {
85-
if let Some(location) =
86-
get_member_location(semantic_model, &member_id)
87-
{
88-
locations.push(location);
89-
continue;
90-
}
91-
}
92-
Some(LuaSemanticDeclId::LuaDecl(decl_id)) => {
93-
if let Some(location) =
94-
get_decl_location(semantic_model, &decl_id)
95-
{
96-
locations.push(location);
97-
continue;
98-
}
99-
}
100-
_ => {}
101-
}
102-
}
103-
if let Some(location) = get_member_location(semantic_model, &member_id)
105+
// 添加原始成员的位置
106+
for member in same_named_members {
107+
if let LuaSemanticDeclId::Member(member_id) = member {
108+
if let Some(location) = get_member_location(semantic_model, &member_id) {
109+
locations.push(location);
110+
}
111+
}
112+
}
113+
114+
// 处理实例表成员
115+
add_instance_table_member_locations(semantic_model, trigger_token, member_id, &mut locations);
116+
117+
if !locations.is_empty() {
118+
Some(GotoDefinitionResponse::Array(
119+
locations.into_iter().unique().collect(),
120+
))
121+
} else {
122+
None
123+
}
124+
}
125+
126+
fn handle_type_decl_definition(
127+
semantic_model: &SemanticModel,
128+
type_decl_id: &LuaTypeDeclId,
129+
) -> Option<GotoDefinitionResponse> {
130+
let type_decl = semantic_model
131+
.get_db()
132+
.get_type_index()
133+
.get_type_decl(type_decl_id)?;
134+
135+
let mut locations: Vec<Location> = Vec::new();
136+
for lua_location in type_decl.get_locations() {
137+
let document = semantic_model.get_document_by_file_id(lua_location.file_id)?;
138+
let location = document.to_lsp_location(lua_location.range)?;
139+
locations.push(location);
140+
}
141+
142+
Some(GotoDefinitionResponse::Array(locations))
143+
}
144+
145+
fn process_matched_members(
146+
semantic_model: &SemanticModel,
147+
compilation: &LuaCompilation,
148+
match_members: &[LuaSemanticDeclId],
149+
locations: &mut Vec<Location>,
150+
) {
151+
for member in match_members {
152+
match member {
153+
LuaSemanticDeclId::Member(member_id) => {
154+
if should_trace_member(semantic_model, member_id).unwrap_or(false) {
155+
// 尝试搜索这个成员最原始的定义
156+
match find_member_origin_owner(compilation, semantic_model, *member_id) {
157+
Some(LuaSemanticDeclId::Member(origin_member_id)) => {
158+
if let Some(location) =
159+
get_member_location(semantic_model, &origin_member_id)
104160
{
105161
locations.push(location);
162+
continue;
106163
}
107164
}
108-
LuaSemanticDeclId::LuaDecl(decl_id) => {
109-
if let Some(location) = get_decl_location(semantic_model, &decl_id) {
165+
Some(LuaSemanticDeclId::LuaDecl(origin_decl_id)) => {
166+
if let Some(location) =
167+
get_decl_location(semantic_model, &origin_decl_id)
168+
{
110169
locations.push(location);
170+
continue;
111171
}
112172
}
113173
_ => {}
114174
}
115175
}
116-
if !locations.is_empty() {
117-
return Some(GotoDefinitionResponse::Array(locations));
176+
if let Some(location) = get_member_location(semantic_model, member_id) {
177+
locations.push(location);
118178
}
119179
}
120-
121-
// 添加原始成员的位置
122-
for member in same_named_members {
123-
match member {
124-
LuaSemanticDeclId::Member(member_id) => {
125-
if let Some(location) = get_member_location(semantic_model, &member_id) {
126-
locations.push(location);
127-
}
128-
}
129-
_ => {}
180+
LuaSemanticDeclId::LuaDecl(decl_id) => {
181+
if let Some(location) = get_decl_location(semantic_model, decl_id) {
182+
locations.push(location);
130183
}
131184
}
185+
_ => {}
186+
}
187+
}
188+
}
132189

133-
/* 对于实例的处理, 对于实例 obj
134-
```lua
135-
---@class T
136-
---@field func fun(a: int)
137-
---@field func fun(a: string)
138-
139-
---@type T
140-
local obj = {
141-
func = function() end -- 点击`func`时需要寻找`T`的定义
142-
}
143-
obj:func(1) -- 点击`func`时, 不止需要寻找`T`的定义也需要寻找`obj`实例化时赋值的`func`
144-
```
190+
fn add_instance_table_member_locations(
191+
semantic_model: &SemanticModel,
192+
trigger_token: &LuaSyntaxToken,
193+
member_id: &LuaMemberId,
194+
locations: &mut Vec<Location>,
195+
) {
196+
/* 对于实例的处理, 对于实例 obj
197+
```lua
198+
---@class T
199+
---@field func fun(a: int)
200+
---@field func fun(a: string)
145201
146-
*/
147-
if let Some(table_field_infos) =
148-
find_instance_table_member(semantic_model, trigger_token, &member_id)
202+
---@type T
203+
local obj = {
204+
func = function() end -- 点击`func`时需要寻找`T`的定义
205+
}
206+
obj:func(1) -- 点击`func`时, 不止需要寻找`T`的定义也需要寻找`obj`实例化时赋值的`func`
207+
```
208+
*/
209+
if let Some(table_field_infos) =
210+
find_instance_table_member(semantic_model, trigger_token, member_id)
211+
{
212+
for table_field_info in table_field_infos {
213+
if let Some(LuaSemanticDeclId::Member(table_member_id)) =
214+
table_field_info.property_owner_id
149215
{
150-
for table_field_info in table_field_infos {
151-
if let Some(LuaSemanticDeclId::Member(table_member_id)) =
152-
table_field_info.property_owner_id
153-
{
154-
if let Some(location) =
155-
get_member_location(semantic_model, &table_member_id)
156-
{
157-
locations.push(location);
158-
}
159-
}
216+
if let Some(location) = get_member_location(semantic_model, &table_member_id) {
217+
locations.push(location);
160218
}
161219
}
162-
163-
if !locations.is_empty() {
164-
return Some(GotoDefinitionResponse::Array(
165-
locations.into_iter().unique().collect(),
166-
));
167-
}
168-
}
169-
LuaSemanticDeclId::TypeDecl(type_decl_id) => {
170-
let type_decl = semantic_model
171-
.get_db()
172-
.get_type_index()
173-
.get_type_decl(&type_decl_id)?;
174-
let mut locations: Vec<Location> = Vec::new();
175-
for lua_location in type_decl.get_locations() {
176-
let document = semantic_model.get_document_by_file_id(lua_location.file_id)?;
177-
let location = document.to_lsp_location(lua_location.range)?;
178-
locations.push(location);
179-
}
180-
181-
return Some(GotoDefinitionResponse::Array(locations));
182220
}
183-
_ => {}
184221
}
185-
None
186222
}
187223

188224
fn goto_source_location(source: &str) -> Option<Location> {

0 commit comments

Comments
 (0)