@@ -905,6 +905,57 @@ fn resolve_hover_parameter_doc(
905905 None
906906}
907907
908+ /// Find the definition used by hover, excluding unrelated keyword-parameter results.
909+ fn find_hover_definition (
910+ transaction : & Transaction < ' _ > ,
911+ handle : & Handle ,
912+ position : TextSize ,
913+ prefer_pyi : bool ,
914+ keyword_argument_identifier : Option < & Identifier > ,
915+ ) -> Option < FindDefinitionItemWithDocstring > {
916+ transaction
917+ . find_definition (
918+ handle,
919+ position,
920+ FindPreference {
921+ prefer_pyi,
922+ ..Default :: default ( )
923+ } ,
924+ )
925+ . ok ( ) ?
926+ . into_vec ( )
927+ . into_iter ( )
928+ . next ( )
929+ . filter ( |item| {
930+ keyword_argument_identifier. is_none_or ( |identifier| {
931+ item. module . code_at ( item. definition_range ) == identifier. id . as_str ( )
932+ } )
933+ } )
934+ }
935+
936+ /// Prefer non-empty stub documentation, falling back to the executable definition.
937+ fn resolve_hover_docstring (
938+ transaction : & Transaction < ' _ > ,
939+ handle : & Handle ,
940+ position : TextSize ,
941+ keyword_argument_identifier : Option < & Identifier > ,
942+ fallback : Option < Docstring > ,
943+ ) -> Option < Docstring > {
944+ find_hover_definition (
945+ transaction,
946+ handle,
947+ position,
948+ true ,
949+ keyword_argument_identifier,
950+ )
951+ . and_then ( |item| {
952+ item. docstring_range
953+ . map ( |range| Docstring ( range, item. module ) )
954+ } )
955+ . filter ( |docstring| !docstring. resolve ( ) . trim ( ) . is_empty ( ) )
956+ . or ( fallback)
957+ }
958+
908959pub fn get_hover (
909960 transaction : & Transaction < ' _ > ,
910961 handle : & Handle ,
@@ -971,42 +1022,19 @@ pub fn get_hover_with_verbosity(
9711022
9721023 let fallback_name_from_type = fallback_hover_name_from_type ( & type_) ;
9731024 let keyword_argument_identifier = keyword_argument_identifier ( transaction, handle, position) ;
974- let find_definition = |prefer_pyi| {
975- transaction
976- . find_definition (
977- handle,
978- position,
979- FindPreference {
980- prefer_pyi,
981- ..Default :: default ( )
982- } ,
983- )
984- . map ( Vec1 :: into_vec)
985- . unwrap_or_default ( )
986- . into_iter ( )
987- . next ( )
988- . filter ( |item| {
989- keyword_argument_identifier
990- . as_ref ( )
991- . is_none_or ( |identifier| {
992- item. module . code_at ( item. definition_range ) == identifier. id . as_str ( )
993- } )
994- } )
995- } ;
996- let preferred_docstring = find_definition ( true )
997- . and_then ( |item| {
998- item. docstring_range
999- . map ( |range| Docstring ( range, item. module ) )
1000- } )
1001- . filter ( |docstring| !docstring. resolve ( ) . trim ( ) . is_empty ( ) ) ;
10021025 let ( kind, name, fallback_docstring) = if let Some ( FindDefinitionItemWithDocstring {
10031026 metadata,
10041027 definition_range : definition_location,
10051028 module,
10061029 docstring_range,
10071030 display_name,
1008- } ) = find_definition ( false )
1009- {
1031+ } ) = find_hover_definition (
1032+ transaction,
1033+ handle,
1034+ position,
1035+ false ,
1036+ keyword_argument_identifier. as_ref ( ) ,
1037+ ) {
10101038 let kind = metadata. symbol_kind ( ) ;
10111039 let name = hover_name_from_definition_snippet (
10121040 module. code_at ( definition_location) ,
@@ -1018,6 +1046,13 @@ pub fn get_hover_with_verbosity(
10181046 } else {
10191047 ( None , fallback_name_from_type, None )
10201048 } ;
1049+ let docstring = resolve_hover_docstring (
1050+ transaction,
1051+ handle,
1052+ position,
1053+ keyword_argument_identifier. as_ref ( ) ,
1054+ fallback_docstring,
1055+ ) ;
10211056
10221057 let name = name. or_else ( || identifier_text_at ( transaction, handle, position) ) ;
10231058
@@ -1075,8 +1110,6 @@ pub fn get_hover_with_verbosity(
10751110 None => ( None , false ) ,
10761111 } ;
10771112
1078- let docstring = preferred_docstring. or ( fallback_docstring) ;
1079-
10801113 let parameter_doc = resolve_hover_parameter_doc ( transaction, handle, position) ;
10811114
10821115 Some ( HoverResult {
0 commit comments