Skip to content

Commit 66913eb

Browse files
fix
1 parent 541b146 commit 66913eb

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

pyrefly/lib/lsp/wasm/hover.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use std::collections::HashMap;
1111

12+
use dupe::Dupe;
1213
use lsp_types::Hover;
1314
use lsp_types::HoverContents;
1415
use lsp_types::MarkupContent;
@@ -309,6 +310,38 @@ fn identifier_text_at(
309310
.map(|id| id.identifier.id.to_string())
310311
}
311312

313+
fn docstring_for_class_object_type(
314+
transaction: &Transaction<'_>,
315+
handle: &Handle,
316+
type_: &Type,
317+
) -> Option<Docstring> {
318+
let qname = match type_ {
319+
Type::ClassDef(cls) => cls.qname(),
320+
Type::Type(inner) => match inner.as_ref() {
321+
Type::ClassType(cls) => cls.qname(),
322+
_ => return None,
323+
},
324+
_ => return None,
325+
};
326+
let definition_handle = Handle::new(
327+
qname.module_name(),
328+
qname.module_path().dupe(),
329+
handle.sys_info().dupe(),
330+
);
331+
let definition = transaction
332+
.find_definition(
333+
&definition_handle,
334+
qname.range().start(),
335+
FindPreference {
336+
resolve_call_dunders: false,
337+
..Default::default()
338+
},
339+
)
340+
.into_iter()
341+
.find(|item| item.definition_range == qname.range())?;
342+
Some(Docstring(definition.docstring_range?, definition.module))
343+
}
344+
312345
fn collect_typed_dict_fields_for_hover<'a>(
313346
solver: &AnswersSolver<TransactionHandle<'a>>,
314347
ty: &Type,
@@ -624,7 +657,7 @@ pub fn get_hover(
624657
let docstring = if let (Some(docstring), Some(module)) = (docstring_range, module) {
625658
Some(Docstring(docstring, module))
626659
} else {
627-
None
660+
docstring_for_class_object_type(transaction, handle, &type_)
628661
};
629662

630663
let mut parameter_doc = keyword_argument_documentation(transaction, handle, position)

pyrefly/lib/test/lsp/hover.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,34 @@ Widget docstring"#
10081008
);
10091009
}
10101010

1011+
#[test]
1012+
fn hover_on_property_returning_class_shows_class_docstring() {
1013+
let lib = r#"
1014+
from typing import Type
1015+
1016+
class current_timestamp:
1017+
"""The CURRENT_TIMESTAMP() SQL function."""
1018+
def __init__(self, *args: object, **kwargs: object) -> None: ...
1019+
1020+
class Func:
1021+
@property
1022+
def current_timestamp(self) -> Type[current_timestamp]: ...
1023+
"#;
1024+
let code = r#"
1025+
from lib import Func
1026+
1027+
f = Func()
1028+
f.current_timestamp
1029+
# ^
1030+
"#;
1031+
let report =
1032+
get_batched_lsp_operations_report(&[("main", code), ("lib", lib)], get_test_report);
1033+
assert!(
1034+
report.contains("The CURRENT_TIMESTAMP() SQL function."),
1035+
"Expected hover to show the class docstring, got: {report}"
1036+
);
1037+
}
1038+
10111039
#[test]
10121040
fn hover_on_first_component_of_multi_part_import() {
10131041
let mymod_init = r#"# mymod/__init__.py

0 commit comments

Comments
 (0)