Skip to content

Commit 4f1edab

Browse files
committed
organize hover
1 parent 1f341dd commit 4f1edab

File tree

2 files changed

+114
-112
lines changed

2 files changed

+114
-112
lines changed

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

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -59,51 +59,38 @@ pub fn build_hover_content<'a>(
5959
db: &DbIndex,
6060
typ: Option<LuaType>,
6161
property_id: LuaPropertyOwnerId,
62-
is_completion: bool, // 是否补全
62+
is_completion: bool,
6363
token: Option<LuaSyntaxToken>,
6464
) -> Option<HoverBuilder<'a>> {
65+
let semantic_model = semantic_model?;
66+
let mut builder = HoverBuilder::new(semantic_model, token, is_completion);
6567
match property_id {
6668
LuaPropertyOwnerId::LuaDecl(decl_id) => {
67-
if let Some(semantic_model) = semantic_model {
68-
let mut builder = HoverBuilder::new(semantic_model, token, is_completion);
69-
if let Some(typ) = typ {
70-
build_decl_hover(&mut builder, db, typ, decl_id);
71-
} else {
69+
let effective_typ = match typ {
70+
Some(t) => t,
71+
None => {
7272
let decl = db.get_decl_index().get_decl(&decl_id)?;
73-
let typ = decl.get_type()?;
74-
build_decl_hover(&mut builder, db, typ.clone(), decl_id);
73+
decl.get_type()?.clone()
7574
}
76-
Some(builder)
77-
} else {
78-
None
79-
}
75+
};
76+
build_decl_hover(&mut builder, db, effective_typ, decl_id);
8077
}
8178
LuaPropertyOwnerId::Member(member_id) => {
82-
if let Some(semantic_model) = semantic_model {
83-
let mut builder = HoverBuilder::new(semantic_model, token, is_completion);
84-
if let Some(typ) = typ {
85-
build_member_hover(&mut builder, db, typ, member_id);
86-
} else {
79+
let effective_typ = match typ {
80+
Some(t) => t,
81+
None => {
8782
let member = db.get_member_index().get_member(&member_id)?;
88-
let typ = member.get_decl_type();
89-
build_member_hover(&mut builder, db, typ.clone(), member_id);
83+
member.get_decl_type().clone()
9084
}
91-
Some(builder)
92-
} else {
93-
None
94-
}
85+
};
86+
build_member_hover(&mut builder, db, effective_typ, member_id);
9587
}
9688
LuaPropertyOwnerId::TypeDecl(type_decl_id) => {
97-
if let Some(semantic_model) = semantic_model {
98-
let mut builder = HoverBuilder::new(semantic_model, token, is_completion);
99-
build_type_decl_hover(&mut builder, db, type_decl_id);
100-
Some(builder)
101-
} else {
102-
None
103-
}
89+
build_type_decl_hover(&mut builder, db, type_decl_id);
10490
}
105-
_ => None,
91+
_ => return None,
10692
}
93+
Some(builder)
10794
}
10895

10996
fn build_decl_hover(
@@ -448,5 +435,3 @@ fn get_member_owner(
448435
}
449436
resolved_property_owner
450437
}
451-
452-

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

Lines changed: 96 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@ pub fn hover_function_type(
2929
) {
3030
match typ {
3131
LuaType::Function => builder.set_type_description(format!("function {}()", func_name)),
32-
LuaType::DocFunction(lua_func) => builder.set_type_description(hover_doc_function_type(
33-
db,
34-
&lua_func,
35-
function_member,
36-
func_name,
37-
)),
32+
LuaType::DocFunction(lua_func) => {
33+
// 泛型时会将`Signature`转为`DocFunction`
34+
builder.set_type_description(hover_doc_function_type(
35+
db,
36+
&lua_func,
37+
function_member,
38+
func_name,
39+
))
40+
}
3841
LuaType::Signature(signature_id) => hover_signature_type(
3942
builder,
4043
db,
@@ -50,41 +53,64 @@ pub fn hover_function_type(
5053
}
5154
}
5255

53-
#[allow(unused)]
56+
// 泛型时会将`Signature`转为`DocFunction`, 我们必须处理这种情况
5457
fn hover_doc_function_type(
5558
db: &DbIndex,
5659
lua_func: &LuaFunctionType,
5760
owner_member: Option<&LuaMember>,
5861
func_name: &str,
5962
) -> String {
60-
let async_prev = if lua_func.is_async() { "async " } else { "" };
61-
let mut type_prev = "function ";
63+
dbg!(&lua_func);
64+
let async_label = if lua_func.is_async() { "async " } else { "" };
65+
let mut type_label = "function ";
6266
// 有可能来源于类. 例如: `local add = class.add`, `add()`应被视为类方法
63-
let full_func_name = if let Some(owner_member) = owner_member {
67+
let full_name = if let Some(owner_member) = owner_member {
6468
let mut name = String::new();
6569
let parent_owner = owner_member.get_owner();
66-
if let LuaMemberOwner::Type(ty) = &parent_owner {
70+
if let LuaMemberOwner::Type(ty) = &parent_owner.clone() {
6771
name.push_str(ty.get_simple_name());
6872
if owner_member.is_field().is_some() {
69-
type_prev = "(field) ";
73+
type_label = "(field) ";
7074
}
7175
}
7276
match owner_member.get_decl_type() {
7377
LuaType::DocFunction(func) => {
7478
if func.is_colon_define()
7579
|| func.get_params().first().and_then(|param| {
76-
param.1.as_ref().map(|ty| {
77-
param.0 == "self"
78-
&& humanize_type(db, ty, RenderLevel::Normal) == "self"
79-
})
80+
param
81+
.1
82+
.as_ref()
83+
.map(|ty| param.0 == "self" && ty.is_self_infer())
8084
}) == Some(true)
8185
{
82-
type_prev = "(method) ";
86+
type_label = "(method) ";
8387
name.push_str(":");
8488
} else {
8589
name.push_str(".");
8690
}
8791
}
92+
LuaType::Signature(signature_id) => {
93+
let signature = db.get_signature_index().get(&signature_id);
94+
if let Some(signature) = signature {
95+
if signature.is_colon_define
96+
|| signature // @field 定义的`docfunction`会被视为`signature`, 因此这里也需要匹配以转换为`method`
97+
.get_type_params()
98+
.first()
99+
.and_then(|param| {
100+
param
101+
.1
102+
.as_ref()
103+
.map(|ty| param.0 == "self" && ty.is_self_infer())
104+
})
105+
.is_some()
106+
{
107+
type_label = "(method) ";
108+
name.push_str(":");
109+
} else {
110+
name.push_str(".");
111+
}
112+
}
113+
}
88114
_ => {}
89115
}
90116
if let LuaMemberKey::Name(n) = owner_member.get_key() {
@@ -104,7 +130,7 @@ fn hover_doc_function_type(
104130
if index == 0
105131
&& param.1.is_some()
106132
&& name == "self"
107-
&& humanize_type(db, param.1.as_ref().unwrap(), RenderLevel::Normal) == "self"
133+
&& param.1.as_ref().unwrap().is_self_infer()
108134
{
109135
"".to_string()
110136
} else if let Some(ty) = &param.1 {
@@ -117,34 +143,21 @@ fn hover_doc_function_type(
117143
.collect::<Vec<_>>()
118144
.join(", ");
119145

120-
let rets = lua_func.get_ret();
121-
122-
let mut result = String::new();
123-
result.push_str(type_prev);
124-
result.push_str(async_prev);
125-
result.push_str(&full_func_name);
126-
result.push_str("(");
127-
result.push_str(params.as_str());
128-
result.push_str(")");
129-
130-
if !rets.is_empty() {
131-
result.push_str(" -> ");
132-
if rets.len() > 1 {
133-
result.push_str("(");
134-
}
135-
result.push_str(
136-
&rets
137-
.iter()
138-
.map(|ty| humanize_type(db, ty, RenderLevel::Normal))
139-
.collect::<Vec<_>>()
140-
.join(", "),
141-
);
142-
if rets.len() > 1 {
143-
result.push_str(")");
146+
let rets = {
147+
let rets = lua_func.get_ret();
148+
if rets.is_empty() {
149+
"".to_string()
150+
} else {
151+
format!(
152+
" -> {}",
153+
rets.iter()
154+
.map(|ty| humanize_type(db, ty, RenderLevel::Simple))
155+
.collect::<Vec<_>>()
156+
.join(", ")
157+
)
144158
}
145-
}
146-
147-
result
159+
};
160+
format_function_type(type_label, async_label, full_name, params, rets)
148161
}
149162

150163
fn hover_signature_type(
@@ -155,6 +168,7 @@ fn hover_signature_type(
155168
func_name: &str,
156169
) -> Option<()> {
157170
let signature = db.get_signature_index().get(&signature_id)?;
171+
let call_signature = builder.get_call_signature();
158172

159173
let mut type_label = "function ";
160174
// 有可能来源于类. 例如: `local add = class.add`, `add()`应被视为类定义的内容
@@ -198,24 +212,20 @@ fn hover_signature_type(
198212
.collect::<Vec<_>>()
199213
.join(", ");
200214
let rets = get_signature_rets_string(db, signature, builder.is_completion, None);
201-
let mut result = String::new();
202-
if type_label.starts_with("function") {
203-
result.push_str(async_label);
204-
result.push_str(type_label);
205-
} else {
206-
result.push_str(type_label);
207-
result.push_str(async_label);
215+
let result = format_function_type(type_label, async_label, full_name.clone(), params, rets);
216+
// 由于 @field 定义的`docfunction`会被视为`signature`, 因此这里额外处理
217+
if let Some(call_signature) = &call_signature {
218+
if call_signature.get_params() == signature.get_type_params() {
219+
// 如果具有完全匹配的签名, 那么将其设置为当前签名, 且不显示重载
220+
builder.set_type_description(result);
221+
builder.signature_overload = None;
222+
return Some(());
223+
}
208224
}
209-
result.push_str(&full_name);
210-
result.push_str("(");
211-
result.push_str(params.as_str());
212-
result.push_str(")");
213-
result.push_str(rets.as_str());
214225
result
215226
};
216227
// 构建所有重载
217228
let overloads: Vec<String> = {
218-
let call_signature = builder.get_call_signature();
219229
let mut overloads = Vec::new();
220230
for (_, overload) in signature.overloads.iter().enumerate() {
221231
let async_label = if overload.is_async() { "async " } else { "" };
@@ -234,20 +244,8 @@ fn hover_signature_type(
234244
.join(", ");
235245
let rets =
236246
get_signature_rets_string(db, signature, builder.is_completion, Some(overload));
237-
238-
let mut result = String::new();
239-
if type_label.starts_with("function") {
240-
result.push_str(async_label);
241-
result.push_str(type_label);
242-
} else {
243-
result.push_str(type_label);
244-
result.push_str(async_label);
245-
}
246-
result.push_str(&full_name);
247-
result.push_str("(");
248-
result.push_str(params.as_str());
249-
result.push_str(")");
250-
result.push_str(rets.as_str());
247+
let result =
248+
format_function_type(type_label, async_label, full_name.clone(), params, rets);
251249

252250
if let Some(call_signature) = &call_signature {
253251
if *call_signature == **overload {
@@ -298,13 +296,17 @@ fn get_signature_rets_string(
298296
overload_rets_string
299297
} else {
300298
let rets = &signature.return_docs;
301-
format!(
302-
" -> {}",
303-
rets.iter()
304-
.map(|ret| humanize_type(db, &ret.type_ref, RenderLevel::Simple))
305-
.collect::<Vec<_>>()
306-
.join(", ")
307-
)
299+
if rets.is_empty() {
300+
"".to_string()
301+
} else {
302+
format!(
303+
" -> {}",
304+
rets.iter()
305+
.map(|ret| humanize_type(db, &ret.type_ref, RenderLevel::Simple))
306+
.collect::<Vec<_>>()
307+
.join(", ")
308+
)
309+
}
308310
};
309311
result.push_str(rets.as_str());
310312
} else {
@@ -351,3 +353,18 @@ fn get_signature_rets_string(
351353
};
352354
result
353355
}
356+
357+
fn format_function_type(
358+
type_label: &str,
359+
async_label: &str,
360+
full_name: String,
361+
params: String,
362+
rets: String,
363+
) -> String {
364+
let prefix = if type_label.starts_with("function") {
365+
format!("{}{}", async_label, type_label)
366+
} else {
367+
format!("{}{}", type_label, async_label)
368+
};
369+
format!("{}{}({}){}", prefix, full_name, params, rets)
370+
}

0 commit comments

Comments
 (0)