Skip to content

Commit 7a9992e

Browse files
committed
optimize hover nil
1 parent f211bf5 commit 7a9992e

File tree

5 files changed

+70
-40
lines changed

5 files changed

+70
-40
lines changed

crates/emmylua_code_analysis/src/compilation/test/and_or_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,6 @@ mod test {
7272

7373
let c = ws.expr_ty("c");
7474
let c_desc = ws.humanize_type(c);
75-
assert_eq!(c_desc, "(string|nil)");
75+
assert_eq!(c_desc, "string?");
7676
}
7777
}

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,17 @@ fn humanize_union_type(db: &DbIndex, union: &LuaUnionType, level: RenderLevel) -
175175
// 需要确保顺序
176176
let mut seen = HashSet::new();
177177
let mut type_strings = Vec::new();
178+
let mut has_nil = false;
178179
for ty in types.iter() {
180+
if ty.is_nil() {
181+
has_nil = true;
182+
continue;
183+
}
179184
let type_str = humanize_type(db, ty, level.next_level());
180185
if seen.insert(type_str.clone()) {
181186
type_strings.push(type_str);
182187
}
183188
}
184-
185189
// 取指定数量的类型
186190
let display_types: Vec<_> = type_strings.into_iter().take(num).collect();
187191
let type_str = display_types.join("|");
@@ -192,9 +196,9 @@ fn humanize_union_type(db: &DbIndex, union: &LuaUnionType, level: RenderLevel) -
192196
};
193197

