@@ -409,8 +409,8 @@ def get_placeholders(arg_list: list[str]):
409409 def get_documentation (self ):
410410 return self .doc_str
411411
412- def get_hover (self , long = False , include_doc = True , drop_arg = - 1 ):
413- return None , False
412+ def get_hover (self , long = False , drop_arg = - 1 ) -> tuple [ str | None , str | None , bool ] :
413+ return None , None , False
414414
415415 def get_signature (self , drop_arg = - 1 ):
416416 return None , None , None
@@ -920,30 +920,52 @@ def get_snippet(self, name_replace=None, drop_arg=-1):
920920 def get_desc (self ):
921921 return "SUBROUTINE"
922922
923- def get_hover (self , long = False , include_doc = True , drop_arg = - 1 ):
923+ def get_hover (self , long = False , drop_arg = - 1 ):
924924 sub_sig , _ = self .get_snippet (drop_arg = drop_arg )
925925 keyword_list = get_keywords (self .keywords )
926926 keyword_list .append (f"{ self .get_desc ()} " )
927927 hover_array = [" " .join (keyword_list ) + sub_sig ]
928- hover_array = self .get_docs_full (hover_array , long , include_doc , drop_arg )
929- return "\n " .join (hover_array ), long
928+ hover_array , docs = self .get_docs_full (hover_array , long , drop_arg )
929+ return "\n " .join (hover_array ), " \n " . join ( docs ), long
930930
931931 def get_docs_full (
932- self , hover_array : list [str ], long = False , include_doc = True , drop_arg = - 1
933- ):
932+ self , hover_array : list [str ], long = False , drop_arg = - 1
933+ ) -> tuple [list [str ], list [str ]]:
934+ """Construct the full documentation with the code signature and the
935+ documentation string + the documentation of any arguments.
936+
937+ Parameters
938+ ----------
939+ hover_array : list[str]
940+ The list of strings to append the documentation to.
941+ long : bool, optional
942+ Whether or not to fetch the docs of the arguments, by default False
943+ drop_arg : int, optional
944+ Whether or not to drop certain arguments from the results, by default -1
945+
946+ Returns
947+ -------
948+ tuple[list[str], list[str]]
949+ Tuple containing the Fortran signature that should be in code blocks
950+ and the documentation string that should be in normal Markdown.
951+ """
952+ doc_strs : list [str ] = []
934953 doc_str = self .get_documentation ()
935- if include_doc and doc_str is not None :
936- hover_array [ 0 ] += " \n " + doc_str
954+ if doc_str is not None :
955+ doc_strs . append ( doc_str )
937956 if long :
957+ has_args = True
938958 for i , arg_obj in enumerate (self .arg_objs ):
939959 if arg_obj is None or i == drop_arg :
940960 continue
941- arg_doc , _ = arg_obj .get_hover (include_doc = False )
942- hover_array .append (f"{ arg_doc } :: { arg_obj .name } " )
943- doc_str = arg_obj .get_documentation ()
944- if include_doc and (doc_str is not None ):
945- hover_array += doc_str .splitlines ()
946- return hover_array
961+ arg , doc_str , _ = arg_obj .get_hover ()
962+ hover_array .append (arg )
963+ if doc_str : # If doc_str is not None or ""
964+ if has_args :
965+ doc_strs .append ("\n **Parameters:** " )
966+ has_args = False
967+ doc_strs .append (f"`{ arg_obj .name } ` { doc_str } " )
968+ return hover_array , doc_strs
947969
948970 def get_signature (self , drop_arg = - 1 ):
949971 arg_sigs = []
@@ -964,14 +986,15 @@ def get_signature(self, drop_arg=-1):
964986 call_sig , _ = self .get_snippet ()
965987 return call_sig , self .get_documentation (), arg_sigs
966988
989+ # TODO: fix this
967990 def get_interface_array (
968991 self , keywords : list [str ], signature : str , change_arg = - 1 , change_strings = None
969992 ):
970993 interface_array = [" " .join (keywords ) + signature ]
971994 for i , arg_obj in enumerate (self .arg_objs ):
972995 if arg_obj is None :
973996 return None
974- arg_doc , _ = arg_obj .get_hover (include_doc = False )
997+ arg_doc , docs , _ = arg_obj .get_hover ()
975998 if i == change_arg :
976999 i0 = arg_doc .lower ().find (change_strings [0 ].lower ())
9771000 if i0 >= 0 :
@@ -1087,8 +1110,8 @@ def is_callable(self):
10871110 return False
10881111
10891112 def get_hover (
1090- self , long : bool = False , include_doc : bool = True , drop_arg : int = - 1
1091- ) -> tuple [str , bool ]:
1113+ self , long : bool = False , drop_arg : int = - 1
1114+ ) -> tuple [str , str , bool ]:
10921115 """Construct the hover message for a FUNCTION.
10931116 Two forms are produced here the `long` i.e. the normal for hover requests
10941117
@@ -1107,8 +1130,6 @@ def get_hover(
11071130 ----------
11081131 long : bool, optional
11091132 toggle between long and short hover results, by default False
1110- include_doc : bool, optional
1111- if to include any documentation, by default True
11121133 drop_arg : int, optional
11131134 Ignore argument at position `drop_arg` in the argument list, by default -1
11141135
@@ -1124,17 +1145,21 @@ def get_hover(
11241145 keyword_list .append ("FUNCTION" )
11251146
11261147 hover_array = [f"{ ' ' .join (keyword_list )} { fun_sig } " ]
1127- hover_array = self .get_docs_full (hover_array , long , include_doc , drop_arg )
1148+ hover_array , docs = self .get_docs_full (hover_array , long , drop_arg )
11281149 # Only append the return value if using long form
11291150 if self .result_obj and long :
1130- arg_doc , _ = self .result_obj .get_hover (include_doc = False )
1131- hover_array .append (f"{ arg_doc } :: { self .result_obj .name } " )
1151+ # Parse the documentation from the result variable
1152+ arg_doc , doc_str , _ = self .result_obj .get_hover ()
1153+ if doc_str is not None :
1154+ docs .append (f"\n **Return:** \n `{ self .result_obj .name } `{ doc_str } " )
1155+ hover_array .append (arg_doc )
11321156 # intrinsic functions, where the return type is missing but can be inferred
11331157 elif self .result_type and long :
11341158 # prepend type to function signature
11351159 hover_array [0 ] = f"{ self .result_type } { hover_array [0 ]} "
1136- return "\n " .join (hover_array ), long
1160+ return "\n " .join (hover_array ), " \n " . join ( docs ), long
11371161
1162+ # TODO: fix this
11381163 def get_interface (self , name_replace = None , change_arg = - 1 , change_strings = None ):
11391164 fun_sig , _ = self .get_snippet (name_replace = name_replace )
11401165 fun_sig += f" RESULT({ self .result_name } )"
@@ -1149,7 +1174,7 @@ def get_interface(self, name_replace=None, change_arg=-1, change_strings=None):
11491174 keyword_list , fun_sig , change_arg , change_strings
11501175 )
11511176 if self .result_obj is not None :
1152- arg_doc , _ = self .result_obj .get_hover (include_doc = False )
1177+ arg_doc , docs , _ = self .result_obj .get_hover ()
11531178 interface_array .append (f"{ arg_doc } :: { self .result_obj .name } " )
11541179 name = self .name
11551180 if name_replace is not None :
@@ -1656,18 +1681,17 @@ def get_snippet(self, name_replace=None, drop_arg=-1):
16561681 # Normal variable
16571682 return None , None
16581683
1659- def get_hover (self , long = False , include_doc = True , drop_arg = - 1 ):
1684+ def get_hover (self , long = False , drop_arg = - 1 ) -> tuple [ str , str , bool ] :
16601685 doc_str = self .get_documentation ()
16611686 # In associated blocks we need to fetch the desc and keywords of the
16621687 # linked object
16631688 hover_str = ", " .join ([self .get_desc ()] + self .get_keywords ())
1664- # TODO: at this stage we can mae this lowercase
1665- # Add parameter value in the output
1689+ # If this is not a preprocessor variable, we can append the variable name
1690+ if not hover_str .startswith ("#" ):
1691+ hover_str += f" :: { self .name } "
16661692 if self .is_parameter () and self .param_val :
1667- hover_str += f" :: { self .name } = { self .param_val } "
1668- if include_doc and (doc_str is not None ):
1669- hover_str += "\n {}" .format ("\n " .join (doc_str .splitlines ()))
1670- return hover_str , True
1693+ hover_str += f" = { self .param_val } "
1694+ return hover_str , doc_str , True
16711695
16721696 def get_keywords (self ):
16731697 # TODO: if local keywords are set they should take precedence over link_obj
@@ -1803,45 +1827,34 @@ def get_documentation(self):
18031827 return self .link_obj .get_documentation ()
18041828 return self .doc_str
18051829
1806- def get_hover (self , long = False , include_doc = True , drop_arg = - 1 ):
1807- doc_str = self .get_documentation ()
1808- if long :
1809- if self .link_obj is None :
1810- sub_sig , _ = self .get_snippet ()
1811- hover_str = f"{ self .get_desc ()} { sub_sig } "
1812- if include_doc and (doc_str is not None ):
1813- hover_str += f"\n { doc_str } "
1814- else :
1815- link_hover , _ = self .link_obj .get_hover (
1816- long = True , include_doc = include_doc , drop_arg = self .drop_arg
1817- )
1818- hover_split = link_hover .splitlines ()
1819- call_sig = hover_split [0 ]
1820- paren_start = call_sig .rfind ("(" )
1821- link_name_len = len (self .link_obj .name )
1822- call_sig = (
1823- call_sig [: paren_start - link_name_len ]
1824- + self .name
1825- + call_sig [paren_start :]
1826- )
1827- hover_split = hover_split [1 :]
1828- if include_doc and (self .doc_str is not None ):
1829- # Replace linked docs with current object's docs
1830- if (len (hover_split ) > 0 ) and (hover_split [0 ].count ("!!" ) > 0 ):
1831- for (i , hover_line ) in enumerate (hover_split ):
1832- if hover_line .count ("!!" ) == 0 :
1833- hover_split = hover_split [i :]
1834- break
1835- else : # All lines are docs
1836- hover_split = []
1837- hover_split = [self .doc_str ] + hover_split
1838- hover_str = "\n " .join ([call_sig ] + hover_split )
1839- return hover_str , True
1840- else :
1830+ def get_hover (self , long = False , drop_arg = - 1 ) -> tuple [str , str , bool ]:
1831+ docs = self .get_documentation ()
1832+ if not long :
18411833 hover_str = ", " .join ([self .desc ] + get_keywords (self .keywords ))
1842- if include_doc and (doc_str is not None ):
1843- hover_str += f"\n { doc_str } "
1844- return hover_str , True
1834+ return hover_str , docs , True
1835+ # Long hover message
1836+ if self .link_obj is None :
1837+ sub_sig , _ = self .get_snippet ()
1838+ hover_str = f"{ self .get_desc ()} { sub_sig } "
1839+ else :
1840+ link_msg , link_docs , _ = self .link_obj .get_hover (
1841+ long = True , drop_arg = self .drop_arg
1842+ )
1843+ # Replace the name of the linked object with the name of this object
1844+ hover_str = link_msg .replace (self .link_obj .name , self .name , 1 )
1845+ if isinstance (link_docs , str ):
1846+ # Get just the docstring of the link, if any, no args
1847+ link_doc_top = self .link_obj .get_documentation ()
1848+ # Replace the linked objects topmost documentation with the
1849+ # documentation of the procedure pointer if one is present
1850+ if link_doc_top is not None :
1851+ docs = link_docs .replace (link_doc_top , docs , 1 )
1852+ # If no top docstring is present at the linked object but there
1853+ # are docstrings for the arguments, add them to the end of the
1854+ # documentation for this object
1855+ elif link_docs :
1856+ docs += " \n " + link_docs
1857+ return hover_str , docs , True
18451858
18461859 def get_signature (self , drop_arg = - 1 ):
18471860 if self .link_obj is not None :
0 commit comments