Skip to content

Commit 10960e4

Browse files
committed
fix: render alias call and generic declaration syntax in hovers
1 parent 72c5c6f commit 10960e4

3 files changed

Lines changed: 133 additions & 25 deletions

File tree

crates/emmylua_code_analysis/src/db_index/type/humanize_type.rs

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,35 @@ impl<'a> TypeHumanizer<'a> {
259259
};
260260

261261
w.write_str(&full_name)?;
262+
if generic.is_empty() {
263+
return Ok(());
264+
}
265+
262266
w.write_char('<')?;
263-
for (i, param) in generic.iter().enumerate() {
264-
if i > 0 {
265-
w.write_str(", ")?;
267+
let saved = self.level;
268+
self.level = self.child_level();
269+
let result = (|| {
270+
for (i, param) in generic.iter().enumerate() {
271+
if i > 0 {
272+
w.write_str(", ")?;
273+
}
274+
if param.is_const {
275+
w.write_str("const ")?;
276+
}
277+
w.write_str(&param.name)?;
278+
if let Some(constraint) = &param.constraint {
279+
w.write_str(" extends ")?;
280+
self.write_type(constraint, w)?;
281+
}
282+
if let Some(default_type) = &param.default {
283+
w.write_str(" = ")?;
284+
self.write_type(default_type, w)?;
285+
}
266286
}
267-
w.write_str(&param.name)?;
268-
}
287+
Ok(())
288+
})();
289+
self.level = saved;
290+
result?;
269291
w.write_char('>')
270292
}
271293

@@ -515,29 +537,56 @@ impl<'a> TypeHumanizer<'a> {
515537
// ─── Call (alias call) ──────────────────────────────────────────
516538

517539
fn write_call_type<W: Write>(&mut self, inner: &LuaAliasCallType, w: &mut W) -> fmt::Result {
518-
let basic = match inner.get_call_kind() {
519-
LuaAliasCallKind::Sub => "sub",
520-
LuaAliasCallKind::Add => "add",
521-
LuaAliasCallKind::KeyOf => "keyof",
522-
LuaAliasCallKind::Extends => "extends",
523-
LuaAliasCallKind::Select => "select",
524-
LuaAliasCallKind::Unpack => "unpack",
525-
LuaAliasCallKind::Index => "index",
526-
LuaAliasCallKind::RawGet => "rawget",
527-
LuaAliasCallKind::Merge => "Merge",
528-
};
529-
w.write_str(basic)?;
530-
w.write_char('<')?;
540+
let operands = inner.get_operands();
531541
let saved = self.level;
532542
self.level = self.child_level();
533-
for (i, ty) in inner.get_operands().iter().enumerate() {
534-
if i > 0 {
535-
w.write_char(',')?;
543+
let result = (|| match inner.get_call_kind() {
544+
LuaAliasCallKind::KeyOf => {
545+
w.write_str("keyof ")?;
546+
for (i, ty) in operands.iter().enumerate() {
547+
if i > 0 {
548+
w.write_char(',')?;
549+
}
550+
self.write_type(ty, w)?;
551+
}
552+
Ok(())
536553
}
537-
self.write_type(ty, w)?;
538-
}
554+
LuaAliasCallKind::Extends if operands.len() == 2 => {
555+
self.write_type(&operands[0], w)?;
556+
w.write_str(" extends ")?;
557+
self.write_type(&operands[1], w)
558+
}
559+
LuaAliasCallKind::Index if operands.len() == 2 => {
560+
self.write_type(&operands[0], w)?;
561+
w.write_char('[')?;
562+
self.write_type(&operands[1], w)?;
563+
w.write_char(']')
564+
}
565+
call_kind => {
566+
let basic = match call_kind {
567+
LuaAliasCallKind::Sub => "sub",
568+
LuaAliasCallKind::Add => "add",
569+
LuaAliasCallKind::KeyOf => "keyof",
570+
LuaAliasCallKind::Extends => "extends",
571+
LuaAliasCallKind::Select => "select",
572+
LuaAliasCallKind::Unpack => "unpack",
573+
LuaAliasCallKind::Index => "index",
574+
LuaAliasCallKind::RawGet => "rawget",
575+
LuaAliasCallKind::Merge => "Merge",
576+
};
577+
w.write_str(basic)?;
578+
w.write_char('<')?;
579+
for (i, ty) in operands.iter().enumerate() {
580+
if i > 0 {
581+
w.write_char(',')?;
582+
}
583+
self.write_type(ty, w)?;
584+
}
585+
w.write_char('>')
586+
}
587+
})();
539588
self.level = saved;
540-
w.write_char('>')
589+
result
541590
}
542591

543592
// ─── DocFunction ────────────────────────────────────────────────

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ pub fn build_type_decl_hover(
1414
let type_decl = db.get_type_index().get_type_decl(&type_decl_id)?;
1515
let type_description = if type_decl.is_alias() {
1616
if let Some(origin) = type_decl.get_alias_origin(db, None) {
17+
let type_name =
18+
humanize_type(db, &LuaType::Def(type_decl_id.clone()), RenderLevel::Normal);
1719
let origin_type = humanize_type(db, &origin, builder.detail_render_level);
18-
format!("(alias) {} = {}", type_decl.get_name(), origin_type)
20+
format!("(alias) {} = {}", type_name, origin_type)
1921
} else {
2022
"".to_string()
2123
}

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,63 @@ mod tests {
295295
Ok(())
296296
}
297297

298+
#[gtest]
299+
fn test_hover_special_alias_call_type_syntax() -> Result<()> {
300+
let mut ws = ProviderVirtualWorkspace::new();
301+
check!(ws.check_hover(
302+
r#"
303+
---@class KeyofHoverShape
304+
---@field name string
305+
306+
---@type keyof KeyofHoverShape
307+
local <??>key
308+
"#,
309+
VirtualHoverResult {
310+
value: "```lua\nlocal key: keyof KeyofHoverShape\n```".to_string(),
311+
},
312+
));
313+
314+
check!(ws.check_hover(
315+
r#"
316+
---@class ExtendsHoverShape
317+
---@field name string
318+
319+
---@type ExtendsHoverShape extends table
320+
local <??>is_table
321+
"#,
322+
VirtualHoverResult {
323+
value: "```lua\nlocal is_table: ExtendsHoverShape extends table\n```".to_string(),
324+
},
325+
));
326+
327+
check!(ws.check_hover(
328+
r#"
329+
---@alias AB<??>C<K extends keyof T, T> T[K]
330+
"#,
331+
VirtualHoverResult {
332+
value: "```lua\n(alias) ABC<K extends keyof T, T> = T[K]\n```".to_string(),
333+
},
334+
));
335+
336+
check!(
337+
ws.check_hover(
338+
r#"
339+
---@class BoxHoverShape
340+
---@field name string
341+
342+
---@class BoxHoverShape<??>Box<K extends keyof BoxHoverShape, T>
343+
---@field value T
344+
"#,
345+
VirtualHoverResult {
346+
value:
347+
"```lua\n(class) BoxHoverShapeBox<K extends keyof BoxHoverShape, T>\n```"
348+
.to_string(),
349+
},
350+
)
351+
);
352+
Ok(())
353+
}
354+
298355
#[gtest]
299356
fn test_hover_narrowed_function_type() -> Result<()> {
300357
let mut ws = ProviderVirtualWorkspace::new();

0 commit comments

Comments
 (0)