docs: def handle_signature(self, sig, signode):
          """Parse the signature *sig* into individual nodes and append them to the
          *signode*. If ValueError is raises, parsing is aborted and the whole
          *sig* string is put into a single desc_name node.
  
          The return value is the value that identifies the object. IOW, it is
          the identifier that will be used to reference this object, datum,
          attribute, proc, etc. It is a tuple of "fullname" (including module and
          class(es)) and the classes. See also :py:meth:`add_target_and_index`.
          """
          if self._is_attr_like():
              sig_match = chpl_attr_sig_pattern.match(sig)
              if sig_match is None:
                  raise ValueError('Signature does not parse: {0}'.format(sig))
              func_prefix, name_prefix, name, retann = sig_match.groups()
              arglist = None
          else:
              sig_match = chpl_sig_pattern.match(sig)
              if sig_match is None:
                  raise ValueError('Signature does not parse: {0}'.format(sig))
  
              func_prefix, name_prefix, name, arglist, retann = \
                  sig_match.groups()
  
          modname = self.options.get(
              'module', self.env.temp_data.get('chpl:module'))
          classname = self.env.temp_data.get('chpl:class')
  
          if classname:
              if name_prefix and name_prefix.startswith(classname):
                  fullname = name_prefix + name
                  # class name is given again in the signature
                  name_prefix = name_prefix[len(classname):].lstrip('.')
              elif name_prefix:
                  # class name is given in the signature, but different
                  # (shouldn't happen)
                  fullname = classname + '.' + name_prefix + name
              else:
                  # class name is not given in the signature
                  fullname = classname + '.' + name
          else:
              if name_prefix:
                  classname = name_prefix.rstrip('.')
                  fullname = name_prefix + name
              else:
                  classname = ''
                  fullname = name
  
          signode['module'] = modname
          signode['class'] = classname
          signode['fullname'] = fullname
  
          sig_prefix = self.get_signature_prefix(sig)
          if sig_prefix:
              signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
          # if func_prefix:
          #     signode += addnodes.desc_addname(func_prefix, func_prefix)
          if name_prefix:
              signode += addnodes.desc_addname(name_prefix, name_prefix)
  
          anno = self.options.get('annotation')
  
          signode += addnodes.desc_name(name, name)
  
          if not arglist:
              # If this needs an arglist, and parens were provided in the
              # signature, add a parameterlist. Chapel supports paren-less
              # functions and methods, which can act as computed properties. If
              # arglist is the empty string, the signature included parens. If
              # arglist is None, it did not include parens.
              if self.needs_arglist() and arglist is not None:
                  # for callables, add an empty parameter list
                  signode += addnodes.desc_parameterlist()
              if retann:
                  signode += addnodes.desc_type(retann, retann)
              if anno:
                  signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
              return fullname, name_prefix
  
          self._pseudo_parse_arglist(signode, arglist)
          if retann:
              signode += addnodes.desc_type(retann, retann)
          if anno:
              signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
          return fullname, name_prefix