buildframework/helium/external/python/lib/common/Sphinx-0.5.1-py2.5.egg/sphinx/directives/desc.py
changeset 179 d8ac696cc51f
equal deleted inserted replaced
1:be27ed110b50 179:d8ac696cc51f
       
     1 # -*- coding: utf-8 -*-
       
     2 """
       
     3     sphinx.directives.desc
       
     4     ~~~~~~~~~~~~~~~~~~~~~~
       
     5 
       
     6     :copyright: 2007-2008 by Georg Brandl.
       
     7     :license: BSD.
       
     8 """
       
     9 
       
    10 import re
       
    11 import string
       
    12 
       
    13 from docutils import nodes
       
    14 from docutils.parsers.rst import directives
       
    15 
       
    16 from sphinx import addnodes
       
    17 from sphinx.util import ws_re
       
    18 
       
    19 
       
    20 # ------ information units ---------------------------------------------------------
       
    21 
       
    22 def desc_index_text(desctype, module, name, add_modules):
       
    23     if desctype == 'function':
       
    24         if not module:
       
    25             return _('%s() (built-in function)') % name
       
    26         return _('%s() (in module %s)') % (name, module)
       
    27     elif desctype == 'data':
       
    28         if not module:
       
    29             return _('%s (built-in variable)') % name
       
    30         return _('%s (in module %s)') % (name, module)
       
    31     elif desctype == 'class':
       
    32         if not module:
       
    33             return _('%s (built-in class)') % name
       
    34         return _('%s (class in %s)') % (name, module)
       
    35     elif desctype == 'exception':
       
    36         return name
       
    37     elif desctype == 'method':
       
    38         try:
       
    39             clsname, methname = name.rsplit('.', 1)
       
    40         except ValueError:
       
    41             if module:
       
    42                 return _('%s() (in module %s)') % (name, module)
       
    43             else:
       
    44                 return '%s()' % name
       
    45         if module and add_modules:
       
    46             return _('%s() (%s.%s method)') % (methname, module, clsname)
       
    47         else:
       
    48             return _('%s() (%s method)') % (methname, clsname)
       
    49     elif desctype == 'staticmethod':
       
    50         try:
       
    51             clsname, methname = name.rsplit('.', 1)
       
    52         except ValueError:
       
    53             if module:
       
    54                 return _('%s() (in module %s)') % (name, module)
       
    55             else:
       
    56                 return '%s()' % name
       
    57         if module and add_modules:
       
    58             return _('%s() (%s.%s static method)') % (methname, module, clsname)
       
    59         else:
       
    60             return _('%s() (%s static method)') % (methname, clsname)
       
    61     elif desctype == 'attribute':
       
    62         try:
       
    63             clsname, attrname = name.rsplit('.', 1)
       
    64         except ValueError:
       
    65             if module:
       
    66                 return _('%s (in module %s)') % (name, module)
       
    67             else:
       
    68                 return name
       
    69         if module and add_modules:
       
    70             return _('%s (%s.%s attribute)') % (attrname, module, clsname)
       
    71         else:
       
    72             return _('%s (%s attribute)') % (attrname, clsname)
       
    73     elif desctype == 'cfunction':
       
    74         return _('%s (C function)') % name
       
    75     elif desctype == 'cmember':
       
    76         return _('%s (C member)') % name
       
    77     elif desctype == 'cmacro':
       
    78         return _('%s (C macro)') % name
       
    79     elif desctype == 'ctype':
       
    80         return _('%s (C type)') % name
       
    81     elif desctype == 'cvar':
       
    82         return _('%s (C variable)') % name
       
    83     else:
       
    84         raise ValueError('unhandled descenv: %s' % desctype)
       
    85 
       
    86 
       
    87 # ------ make field lists (like :param foo:) in desc bodies prettier
       
    88 
       
    89 _ = lambda x: x  # make gettext extraction in constants possible
       
    90 
       
    91 doc_fields_with_arg = {
       
    92     'param': '%param',
       
    93     'parameter': '%param',
       
    94     'arg': '%param',
       
    95     'argument': '%param',
       
    96     'keyword': '%param',
       
    97     'kwarg': '%param',
       
    98     'kwparam': '%param',
       
    99     'type': '%type',
       
   100     'raises': _('Raises'),
       
   101     'raise': 'Raises',
       
   102     'exception': 'Raises',
       
   103     'except': 'Raises',
       
   104     'var': _('Variable'),
       
   105     'ivar': 'Variable',
       
   106     'cvar': 'Variable',
       
   107     'returns': _('Returns'),
       
   108     'return': 'Returns',
       
   109 }
       
   110 
       
   111 doc_fields_with_linked_arg = ('raises', 'raise', 'exception', 'except')
       
   112 
       
   113 doc_fields_without_arg = {
       
   114     'returns': 'Returns',
       
   115     'return': 'Returns',
       
   116     'rtype': _('Return type'),
       
   117 }
       
   118 
       
   119 del _
       
   120 
       
   121 
       
   122 def _is_only_paragraph(node):
       
   123     # determine if the node only contains one paragraph (and system messages)
       
   124     if len(node) == 0:
       
   125         return False
       
   126     elif len(node) > 1:
       
   127         for subnode in node[1:]:
       
   128             if not isinstance(subnode, nodes.system_message):
       
   129                 return False
       
   130     if isinstance(node[0], nodes.paragraph):
       
   131         return True
       
   132     return False
       
   133 
       
   134 
       
   135 def handle_doc_fields(node, env):
       
   136     # don't traverse, only handle field lists that are immediate children
       
   137     for child in node.children:
       
   138         if not isinstance(child, nodes.field_list):
       
   139             continue
       
   140         params = None
       
   141         param_nodes = {}
       
   142         param_types = {}
       
   143         new_list = nodes.field_list()
       
   144         for field in child:
       
   145             fname, fbody = field
       
   146             try:
       
   147                 typ, obj = fname.astext().split(None, 1)
       
   148                 typdesc = _(doc_fields_with_arg[typ])
       
   149                 if _is_only_paragraph(fbody):
       
   150                     children = fbody.children[0].children
       
   151                 else:
       
   152                     children = fbody.children
       
   153                 if typdesc == '%param':
       
   154                     if not params:
       
   155                         pfield = nodes.field()
       
   156                         pfield += nodes.field_name('', _('Parameters'))
       
   157                         pfield += nodes.field_body()
       
   158                         params = nodes.bullet_list()
       
   159                         pfield[1] += params
       
   160                         new_list += pfield
       
   161                     dlitem = nodes.list_item()
       
   162                     dlpar = nodes.paragraph()
       
   163                     dlpar += nodes.emphasis(obj, obj)
       
   164                     dlpar += nodes.Text(' -- ', ' -- ')
       
   165                     dlpar += children
       
   166                     param_nodes[obj] = dlpar
       
   167                     dlitem += dlpar
       
   168                     params += dlitem
       
   169                 elif typdesc == '%type':
       
   170                     typenodes = fbody.children
       
   171                     if _is_only_paragraph(fbody):
       
   172                         typenodes = [nodes.Text(' (')] + \
       
   173                                     typenodes[0].children + [nodes.Text(')')]
       
   174                     param_types[obj] = typenodes
       
   175                 else:
       
   176                     fieldname = typdesc + ' '
       
   177                     nfield = nodes.field()
       
   178                     nfieldname = nodes.field_name(fieldname, fieldname)
       
   179                     nfield += nfieldname
       
   180                     node = nfieldname
       
   181                     if typ in doc_fields_with_linked_arg:
       
   182                         node = addnodes.pending_xref(obj, reftype='obj',
       
   183                                                      refcaption=False,
       
   184                                                      reftarget=obj,
       
   185                                                      modname=env.currmodule,
       
   186                                                      classname=env.currclass)
       
   187                         nfieldname += node
       
   188                     node += nodes.Text(obj, obj)
       
   189                     nfield += nodes.field_body()
       
   190                     nfield[1] += fbody.children
       
   191                     new_list += nfield
       
   192             except (KeyError, ValueError):
       
   193                 fnametext = fname.astext()
       
   194                 try:
       
   195                     typ = _(doc_fields_without_arg[fnametext])
       
   196                 except KeyError:
       
   197                     # at least capitalize the field name
       
   198                     typ = fnametext.capitalize()
       
   199                 fname[0] = nodes.Text(typ)
       
   200                 new_list += field
       
   201         for param, type in param_types.iteritems():
       
   202             if param in param_nodes:
       
   203                 param_nodes[param][1:1] = type
       
   204         child.replace_self(new_list)
       
   205 
       
   206 
       
   207 # ------ functions to parse a Python or C signature and create desc_* nodes.
       
   208 
       
   209 py_sig_re = re.compile(
       
   210     r'''^ ([\w.]*\.)?            # class name(s)
       
   211           (\w+)  \s*             # thing name
       
   212           (?: \((.*)\)           # optional arguments
       
   213           (\s* -> \s* .*)? )? $  # optional return annotation
       
   214           ''', re.VERBOSE)
       
   215 
       
   216 py_paramlist_re = re.compile(r'([\[\],])')  # split at '[', ']' and ','
       
   217 
       
   218 def parse_py_signature(signode, sig, desctype, module, env):
       
   219     """
       
   220     Transform a python signature into RST nodes.
       
   221     Return (fully qualified name of the thing, classname if any).
       
   222 
       
   223     If inside a class, the current class name is handled intelligently:
       
   224     * it is stripped from the displayed name if present
       
   225     * it is added to the full name (return value) if not present
       
   226     """
       
   227     m = py_sig_re.match(sig)
       
   228     if m is None:
       
   229         raise ValueError
       
   230     classname, name, arglist, retann = m.groups()
       
   231 
       
   232     if retann:
       
   233         retann = u' \N{RIGHTWARDS ARROW} ' + retann.strip()[2:]
       
   234 
       
   235     if env.currclass:
       
   236         add_module = False
       
   237         if classname and classname.startswith(env.currclass):
       
   238             fullname = classname + name
       
   239             # class name is given again in the signature
       
   240             classname = classname[len(env.currclass):].lstrip('.')
       
   241         elif classname:
       
   242             # class name is given in the signature, but different
       
   243             # (shouldn't happen)
       
   244             fullname = env.currclass + '.' + classname + name
       
   245         else:
       
   246             # class name is not given in the signature
       
   247             fullname = env.currclass + '.' + name
       
   248     else:
       
   249         add_module = True
       
   250         fullname = classname and classname + name or name
       
   251 
       
   252     if desctype == 'staticmethod':
       
   253         signode += addnodes.desc_annotation('static ', 'static ')
       
   254 
       
   255     if classname:
       
   256         signode += addnodes.desc_addname(classname, classname)
       
   257     # exceptions are a special case, since they are documented in the
       
   258     # 'exceptions' module.
       
   259     elif add_module and env.config.add_module_names and \
       
   260            module and module != 'exceptions':
       
   261         nodetext = module + '.'
       
   262         signode += addnodes.desc_addname(nodetext, nodetext)
       
   263 
       
   264     signode += addnodes.desc_name(name, name)
       
   265     if not arglist:
       
   266         if desctype in ('function', 'method', 'staticmethod'):
       
   267             # for callables, add an empty parameter list
       
   268             signode += addnodes.desc_parameterlist()
       
   269         if retann:
       
   270             signode += addnodes.desc_type(retann, retann)
       
   271         return fullname, classname
       
   272     signode += addnodes.desc_parameterlist()
       
   273 
       
   274     stack = [signode[-1]]
       
   275     for token in py_paramlist_re.split(arglist):
       
   276         if token == '[':
       
   277             opt = addnodes.desc_optional()
       
   278             stack[-1] += opt
       
   279             stack.append(opt)
       
   280         elif token == ']':
       
   281             try:
       
   282                 stack.pop()
       
   283             except IndexError:
       
   284                 raise ValueError
       
   285         elif not token or token == ',' or token.isspace():
       
   286             pass
       
   287         else:
       
   288             token = token.strip()
       
   289             stack[-1] += addnodes.desc_parameter(token, token)
       
   290     if len(stack) != 1:
       
   291         raise ValueError
       
   292     if retann:
       
   293         signode += addnodes.desc_type(retann, retann)
       
   294     return fullname, classname
       
   295 
       
   296 
       
   297 c_sig_re = re.compile(
       
   298     r'''^([^(]*?)          # return type
       
   299         ([\w:]+)  \s*      # thing name (colon allowed for C++ class names)
       
   300         (?: \((.*)\) )?    # optionally arguments
       
   301         (\s+const)? $      # const specifier
       
   302     ''', re.VERBOSE)
       
   303 c_funcptr_sig_re = re.compile(
       
   304     r'''^([^(]+?)          # return type
       
   305         (\( [^()]+ \)) \s* # name in parentheses
       
   306         \( (.*) \)         # arguments
       
   307         (\s+const)? $      # const specifier
       
   308     ''', re.VERBOSE)
       
   309 c_funcptr_name_re = re.compile(r'^\(\s*\*\s*(.*?)\s*\)$')
       
   310 
       
   311 # RE to split at word boundaries
       
   312 wsplit_re = re.compile(r'(\W+)')
       
   313 
       
   314 # These C types aren't described in the reference, so don't try to create
       
   315 # a cross-reference to them
       
   316 stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct'))
       
   317 
       
   318 def parse_c_type(node, ctype):
       
   319     # add cross-ref nodes for all words
       
   320     for part in filter(None, wsplit_re.split(ctype)):
       
   321         tnode = nodes.Text(part, part)
       
   322         if part[0] in string.letters+'_' and part not in stopwords:
       
   323             pnode = addnodes.pending_xref(
       
   324                 '', reftype='ctype', reftarget=part, modname=None, classname=None)
       
   325             pnode += tnode
       
   326             node += pnode
       
   327         else:
       
   328             node += tnode
       
   329 
       
   330 def parse_c_signature(signode, sig, desctype):
       
   331     """Transform a C (or C++) signature into RST nodes."""
       
   332     # first try the function pointer signature regex, it's more specific
       
   333     m = c_funcptr_sig_re.match(sig)
       
   334     if m is None:
       
   335         m = c_sig_re.match(sig)
       
   336     if m is None:
       
   337         raise ValueError('no match')
       
   338     rettype, name, arglist, const = m.groups()
       
   339 
       
   340     signode += addnodes.desc_type('', '')
       
   341     parse_c_type(signode[-1], rettype)
       
   342     try:
       
   343         classname, funcname = name.split('::', 1)
       
   344         classname += '::'
       
   345         signode += addnodes.desc_addname(classname, classname)
       
   346         signode += addnodes.desc_name(funcname, funcname)
       
   347         # name (the full name) is still both parts
       
   348     except ValueError:
       
   349         signode += addnodes.desc_name(name, name)
       
   350     # clean up parentheses from canonical name
       
   351     m = c_funcptr_name_re.match(name)
       
   352     if m:
       
   353         name = m.group(1)
       
   354     if not arglist:
       
   355         if desctype == 'cfunction':
       
   356             # for functions, add an empty parameter list
       
   357             signode += addnodes.desc_parameterlist()
       
   358         return name
       
   359 
       
   360     paramlist = addnodes.desc_parameterlist()
       
   361     arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
       
   362     # this messes up function pointer types, but not too badly ;)
       
   363     args = arglist.split(',')
       
   364     for arg in args:
       
   365         arg = arg.strip()
       
   366         param = addnodes.desc_parameter('', '', noemph=True)
       
   367         try:
       
   368             ctype, argname = arg.rsplit(' ', 1)
       
   369         except ValueError:
       
   370             # no argument name given, only the type
       
   371             parse_c_type(param, arg)
       
   372         else:
       
   373             parse_c_type(param, ctype)
       
   374             param += nodes.emphasis(' '+argname, ' '+argname)
       
   375         paramlist += param
       
   376     signode += paramlist
       
   377     if const:
       
   378         signode += addnodes.desc_addname(const, const)
       
   379     return name
       
   380 
       
   381 
       
   382 option_desc_re = re.compile(
       
   383     r'((?:/|-|--)[-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)')
       
   384 
       
   385 def parse_option_desc(signode, sig):
       
   386     """Transform an option description into RST nodes."""
       
   387     count = 0
       
   388     firstname = ''
       
   389     for m in option_desc_re.finditer(sig):
       
   390         optname, args = m.groups()
       
   391         if count:
       
   392             signode += addnodes.desc_addname(', ', ', ')
       
   393         signode += addnodes.desc_name(optname, optname)
       
   394         signode += addnodes.desc_addname(args, args)
       
   395         if not count:
       
   396             firstname = optname
       
   397         count += 1
       
   398     if not firstname:
       
   399         raise ValueError
       
   400     return firstname
       
   401 
       
   402 
       
   403 strip_backslash_re = re.compile(r'\\(?=[^\\])')
       
   404 
       
   405 def desc_directive(desctype, arguments, options, content, lineno,
       
   406                    content_offset, block_text, state, state_machine):
       
   407     env = state.document.settings.env
       
   408     inode = addnodes.index(entries=[])
       
   409     node = addnodes.desc()
       
   410     node['desctype'] = desctype
       
   411 
       
   412     noindex = ('noindex' in options)
       
   413     node['noindex'] = noindex
       
   414     # remove backslashes to support (dummy) escapes; helps Vim's highlighting
       
   415     signatures = map(lambda s: strip_backslash_re.sub('', s.strip()),
       
   416                      arguments[0].split('\n'))
       
   417     names = []
       
   418     clsname = None
       
   419     module = options.get('module', env.currmodule)
       
   420     for i, sig in enumerate(signatures):
       
   421         # add a signature node for each signature in the current unit
       
   422         # and add a reference target for it
       
   423         sig = sig.strip()
       
   424         signode = addnodes.desc_signature(sig, '')
       
   425         signode['first'] = False
       
   426         node.append(signode)
       
   427         try:
       
   428             if desctype in ('function', 'data', 'class', 'exception',
       
   429                             'method', 'staticmethod', 'attribute'):
       
   430                 name, clsname = parse_py_signature(signode, sig, desctype, module, env)
       
   431             elif desctype in ('cfunction', 'cmember', 'cmacro', 'ctype', 'cvar'):
       
   432                 name = parse_c_signature(signode, sig, desctype)
       
   433             elif desctype == 'cmdoption':
       
   434                 optname = parse_option_desc(signode, sig)
       
   435                 if not noindex:
       
   436                     targetname = optname.replace('/', '-')
       
   437                     if env.currprogram:
       
   438                         targetname = '-' + env.currprogram + targetname
       
   439                     targetname = 'cmdoption' + targetname
       
   440                     signode['ids'].append(targetname)
       
   441                     state.document.note_explicit_target(signode)
       
   442                     inode['entries'].append(
       
   443                         ('pair', _('%scommand line option; %s') %
       
   444                          ((env.currprogram and env.currprogram + ' ' or ''), sig),
       
   445                          targetname, targetname))
       
   446                     env.note_progoption(optname, targetname)
       
   447                 continue
       
   448             elif desctype == 'describe':
       
   449                 signode.clear()
       
   450                 signode += addnodes.desc_name(sig, sig)
       
   451                 continue
       
   452             else:
       
   453                 # another registered generic x-ref directive
       
   454                 rolename, indextemplate, parse_node = additional_xref_types[desctype]
       
   455                 if parse_node:
       
   456                     fullname = parse_node(env, sig, signode)
       
   457                 else:
       
   458                     signode.clear()
       
   459                     signode += addnodes.desc_name(sig, sig)
       
   460                     # normalize whitespace like xfileref_role does
       
   461                     fullname = ws_re.sub('', sig)
       
   462                 if not noindex:
       
   463                     targetname = '%s-%s' % (rolename, fullname)
       
   464                     signode['ids'].append(targetname)
       
   465                     state.document.note_explicit_target(signode)
       
   466                     if indextemplate:
       
   467                         indexentry = _(indextemplate) % (fullname,)
       
   468                         indextype = 'single'
       
   469                         colon = indexentry.find(':')
       
   470                         if colon != -1:
       
   471                             indextype = indexentry[:colon].strip()
       
   472                             indexentry = indexentry[colon+1:].strip()
       
   473                         inode['entries'].append((indextype, indexentry,
       
   474                                                  targetname, targetname))
       
   475                     env.note_reftarget(rolename, fullname, targetname)
       
   476                 # don't use object indexing below
       
   477                 continue
       
   478         except ValueError, err:
       
   479             # signature parsing failed
       
   480             signode.clear()
       
   481             signode += addnodes.desc_name(sig, sig)
       
   482             continue             # we don't want an index entry here
       
   483         # only add target and index entry if this is the first description of the
       
   484         # function name in this desc block
       
   485         if not noindex and name not in names:
       
   486             fullname = (module and module + '.' or '') + name
       
   487             # note target
       
   488             if fullname not in state.document.ids:
       
   489                 signode['names'].append(fullname)
       
   490                 signode['ids'].append(fullname)
       
   491                 signode['first'] = (not names)
       
   492                 state.document.note_explicit_target(signode)
       
   493                 env.note_descref(fullname, desctype, lineno)
       
   494             names.append(name)
       
   495 
       
   496             indextext = desc_index_text(desctype, module, name,
       
   497                                         env.config.add_module_names)
       
   498             inode['entries'].append(('single', indextext, fullname, fullname))
       
   499 
       
   500     subnode = addnodes.desc_content()
       
   501     # needed for automatic qualification of members
       
   502     clsname_set = False
       
   503     if desctype in ('class', 'exception') and names:
       
   504         env.currclass = names[0]
       
   505         clsname_set = True
       
   506     elif desctype in ('method', 'staticmethod', 'attribute') and \
       
   507              clsname and not env.currclass:
       
   508         env.currclass = clsname.strip('.')
       
   509         clsname_set = True
       
   510     # needed for association of version{added,changed} directives
       
   511     if names:
       
   512         env.currdesc = names[0]
       
   513     state.nested_parse(content, content_offset, subnode)
       
   514     handle_doc_fields(subnode, env)
       
   515     if clsname_set:
       
   516         env.currclass = None
       
   517     env.currdesc = None
       
   518     node.append(subnode)
       
   519     return [inode, node]
       
   520 
       
   521 desc_directive.content = 1
       
   522 desc_directive.arguments = (1, 0, 1)
       
   523 desc_directive.options = {'noindex': directives.flag,
       
   524                           'module': directives.unchanged}
       
   525 
       
   526 desctypes = [
       
   527     # the Python ones
       
   528     'function',
       
   529     'data',
       
   530     'class',
       
   531     'method',
       
   532     'staticmethod',
       
   533     'attribute',
       
   534     'exception',
       
   535     # the C ones
       
   536     'cfunction',
       
   537     'cmember',
       
   538     'cmacro',
       
   539     'ctype',
       
   540     'cvar',
       
   541     # for command line options
       
   542     'cmdoption',
       
   543     # the generic one
       
   544     'describe',
       
   545     'envvar',
       
   546 ]
       
   547 
       
   548 for _name in desctypes:
       
   549     directives.register_directive(_name, desc_directive)
       
   550 
       
   551 _ = lambda x: x
       
   552 
       
   553 # Generic cross-reference types; they can be registered in the application;
       
   554 # the directives are either desc_directive or target_directive
       
   555 additional_xref_types = {
       
   556     # directive name: (role name, index text, function to parse the desc node)
       
   557     'envvar': ('envvar', _('environment variable; %s'), None),
       
   558 }
       
   559 
       
   560 del _
       
   561 
       
   562 
       
   563 # ------ target --------------------------------------------------------------------
       
   564 
       
   565 def target_directive(targettype, arguments, options, content, lineno,
       
   566                      content_offset, block_text, state, state_machine):
       
   567     """Generic target for user-defined cross-reference types."""
       
   568     env = state.document.settings.env
       
   569     rolename, indextemplate, foo = additional_xref_types[targettype]
       
   570     # normalize whitespace in fullname like xfileref_role does
       
   571     fullname = ws_re.sub('', arguments[0].strip())
       
   572     targetname = '%s-%s' % (rolename, fullname)
       
   573     node = nodes.target('', '', ids=[targetname])
       
   574     state.document.note_explicit_target(node)
       
   575     ret = [node]
       
   576     if indextemplate:
       
   577         indexentry = indextemplate % (fullname,)
       
   578         indextype = 'single'
       
   579         colon = indexentry.find(':')
       
   580         if colon != -1:
       
   581             indextype = indexentry[:colon].strip()
       
   582             indexentry = indexentry[colon+1:].strip()
       
   583         inode = addnodes.index(entries=[(indextype, indexentry, targetname, targetname)])
       
   584         ret.insert(0, inode)
       
   585     env.note_reftarget(rolename, fullname, targetname)
       
   586     return ret
       
   587 
       
   588 target_directive.content = 0
       
   589 target_directive.arguments = (1, 0, 1)
       
   590 
       
   591 # note, the target directive is not registered here, it is used by the application
       
   592 # when registering additional xref types