Skip to content

Commit 159fd49

Browse files
committed
hover: 赋值语句左值显示右值结果
1 parent 69c39df commit 159fd49

4 files changed

Lines changed: 114 additions & 9 deletions

File tree

crates/emmylua_code_analysis/src/semantic/infer/infer_name.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use emmylua_parser::{LuaAssignStat, LuaAstNode, LuaNameExpr};
1+
use emmylua_parser::{LuaAstNode, LuaNameExpr};
22

33
use crate::{
44
db_index::{DbIndex, LuaDeclOrMemberId},
@@ -37,12 +37,9 @@ pub fn infer_name_expr(
3737
let flow_chain = db.get_flow_index().get_flow_chain(file_id, flow_id);
3838
let root = name_expr.get_root();
3939
if let Some(flow_chain) = flow_chain {
40-
let mut position = name_expr.get_position();
41-
// 如果是赋值语句, 那么我们使用赋值语句的结束位置来获取类型, 应用于`hover`左值
42-
if let Some(assign_stat) = name_expr.get_parent::<LuaAssignStat>() {
43-
position = assign_stat.get_range().end();
44-
}
45-
for type_assert in flow_chain.get_type_asserts(name, position, Some(decl_id.position)) {
40+
for type_assert in
41+
flow_chain.get_type_asserts(name, name_expr.get_position(), Some(decl_id.position))
42+
{
4643
decl_type = type_assert.tighten_type(db, cache, &root, decl_type)?;
4744
}
4845
}

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

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,10 @@ fn build_decl_hover(
152152
};
153153
builder.set_type_description(format!("{}{}: {}", prefix, decl.get_name(), const_value));
154154
} else {
155+
let decl_hover_type =
156+
get_hover_type(builder, builder.semantic_model).unwrap_or(typ.clone());
155157
let type_humanize_text =
156-
hover_type(builder, &typ, Some(RenderLevel::Detailed)).unwrap_or_default();
158+
hover_type(builder, &decl_hover_type, Some(RenderLevel::Detailed)).unwrap_or_default();
157159
let prefix = if decl.is_local() {
158160
"local "
159161
} else {
@@ -251,8 +253,10 @@ fn build_member_hover(
251253
builder.set_type_description(format!("(field) {}: {}", member_name, const_value));
252254
builder.set_location_path(Some(&member));
253255
} else {
256+
let member_hover_type =
257+
get_hover_type(builder, builder.semantic_model).unwrap_or(typ.clone());
254258
let type_humanize_text =
255-
hover_type(builder, &typ, Some(RenderLevel::Simple)).unwrap_or_default();
259+
hover_type(builder, &member_hover_type, Some(RenderLevel::Simple)).unwrap_or_default();
256260
builder.set_type_description(format!("(field) {}: {}", member_name, type_humanize_text));
257261
builder.set_location_path(Some(&member));
258262
}
@@ -445,3 +449,36 @@ fn get_member_owner(
445449
}
446450
resolved_property_owner
447451
}
452+
453+
pub fn get_hover_type(builder: &HoverBuilder, semantic_model: &SemanticModel) -> Option<LuaType> {
454+
let assign_stat = LuaAssignStat::cast(builder.get_trigger_token()?.parent()?.parent()?)?;
455+
let (vars, exprs) = assign_stat.get_var_and_expr_list();
456+
for (i, var) in vars.iter().enumerate() {
457+
if var
458+
.syntax()
459+
.text_range()
460+
.contains(builder.get_trigger_token()?.text_range().start())
461+
{
462+
let mut expr: Option<&emmylua_parser::LuaExpr> = exprs.get(i);
463+
let multi_return_index = if expr.is_none() {
464+
expr = Some(&exprs.last().unwrap());
465+
i + 1 - exprs.len()
466+
} else {
467+
0
468+
};
469+
470+
let expr_type = semantic_model.infer_expr(expr.unwrap().clone());
471+
match expr_type {
472+
Ok(expr_type) => match expr_type {
473+
LuaType::MuliReturn(muli_return) => {
474+
return muli_return.get_type(multi_return_index).map(|t| t.clone());
475+
}
476+
_ => return Some(expr_type),
477+
},
478+
Err(_) => return None,
479+
}
480+
}
481+
}
482+
483+
None
484+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,4 +333,8 @@ impl<'a> HoverBuilder<'a> {
333333
range,
334334
})
335335
}
336+
337+
pub fn get_trigger_token(&self) -> Option<LuaSyntaxToken> {
338+
self.trigger_token.clone()
339+
}
336340
}

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

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,71 @@ mod tests {
1717
},
1818
));
1919
}
20+
21+
#[test]
22+
fn test_right_to_left() {
23+
let mut ws = HoverVirtualWorkspace::new();
24+
assert!(ws.check_hover(
25+
r#"
26+
---@class H4
27+
local m = {
28+
x = 1
29+
}
30+
31+
---@type H4
32+
local m1
33+
34+
m1.x = {}
35+
m1.<??>x = {}
36+
"#,
37+
VirtualHoverResult {
38+
value: "\n```lua\n(field) x: integer = 1\n```\n\n---\n".to_string(),
39+
},
40+
));
41+
42+
assert!(ws.check_hover(
43+
r#"
44+
---@class Node
45+
---@field x number
46+
---@field right Node?
47+
48+
---@return Node
49+
local function createRBNode()
50+
end
51+
52+
---@type Node
53+
local node
54+
55+
if node.right then
56+
else
57+
node.<??>right = createRBNode()
58+
end
59+
"#,
60+
VirtualHoverResult {
61+
value: "\n```lua\n(field) right: Node\n```\n\n---\n".to_string(),
62+
},
63+
));
64+
65+
assert!(ws.check_hover(
66+
r#"
67+
---@class Node1
68+
---@field x number
69+
70+
---@return Node1
71+
local function createRBNode()
72+
end
73+
74+
---@type Node1?
75+
local node
76+
77+
if node then
78+
else
79+
<??>node = createRBNode()
80+
end
81+
"#,
82+
VirtualHoverResult {
83+
value: "\n```lua\nlocal node: Node1 {\n x: number,\n}\n```\n\n---\n".to_string(),
84+
},
85+
));
86+
}
2087
}

0 commit comments

Comments
 (0)