@@ -165,9 +165,13 @@ def find_in_scope(
165165 obj_tree : dict ,
166166 interface : bool = False ,
167167 local_only : bool = False ,
168+ var_line_number : int = None ,
168169):
169170 def check_scope (
170- local_scope : fortran_scope , var_name_lower : str , filter_public : bool = False
171+ local_scope : fortran_scope ,
172+ var_name_lower : str ,
173+ filter_public : bool = False ,
174+ var_line_number : int = None ,
171175 ):
172176 for child in local_scope .get_children ():
173177 if child .name .startswith ("#GEN_INT" ):
@@ -178,6 +182,19 @@ def check_scope(
178182 if (child .vis < 0 ) or ((local_scope .def_vis < 0 ) and (child .vis <= 0 )):
179183 continue
180184 if child .name .lower () == var_name_lower :
185+ # For functions with an implicit result() variable the name
186+ # of the function is used. If we are hovering over the function
187+ # definition, we do not want the implicit result() to be returned.
188+ # If scope is from a function and child's name is same as functions name
189+ # and start of scope i.e. function definition is equal to the request ln
190+ # then we are need to skip this child
191+ if (
192+ isinstance (local_scope , fortran_function )
193+ and local_scope .name .lower () == child .name .lower ()
194+ and var_line_number in (local_scope .sline , local_scope .eline )
195+ ):
196+ return None
197+
181198 return child
182199 return None
183200
@@ -186,7 +203,7 @@ def check_scope(
186203 # Check local scope
187204 if scope is None :
188205 return None
189- tmp_var = check_scope (scope , var_name_lower )
206+ tmp_var = check_scope (scope , var_name_lower , var_line_number = var_line_number )
190207 if local_only or (tmp_var is not None ):
191208 return tmp_var
192209 # Check INCLUDE statements
@@ -959,7 +976,7 @@ def get_hover(self, long=False, include_doc=True, drop_arg=-1):
959976 keyword_list = get_keywords (self .keywords )
960977 keyword_list .append (f"{ self .get_desc ()} " )
961978 hover_array = [" " .join (keyword_list ) + sub_sig ]
962- self .get_docs_full (hover_array , long , include_doc , drop_arg )
979+ hover_array = self .get_docs_full (hover_array , long , include_doc , drop_arg )
963980 return "\n " .join (hover_array ), long
964981
965982 def get_docs_full (
@@ -977,6 +994,7 @@ def get_docs_full(
977994 doc_str = arg_obj .get_documentation ()
978995 if include_doc and (doc_str is not None ):
979996 hover_array += doc_str .splitlines ()
997+ return hover_array
980998
981999 def get_signature (self , drop_arg = - 1 ):
9821000 arg_sigs = []
@@ -1070,8 +1088,8 @@ def __init__(
10701088 args : str = "" ,
10711089 mod_flag : bool = False ,
10721090 keywords : list = None ,
1073- return_type = None ,
1074- result_var = None ,
1091+ result_type : str = None ,
1092+ result_name : str = None ,
10751093 ):
10761094 super ().__init__ (file_ast , line_number , name , args , mod_flag , keywords )
10771095 self .args : str = args .replace (" " , "" ).lower ()
@@ -1080,65 +1098,108 @@ def __init__(
10801098 self .in_children : list = []
10811099 self .missing_args : list = []
10821100 self .mod_scope : bool = mod_flag
1083- self .result_var = result_var
1084- self .result_obj = None
1085- self .return_type = None
1086- if return_type is not None :
1087- self .return_type = return_type [0 ]
1101+ self .result_name : str = result_name
1102+ self .result_type : str = result_type
1103+ self .result_obj : fortran_var = None
1104+ # Set the implicit result() name to be the function name
1105+ if self .result_name is None :
1106+ self .result_name = self .name
10881107
10891108 def copy_interface (self , copy_source : fortran_function ):
10901109 # Call the parent class method
10911110 child_names = super ().copy_interface (copy_source )
10921111 # Return specific options
1093- self .result_var = copy_source .result_var
1112+ self .result_name = copy_source .result_name
1113+ self .result_type = copy_source .result_type
10941114 self .result_obj = copy_source .result_obj
10951115 if copy_source .result_obj is not None :
10961116 if copy_source .result_obj .name .lower () not in child_names :
10971117 self .in_children .append (copy_source .result_obj )
10981118
10991119 def resolve_link (self , obj_tree ):
11001120 self .resolve_arg_link (obj_tree )
1101- if self .result_var is not None :
1102- result_var_lower = self .result_var .lower ()
1103- for child in self .children :
1104- if child .name .lower () == result_var_lower :
1105- self .result_obj = child
1121+ result_var_lower = self .result_name .lower ()
1122+ for child in self .children :
1123+ if child .name .lower () == result_var_lower :
1124+ self .result_obj = child
1125+ # Update result value and type
1126+ self .result_name = child .name
1127+ self .result_type = child .get_desc ()
11061128
11071129 def get_type (self , no_link = False ):
11081130 return FUNCTION_TYPE_ID
11091131
11101132 def get_desc (self ):
1111- if self .result_obj is not None :
1112- return self .result_obj .get_desc () + " FUNCTION"
1113- if self .return_type is not None :
1114- return self .return_type + " FUNCTION"
1133+ if self .result_type :
1134+ return self .result_type + " FUNCTION"
11151135 return "FUNCTION"
11161136
11171137 def is_callable (self ):
11181138 return False
11191139
1120- def get_hover (self , long = False , include_doc = True , drop_arg = - 1 ):
1140+ def get_hover (
1141+ self , long : bool = False , include_doc : bool = True , drop_arg : int = - 1
1142+ ) -> tuple [str , bool ]:
1143+ """Construct the hover message for a FUNCTION.
1144+ Two forms are produced here the `long` i.e. the normal for hover requests
1145+
1146+ ```
1147+ [MODIFIERS] FUNCTION NAME([ARGS]) RESULT(RESULT_VAR)
1148+ TYPE, [ARG_MODIFIERS] :: [ARGS]
1149+ TYPE, [RESULT_MODIFIERS] :: RESULT_VAR
1150+ ```
1151+
1152+ note: intrinsic functions will display slightly different,
1153+ `RESULT_VAR` and its `TYPE` might not always be present
1154+
1155+ short form, used when functions are arguments in functions and subroutines:
1156+
1157+ ```
1158+ FUNCTION NAME([ARGS]) :: ARG_LIST_NAME
1159+ ```
1160+
1161+ Parameters
1162+ ----------
1163+ long : bool, optional
1164+ toggle between long and short hover results, by default False
1165+ include_doc : bool, optional
1166+ if to include any documentation, by default True
1167+ drop_arg : int, optional
1168+ Ignore argument at position `drop_arg` in the argument list, by default -1
1169+
1170+ Returns
1171+ -------
1172+ tuple[str, bool]
1173+ String representative of the hover message and the `long` flag used
1174+ """
11211175 fun_sig , _ = self .get_snippet (drop_arg = drop_arg )
1122- fun_return = ""
1123- if self .result_obj is not None :
1124- fun_return , _ = self .result_obj .get_hover (include_doc = False )
1125- if self .return_type is not None :
1126- fun_return = self .return_type
1176+ # short hover messages do not include the result()
1177+ fun_sig += f" RESULT({ self .result_name } )" if long else ""
11271178 keyword_list = get_keywords (self .keywords )
11281179 keyword_list .append ("FUNCTION" )
1129- hover_array = [f"{ fun_return } { ' ' .join (keyword_list )} { fun_sig } " ]
1130- self .get_docs_full (hover_array , long , include_doc , drop_arg )
1180+
1181+ hover_array = [f"{ ' ' .join (keyword_list )} { fun_sig } " ]
1182+ hover_array = self .get_docs_full (hover_array , long , include_doc , drop_arg )
1183+ # Only append the return value if using long form
1184+ if self .result_obj and long :
1185+ arg_doc , _ = self .result_obj .get_hover (include_doc = False )
1186+ hover_array .append (f"{ arg_doc } :: { self .result_obj .name } " )
1187+ # intrinsic functions, where the return type is missing but can be inferred
1188+ elif self .result_type and long :
1189+ # prepend type to function signature
1190+ hover_array [0 ] = f"{ self .result_type } { hover_array [0 ]} "
11311191 return "\n " .join (hover_array ), long
11321192
11331193 def get_interface (self , name_replace = None , change_arg = - 1 , change_strings = None ):
11341194 fun_sig , _ = self .get_snippet (name_replace = name_replace )
1195+ fun_sig += f" RESULT({ self .result_name } )"
1196+ # XXX:
11351197 keyword_list = []
1136- if self .return_type is not None :
1137- keyword_list .append (self .return_type )
1138- if self .result_obj is not None :
1139- fun_sig += f" RESULT({ self .result_obj .name } )"
1198+ if self .result_type :
1199+ keyword_list .append (self .result_type )
11401200 keyword_list += get_keywords (self .keywords )
11411201 keyword_list .append ("FUNCTION " )
1202+
11421203 interface_array = self .get_interface_array (
11431204 keyword_list , fun_sig , change_arg , change_strings
11441205 )
@@ -1628,6 +1689,7 @@ def get_hover(self, long=False, include_doc=True, drop_arg=-1):
16281689 hover_str = ", " .join (
16291690 [self .desc ] + get_keywords (self .keywords , self .keyword_info )
16301691 )
1692+ # TODO: at this stage we can mae this lowercase
16311693 # Add parameter value in the output
16321694 if self .is_parameter () and self .param_val :
16331695 hover_str += f" :: { self .name } = { self .param_val } "
0 commit comments