5656 (?:[+*/!~%<>=&^|\-:]+) # or operator name
5757 ) \s*
5858 (?:\((.*?)\))? # opt: arguments
59- (\s+(?:const\s)? (?:\w+?)| # or return intent
60- \s* : \s* (?:[^:]+?)| # or return type
61- \s+(?:const\s)? \w+\s* : \s* (?:[^:]+?) # or return intent and type
59+ (\s+(?:const\s)? (?:\w+?) # opt: return intent
60+ )?
61+ (\s*:\s*(?:[^:]+?) # opt: return type
62+ )?
63+ (\s+throws # opt: throws
6264 )?
6365 (\s+where\s+.* # Where clause
6466 )?
6567 $""" , re .VERBOSE )
6668
69+
70+ def match_chpl_sig_pattern (sig : str ):
71+ """
72+ Match a Chapel signature against the regex pattern defined in
73+ chpl_sig_pattern. chpl_sig_pattern cannot be used directly because we need
74+ to fix some things up
75+
76+ For example, `const throws` will be treated by the regex as a return
77+ intent, when really it is a `const` return intent and a `throws`. This
78+ function splits them apart
79+
80+ Additionally, this function cleans up the whitespace on the return type
81+ (and removes ':'!), return intent, and any captured throws to make testing
82+ more consistent.
83+ """
84+ sig_match = chpl_sig_pattern .match (sig )
85+ if not sig_match :
86+ return None
87+ (
88+ func_prefix ,
89+ name_prefix ,
90+ name ,
91+ arglist ,
92+ return_intent ,
93+ return_type ,
94+ throws ,
95+ where_clause ,
96+ ) = sig_match .groups ()
97+
98+ if return_type :
99+ return_type = return_type .strip ().removeprefix (':' ).lstrip ()
100+ if return_intent :
101+ return_intent = return_intent .strip ()
102+ if throws :
103+ throws = throws .strip ()
104+
105+ if return_intent and "throws" in return_intent :
106+ return_intent = return_intent .replace ("throws" , "" ).strip ()
107+ if not return_intent :
108+ return_intent = None
109+ throws = "throws"
110+
111+ return (
112+ func_prefix ,
113+ name_prefix ,
114+ name ,
115+ arglist ,
116+ return_intent ,
117+ return_type ,
118+ throws ,
119+ where_clause ,
120+ )
121+
122+
67123# regex for parsing attribute and data directives.
68124chpl_attr_sig_pattern = re .compile (
69125 r"""^ ((?:\w+\s+)*)? # optional: prefixes
@@ -210,25 +266,25 @@ def _pseudo_parse_arglist(signode, arglist):
210266 signode += paramlist
211267
212268 @staticmethod
213- def _handle_signature_suffix (signode , retann , anno , where_clause ):
269+ def _handle_signature_suffix (
270+ signode , return_intent , return_type , throws , anno , where_clause
271+ ):
214272 """
215273 handle the signature suffix items like return intent, return type,
216274 where clause, annotation, etc.
217275 """
218- if retann :
219- if ':' in retann :
220- retintent , _ , rettype = retann .partition (':' )
221- rettype = rettype .strip ()
222- else :
223- retintent , rettype = retann , None
224- retintent = retintent .strip ()
225- if retintent :
226- signode += addnodes .desc_sig_space (' ' , ' ' )
227- signode += addnodes .desc_annotation (' ' + retintent ,
228- ' ' + retintent )
229- if rettype :
230- signode += addnodes .desc_annotation (' : ' + rettype ,
231- ' : ' + rettype )
276+
277+ if return_intent :
278+ signode += addnodes .desc_sig_space (' ' , ' ' )
279+ signode += addnodes .desc_annotation (' ' + return_intent ,
280+ ' ' + return_intent )
281+ if return_type :
282+ signode += addnodes .desc_sig_space (' ' , ' ' )
283+ signode += addnodes .desc_annotation (' : ' + return_type ,
284+ ' : ' + return_type )
285+ if throws :
286+ signode += addnodes .desc_sig_space (' ' , ' ' )
287+ signode += addnodes .desc_annotation (' throws' , ' throws' )
232288 if anno :
233289 signode += addnodes .desc_annotation (' ' + anno , ' ' + anno )
234290 if where_clause :
@@ -253,11 +309,11 @@ def _get_proc_like_prefix(self, sig):
253309 """Return prefix text for function or method directive
254310 (and similar).
255311 """
256- sig_match = chpl_sig_pattern . match (sig )
312+ sig_match = match_chpl_sig_pattern (sig )
257313 if sig_match is None :
258314 return ChapelObject .get_signature_prefix (self , sig )
259315
260- prefixes , _ , _ , _ , _ , _ = sig_match . groups ()
316+ prefixes = sig_match [ 0 ]
261317 if prefixes :
262318 return prefixes .strip () + ' '
263319 elif self .objtype .startswith ('iter' ):
@@ -321,16 +377,26 @@ def handle_signature(self, sig, signode):
321377 sig_match = chpl_attr_sig_pattern .match (sig )
322378 if sig_match is None :
323379 raise ValueError ('Signature does not parse: {0}' .format (sig ))
324- func_prefix , name_prefix , name , retann = sig_match .groups ()
380+ func_prefix , name_prefix , name , return_type = sig_match .groups ()
381+ return_intent = None
382+ throws = None
325383 arglist = None
326384 where_clause = None
327385 else :
328- sig_match = chpl_sig_pattern . match (sig )
386+ sig_match = match_chpl_sig_pattern (sig )
329387 if sig_match is None :
330388 raise ValueError ('Signature does not parse: {0}' .format (sig ))
331389
332- func_prefix , name_prefix , name , arglist , retann , where_clause = \
333- sig_match .groups ()
390+ (
391+ func_prefix ,
392+ name_prefix ,
393+ name ,
394+ arglist ,
395+ return_intent ,
396+ return_type ,
397+ throws ,
398+ where_clause ,
399+ ) = sig_match
334400
335401 # check if where clause is valid
336402 if where_clause is not None and not self ._is_proc_like ():
@@ -386,11 +452,15 @@ def handle_signature(self, sig, signode):
386452 if self .needs_arglist () and arglist is not None :
387453 # for callables, add an empty parameter list
388454 signode += addnodes .desc_parameterlist ()
389- self ._handle_signature_suffix (signode , retann , anno , where_clause )
455+ self ._handle_signature_suffix (
456+ signode , return_intent , return_type , throws , anno , where_clause
457+ )
390458 return fullname , name_prefix
391459
392460 self ._pseudo_parse_arglist (signode , arglist )
393- self ._handle_signature_suffix (signode , retann , anno , where_clause )
461+ self ._handle_signature_suffix (
462+ signode , return_intent , return_type , throws , anno , where_clause
463+ )
394464
395465 return fullname , name_prefix
396466
0 commit comments