194198
if display_types.len() == 1 {
195-
type_str
199+
format!("{}{}", type_str, if has_nil { "?" } else { "" })
196200
} else {
197-
format!("({}{})", type_str, dots)
201+
format!("({}{}){}", type_str, dots, if has_nil { "?" } else { "" })
198202
}
199203
}
200204

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,7 @@ fn build_decl_hover(
154154
} else {
155155
let decl_hover_type =
156156
get_hover_type(builder, builder.semantic_model).unwrap_or(typ.clone());
157-
let type_humanize_text =
158-
hover_type(builder, &decl_hover_type, Some(RenderLevel::Detailed)).unwrap_or_default();
157+
let type_humanize_text = hover_type(builder, &decl_hover_type, Some(RenderLevel::Detailed));
159158
let prefix = if decl.is_local() {
160159
"local "
161160
} else {
@@ -255,8 +254,7 @@ fn build_member_hover(
255254
} else {
256255
let member_hover_type =
257256
get_hover_type(builder, builder.semantic_model).unwrap_or(typ.clone());
258-
let type_humanize_text =
259-
hover_type(builder, &member_hover_type, Some(RenderLevel::Simple)).unwrap_or_default();
257+
let type_humanize_text = hover_type(builder, &member_hover_type, Some(RenderLevel::Simple));
260258
builder.set_type_description(format!("(field) {}: {}", member_name, type_humanize_text));
261259
builder.set_location_path(Some(&member));
262260
}

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

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,7 @@ fn build_signature_ret_type(
376376
i: usize,
377377
) -> String {
378378
let type_expansion_count = builder.get_type_expansion_count();
379-
let type_text =
380-
hover_type(builder, &ret_info.type_ref, Some(RenderLevel::Simple)).unwrap_or_default();
379+
let type_text = hover_type(builder, &ret_info.type_ref, Some(RenderLevel::Simple));
381380
if builder.get_type_expansion_count() > type_expansion_count {
382381
// 重新设置`type_expansion`
383382
if let Some(pop_type_expansion) =
@@ -419,37 +418,30 @@ pub fn hover_type(
419418
builder: &mut HoverBuilder,
420419
ty: &LuaType,
421420
fallback_level: Option<RenderLevel>, // 当有值时, 若获取类型描述为空会回退到使用`humanize_type()`
422-
) -> Option<String> {
421+
) -> String {
423422
let db = builder.semantic_model.get_db();
424-
let type_text = match ty {
423+
match ty {
425424
LuaType::Ref(type_decl_id) => {
426-
let type_decl = db.get_type_index().get_type_decl(type_decl_id)?;
427-
428-
if type_decl.is_alias() {
429-
let origin = type_decl.get_alias_origin(db, None);
430-
match origin {
431-
Some(LuaType::MultiLineUnion(multi_union)) => hover_multi_line_union_type(
425+
if let Some(type_decl) = db.get_type_index().get_type_decl(type_decl_id) {
426+
if let Some(LuaType::MultiLineUnion(multi_union)) =
427+
type_decl.get_alias_origin(db, None)
428+
{
429+
return hover_multi_line_union_type(
432430
builder,
433431
db,
434432
multi_union.as_ref(),
435433
Some(type_decl.get_full_name()),
436-
),
437-
_ => None,
434+
)
435+
.unwrap_or_default();
438436
}
439-
} else {
440-
None
441437
}
438+
humanize_type(db, ty, fallback_level.unwrap_or(RenderLevel::Simple))
442439
}
443440
LuaType::MultiLineUnion(multi_union) => {
444-
hover_multi_line_union_type(builder, db, multi_union.as_ref(), None)
441+
hover_multi_line_union_type(builder, db, multi_union.as_ref(), None).unwrap_or_default()
445442
}
446-
LuaType::Union(union) => Some(hover_union_type(builder, union, RenderLevel::Detailed)),
447-
_ => None,
448-
};
449-
match (fallback_level, type_text) {
450-
(Some(level), Some(text)) if text.is_empty() => Some(humanize_type(db, ty, level)),
451-
(Some(level), None) => Some(humanize_type(db, ty, level)),
452-
(_, text) => text,
443+
LuaType::Union(union) => hover_union_type(builder, union, RenderLevel::Detailed),
444+
_ => humanize_type(db, ty, fallback_level.unwrap_or(RenderLevel::Simple)),
453445
}
454446
}
455447

@@ -468,17 +460,34 @@ fn hover_union_type(
468460
return "union<...>".to_string();
469461
}
470462
};
471-
let type_str = types
472-
.iter()
473-
.take(num)
474-
.filter_map(|ty| hover_type(builder, ty, None))
475-
.collect::<Vec<_>>()
476-
.join("|");
477-
if type_str.is_empty() {
478-
return "".to_string();
463+
// 需要确保顺序
464+
let mut seen = HashSet::new();
465+
let mut type_strings = Vec::new();
466+
let mut has_nil = false;
467+
for ty in types.iter() {
468+
if ty.is_nil() {
469+
has_nil = true;
470+
continue;
471+
}
472+
let type_str = hover_type(builder, ty, Some(level.next_level()));
473+
if seen.insert(type_str.clone()) {
474+
type_strings.push(type_str);
475+
}
476+
}
477+
// 取指定数量的类型
478+
let display_types: Vec<_> = type_strings.into_iter().take(num).collect();
479+
let type_str = display_types.join("|");
480+
let dots = if display_types.len() < types.len() {
481+
"..."
482+
} else {
483+
""
484+
};
485+
486+
if display_types.len() == 1 {
487+
format!("{}{}", type_str, if has_nil { "?" } else { "" })
488+
} else {
489+
format!("({}{}){}", type_str, dots, if has_nil { "?" } else { "" })
479490
}
480-
let dots = if types.len() > num { "..." } else { "" };
481-
format!("({}{})", type_str, dots)
482491
}
483492

484493
fn hover_multi_line_union_type(

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,23 @@ mod tests {
8484
},
8585
));
8686
}
87+
88+
#[test]
89+
fn test_hover_nil() {
90+
let mut ws = HoverVirtualWorkspace::new();
91+
assert!(ws.check_hover(
92+
r#"
93+
---@class A
94+
---@field a? number
95+
96+
---@type A
97+
local a
98+
99+
local d = a.<??>a
100+
"#,
101+
VirtualHoverResult {
102+
value: "\n```lua\n(field) a: number?\n```\n\n---\n".to_string(),
103+
},
104+
));
105+
}
87106
}

0 commit comments

Comments
 (0)