mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Allow a leading dot in x-reference roles, marking reversed search order for targets.
This commit is contained in:
@@ -116,7 +116,7 @@ py_paramlist_re = re.compile(r'([\[\],])') # split at '[', ']' and ','
|
||||
def parse_py_signature(signode, sig, desctype, env):
|
||||
"""
|
||||
Transform a python signature into RST nodes.
|
||||
Return the fully qualified name of the thing.
|
||||
Return (fully qualified name of the thing, classname if any).
|
||||
|
||||
If inside a class, the current class name is handled intelligently:
|
||||
* it is stripped from the displayed name if present
|
||||
@@ -153,7 +153,7 @@ def parse_py_signature(signode, sig, desctype, env):
|
||||
if desctype in ('function', 'method'):
|
||||
# for callables, add an empty parameter list
|
||||
signode += addnodes.desc_parameterlist()
|
||||
return fullname
|
||||
return fullname, classname
|
||||
signode += addnodes.desc_parameterlist()
|
||||
|
||||
stack = [signode[-1]]
|
||||
@@ -171,7 +171,7 @@ def parse_py_signature(signode, sig, desctype, env):
|
||||
token = token.strip()
|
||||
stack[-1] += addnodes.desc_parameter(token, token)
|
||||
if len(stack) != 1: raise ValueError
|
||||
return fullname
|
||||
return fullname, classname
|
||||
|
||||
|
||||
c_sig_re = re.compile(
|
||||
@@ -280,6 +280,7 @@ def desc_directive(desctype, arguments, options, content, lineno,
|
||||
noindex = ('noindex' in options)
|
||||
signatures = map(lambda s: s.strip(), arguments[0].split('\n'))
|
||||
names = []
|
||||
clsname = None
|
||||
for i, sig in enumerate(signatures):
|
||||
# add a signature node for each signature in the current unit
|
||||
# and add a reference target for it
|
||||
@@ -290,7 +291,7 @@ def desc_directive(desctype, arguments, options, content, lineno,
|
||||
try:
|
||||
if desctype in ('function', 'data', 'class', 'exception',
|
||||
'method', 'attribute'):
|
||||
name = parse_py_signature(signode, sig, desctype, env)
|
||||
name, clsname = parse_py_signature(signode, sig, desctype, env)
|
||||
elif desctype in ('cfunction', 'cmember', 'cmacro', 'ctype', 'cvar'):
|
||||
name = parse_c_signature(signode, sig, desctype)
|
||||
elif desctype == 'opcode':
|
||||
@@ -323,13 +324,18 @@ def desc_directive(desctype, arguments, options, content, lineno,
|
||||
if desctype == 'cfunction':
|
||||
add_refcount_annotation(env, subnode, name)
|
||||
# needed for automatic qualification of members
|
||||
clsname_set = False
|
||||
if desctype == 'class' and names:
|
||||
env.currclass = names[0]
|
||||
clsname_set = True
|
||||
elif desctype in ('method', 'attribute') and clsname and not env.currclass:
|
||||
env.currclass = clsname.strip('.')
|
||||
clsname_set = True
|
||||
# needed for association of version{added,changed} directives
|
||||
if names:
|
||||
env.currdesc = names[0]
|
||||
state.nested_parse(content, content_offset, subnode)
|
||||
if desctype == 'class':
|
||||
if clsname_set:
|
||||
env.currclass = None
|
||||
env.currdesc = None
|
||||
node.append(subnode)
|
||||
|
||||
@@ -621,7 +621,8 @@ class BuildEnvironment:
|
||||
builder.get_relative_uri(docfilename, filename) + anchor)
|
||||
newnode.append(contnode)
|
||||
else:
|
||||
name, desc = self.find_desc(modname, clsname, target, typ)
|
||||
searchorder = 1 if node.hasattr('refspecific') else 0
|
||||
name, desc = self.find_desc(modname, clsname, target, typ, searchorder)
|
||||
if not desc:
|
||||
newnode = contnode
|
||||
else:
|
||||
@@ -742,13 +743,16 @@ class BuildEnvironment:
|
||||
|
||||
# --------- QUERYING -------------------------------------------------------
|
||||
|
||||
def find_desc(self, modname, classname, name, type):
|
||||
def find_desc(self, modname, classname, name, type, searchorder=0):
|
||||
"""Find a description node matching "name", perhaps using
|
||||
the given module and/or classname."""
|
||||
# skip parens
|
||||
if name[-2:] == '()':
|
||||
name = name[:-2]
|
||||
|
||||
if not name:
|
||||
return None, None
|
||||
|
||||
# don't add module and class names for C things
|
||||
if type[0] == 'c' and type not in ('class', 'const'):
|
||||
# skip trailing star and whitespace
|
||||
@@ -757,22 +761,32 @@ class BuildEnvironment:
|
||||
return name, self.descrefs[name]
|
||||
return None, None
|
||||
|
||||
if name in self.descrefs:
|
||||
newname = name
|
||||
elif modname and modname + '.' + name in self.descrefs:
|
||||
newname = modname + '.' + name
|
||||
elif modname and classname and \
|
||||
modname + '.' + classname + '.' + name in self.descrefs:
|
||||
newname = modname + '.' + classname + '.' + name
|
||||
# special case: builtin exceptions have module "exceptions" set
|
||||
elif type == 'exc' and '.' not in name and \
|
||||
'exceptions.' + name in self.descrefs:
|
||||
newname = 'exceptions.' + name
|
||||
# special case: object methods
|
||||
elif type in ('func', 'meth') and '.' not in name and \
|
||||
'object.' + name in self.descrefs:
|
||||
newname = 'object.' + name
|
||||
newname = None
|
||||
if searchorder == 1:
|
||||
if modname and classname and \
|
||||
modname + '.' + classname + '.' + name in self.descrefs:
|
||||
newname = modname + '.' + classname + '.' + name
|
||||
elif modname and modname + '.' + name in self.descrefs:
|
||||
newname = modname + '.' + name
|
||||
elif name in self.descrefs:
|
||||
newname = name
|
||||
else:
|
||||
if name in self.descrefs:
|
||||
newname = name
|
||||
elif modname and modname + '.' + name in self.descrefs:
|
||||
newname = modname + '.' + name
|
||||
elif modname and classname and \
|
||||
modname + '.' + classname + '.' + name in self.descrefs:
|
||||
newname = modname + '.' + classname + '.' + name
|
||||
# special case: builtin exceptions have module "exceptions" set
|
||||
elif type == 'exc' and '.' not in name and \
|
||||
'exceptions.' + name in self.descrefs:
|
||||
newname = 'exceptions.' + name
|
||||
# special case: object methods
|
||||
elif type in ('func', 'meth') and '.' not in name and \
|
||||
'object.' + name in self.descrefs:
|
||||
newname = 'object.' + name
|
||||
if newname is None:
|
||||
return None, None
|
||||
return newname, self.descrefs[newname]
|
||||
|
||||
|
||||
@@ -100,6 +100,12 @@ def xfileref_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||
text += '()'
|
||||
pnode = addnodes.pending_xref(rawtext)
|
||||
pnode['reftype'] = typ
|
||||
# if the first character is a dot, search more specific namespaces first
|
||||
# else search builtins first
|
||||
if text[0:1] == '.' and \
|
||||
typ in ('data', 'exc', 'func', 'class', 'const', 'attr', 'meth'):
|
||||
text = text[1:]
|
||||
pnode['refspecific'] = True
|
||||
pnode['reftarget'] = ws_re.sub('', text)
|
||||
pnode['modname'] = env.currmodule
|
||||
pnode['classname'] = env.currclass
|
||||
|
||||
Reference in New Issue
Block a user