diff --git a/crates/emmylua_ls/src/handlers/hover/mod.rs b/crates/emmylua_ls/src/handlers/hover/mod.rs index b82a8b62..e3d60c7d 100644 --- a/crates/emmylua_ls/src/handlers/hover/mod.rs +++ b/crates/emmylua_ls/src/handlers/hover/mod.rs @@ -9,7 +9,7 @@ mod std_hover; pub use build_hover::build_hover_content_for_completion; use build_hover::build_semantic_info_hover; use emmylua_code_analysis::{EmmyLuaAnalysis, FileId}; -use emmylua_parser::LuaAstNode; +use emmylua_parser::{LuaAstNode, LuaTokenKind}; pub use find_origin::{find_all_same_named_members, find_member_origin_owner}; pub use hover_builder::HoverBuilder; pub use hover_humanize::infer_prefix_global_name; @@ -56,10 +56,20 @@ pub fn hover(analysis: &EmmyLuaAnalysis, file_id: FileId, position: Position) -> let token = match root.syntax().token_at_offset(position_offset) { TokenAtOffset::Single(token) => token, - TokenAtOffset::Between(_, right) => right, - TokenAtOffset::None => { - return None; + TokenAtOffset::Between(left, right) => { + if matches!( + right.kind().into(), + LuaTokenKind::TkDot + | LuaTokenKind::TkColon + | LuaTokenKind::TkLeftBracket + | LuaTokenKind::TkRightBracket + ) { + left + } else { + right + } } + TokenAtOffset::None => return None, }; match token { keywords if is_keyword(keywords.clone()) => { diff --git a/crates/emmylua_ls/src/handlers/test/hover_test.rs b/crates/emmylua_ls/src/handlers/test/hover_test.rs index 9f1b17f9..279f686c 100644 --- a/crates/emmylua_ls/src/handlers/test/hover_test.rs +++ b/crates/emmylua_ls/src/handlers/test/hover_test.rs @@ -310,4 +310,59 @@ mod tests { )); Ok(()) } + + #[gtest] + fn test_before_dot_returns_object_info() -> Result<()> { + let mut ws = ProviderVirtualWorkspace::new(); + ws.def( + r#" + ---@class Node + ---@field field number? + ---@field method fun(self: Node) + + ---@type Node + node = {} + + function node.method() end + "#, + ); + + check!(ws.check_hover( + r#" + node.field = nil + "#, + VirtualHoverResult { + value: "```lua\n(global) node: Node {\n field: number?,\n method: function,\n}\n```".to_string(), + }, + )); + + check!(ws.check_hover( + r#" + node:method() + "#, + VirtualHoverResult { + value: "```lua\n(global) node: Node {\n field: number?,\n method: function,\n}\n```".to_string(), + }, + )); + + check!(ws.check_hover( + r#" + node["key"] = "value" + "#, + VirtualHoverResult { + value: "```lua\n(global) node: Node {\n field: number?,\n method: function,\n}\n```".to_string(), + }, + )); + + check!(ws.check_hover( + r#" + node["key"] = "value" + "#, + VirtualHoverResult { + value: "\"key\"".to_string(), + }, + )); + + Ok(()) + } }