Skip to content

Commit bc72d51

Browse files
committed
optimize definition: support generic type
1 parent e138c07 commit bc72d51

File tree

2 files changed

+80
-15
lines changed

2 files changed

+80
-15
lines changed

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

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -213,24 +213,26 @@ pub fn goto_str_tpl_ref_definition(
213213
}
214214
_ => params.get(string_token_idx),
215215
}?;
216-
if let Some(LuaType::StrTplRef(str_tpl)) = target_param.1.clone() {
217-
let prefix = str_tpl.get_prefix();
218-
let suffix = str_tpl.get_suffix();
219-
let type_decl_id = LuaTypeDeclId::new(format!("{}{}{}", prefix, name, suffix).as_str());
220-
let type_decl = semantic_model
221-
.get_db()
222-
.get_type_index()
223-
.get_type_decl(&type_decl_id)?;
224-
let mut locations = Vec::new();
225-
for lua_location in type_decl.get_locations() {
226-
let document = semantic_model.get_document_by_file_id(lua_location.file_id)?;
227-
let location = document.to_lsp_location(lua_location.range)?;
228-
locations.push(location);
229-
}
230-
216+
// 首先尝试直接匹配StrTplRef类型
217+
if let Some(locations) =
218+
try_extract_str_tpl_ref_locations(semantic_model, &target_param.1, &name)
219+
{
231220
return Some(GotoDefinitionResponse::Array(locations));
232221
}
233222

223+
// 如果参数类型是union,尝试从中提取StrTplRef类型
224+
if let Some(LuaType::Union(union_type)) = target_param.1.clone() {
225+
for union_member in union_type.get_types() {
226+
if let Some(locations) = try_extract_str_tpl_ref_locations(
227+
semantic_model,
228+
&Some(union_member.clone()),
229+
&name,
230+
) {
231+
return Some(GotoDefinitionResponse::Array(locations));
232+
}
233+
}
234+
}
235+
234236
None
235237
}
236238

@@ -336,3 +338,27 @@ fn get_decl_location(semantic_model: &SemanticModel, decl_id: &LuaDeclId) -> Opt
336338
let location = document.to_lsp_location(decl.get_range())?;
337339
Some(location)
338340
}
341+
342+
fn try_extract_str_tpl_ref_locations(
343+
semantic_model: &SemanticModel,
344+
param_type: &Option<LuaType>,
345+
name: &str,
346+
) -> Option<Vec<Location>> {
347+
if let Some(LuaType::StrTplRef(str_tpl)) = param_type {
348+
let prefix = str_tpl.get_prefix();
349+
let suffix = str_tpl.get_suffix();
350+
let type_decl_id = LuaTypeDeclId::new(format!("{}{}{}", prefix, name, suffix).as_str());
351+
let type_decl = semantic_model
352+
.get_db()
353+
.get_type_index()
354+
.get_type_decl(&type_decl_id)?;
355+
let mut locations = Vec::new();
356+
for lua_location in type_decl.get_locations() {
357+
let document = semantic_model.get_document_by_file_id(lua_location.file_id)?;
358+
let location = document.to_lsp_location(lua_location.range)?;
359+
locations.push(location);
360+
}
361+
return Some(locations);
362+
}
363+
None
364+
}

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,4 +212,43 @@ mod tests {
212212
}
213213
}
214214
}
215+
216+
#[test]
217+
fn test_goto_generic_type() {
218+
let mut ws = ProviderVirtualWorkspace::new();
219+
ws.def_file(
220+
"1.lua",
221+
r#"
222+
---@generic T
223+
---@param name `T`|T
224+
---@return T
225+
function new(name)
226+
end
227+
"#,
228+
);
229+
ws.def_file(
230+
"2.lua",
231+
r#"
232+
---@namespace AAA
233+
---@class BBB<T>
234+
"#,
235+
);
236+
let result = ws
237+
.check_definition(
238+
r#"
239+
new("AAA.BBB<??>")
240+
"#,
241+
)
242+
.unwrap();
243+
match result {
244+
GotoDefinitionResponse::Array(array) => {
245+
assert_eq!(array.len(), 1);
246+
let location = &array[0];
247+
assert_eq!(location.uri.path().as_str().ends_with("2.lua"), true);
248+
}
249+
_ => {
250+
panic!("expect array");
251+
}
252+
}
253+
}
215254
}

0 commit comments

Comments
 (0)