From db8395f9e18cfc1f620d7c86befa98cae91079ba Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 13 Jul 2009 18:27:34 +0200 Subject: [PATCH] Add make_refnode() utility function. --- sphinx/domains.py | 69 +++++++++++++++++------------------------ sphinx/environment.py | 43 +++++++++---------------- sphinx/util/__init__.py | 15 +++++++++ 3 files changed, 58 insertions(+), 69 deletions(-) diff --git a/sphinx/domains.py b/sphinx/domains.py index fdf5a9d7c..f3389da1a 100644 --- a/sphinx/domains.py +++ b/sphinx/domains.py @@ -15,6 +15,7 @@ import re from sphinx import addnodes from sphinx.roles import XRefRole from sphinx.directives import DescDirective +from sphinx.util import make_refnode class Domain(object): @@ -50,7 +51,7 @@ class Domain(object): inliner, options, content) self._role_cache[name] = role_adapter return role_adapter - + def directive(self, name): """ Return a directive adapter class that always gives the registered @@ -384,8 +385,10 @@ class PythonDomain(Domain): } def find_desc(self, env, modname, classname, name, type, searchorder=0): - """Find a description node matching "name", perhaps using - the given module and/or classname.""" + """ + Find a Python object description for "name", perhaps using the given + module and/or classname. + """ # skip parens if name[-2:] == '()': name = name[:-2] @@ -393,14 +396,6 @@ class PythonDomain(Domain): 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 - name = name.rstrip(' *') - if name in env.descrefs and env.descrefs[name][1][0] == 'c': - return name, env.descrefs[name] - return None, None - newname = None if searchorder == 1: if modname and classname and \ @@ -432,28 +427,22 @@ class PythonDomain(Domain): def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): - - if typ == 'mod' or \ - typ == 'obj' and target in env.modules: + if (typ == 'mod' or + typ == 'obj' and target in env.modules): docname, synopsis, platform, deprecated = \ env.modules.get(target, ('','','', '')) if not docname: - newnode = builder.app.emit_firstresult( - 'missing-reference', env, node, contnode) - if not newnode: - newnode = contnode + return None elif docname == fromdocname: # don't link to self - newnode = contnode + return contnode else: - newnode = nodes.reference('', '') - newnode['refuri'] = builder.get_relative_uri( - fromdocname, docname) + '#module-' + target - newnode['reftitle'] = '%s%s%s' % ( - (platform and '(%s) ' % platform), - synopsis, (deprecated and ' (deprecated)' or '')) - newnode.append(contnode) - elif typ in env.descroles: + title = '%s%s%s' % ((platform and '(%s) ' % platform), + synopsis, + (deprecated and ' (deprecated)' or '')) + return make_refnode(builder, fromdocname, docname, + 'module-' + target, contnode, title) + else: # "descrefs" modname = node['modname'] clsname = node['classname'] @@ -461,20 +450,10 @@ class PythonDomain(Domain): name, desc = self.find_desc(env, modname, clsname, target, typ, searchorder) if not desc: - newnode = builder.app.emit_firstresult( - 'missing-reference', env, node, contnode) - if not newnode: - newnode = contnode + return None else: - newnode = nodes.reference('', '') - if desc[0] == fromdocname: - newnode['refid'] = name - else: - newnode['refuri'] = ( - builder.get_relative_uri(fromdocname, desc[0]) - + '#' + name) - newnode['reftitle'] = name - newnode.append(contnode) + return make_refnode(builder, fromdocname, desc[0], name, + contnode, name) @@ -620,6 +599,16 @@ class CDomain(Domain): 'type': XRefRole(), } + def resolve_xref(self, env, fromdocname, builder, + typ, target, node, contnode): + # strip pointer asterisk + target = target.rstrip(' *') + # XXX descrefs + if target not in env.descrefs: + return None + desc = env.descrefs[target] + return make_refnode(builder, fromdocname, desc[0], contnode, target) + # this contains all registered domains all_domains = { diff --git a/sphinx/environment.py b/sphinx/environment.py index 80bc77535..a5bf49ebb 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -43,7 +43,7 @@ from docutils.transforms.parts import ContentsFilter from sphinx import addnodes from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \ - docname_join, FilenameUniqDict, url_re + docname_join, FilenameUniqDict, url_re, make_refnode from sphinx.errors import SphinxError from sphinx.directives import additional_xref_types @@ -1199,10 +1199,6 @@ class BuildEnvironment: docname, refnode['refuri']) + refnode['anchorname'] return newnode - descroles = frozenset(('data', 'exc', 'func', 'class', 'const', - 'attr', 'obj', 'meth', 'cfunc', 'cmember', - 'cdata', 'ctype', 'cmacro')) - def resolve_references(self, doctree, fromdocname, builder): # XXX remove this reftarget_roles = set(('token', 'term', 'citation')) @@ -1218,7 +1214,7 @@ class BuildEnvironment: try: if node.has_key('refdomain'): - # let the domain resolve the reference + # let the domain try to resolve the reference try: domain = builder.app.domains[node['refdomain']] except KeyError: @@ -1290,13 +1286,8 @@ class BuildEnvironment: #self.warn(fromdocname, 'unknown keyword: %s' % target) newnode = contnode else: - newnode = nodes.reference('', '') - if docname == fromdocname: - newnode['refid'] = labelid - else: - newnode['refuri'] = builder.get_relative_uri( - fromdocname, docname) + '#' + labelid - newnode.append(contnode) + newnode = make_refnode(builder, fromdocname, docname, + labelid, contnode) elif typ == 'option': progname = node['refprogram'] docname, labelid = self.progoptions.get((progname, target), @@ -1304,13 +1295,8 @@ class BuildEnvironment: if not docname: newnode = contnode else: - newnode = nodes.reference('', '') - if docname == fromdocname: - newnode['refid'] = labelid - else: - newnode['refuri'] = builder.get_relative_uri( - fromdocname, docname) + '#' + labelid - newnode.append(contnode) + newnode = make_refnode(builder, fromdocname, docname, + labelid, contnode) elif typ in reftarget_roles: docname, labelid = self.reftargets.get((typ, target), ('', '')) @@ -1325,20 +1311,19 @@ class BuildEnvironment: node.line) newnode = contnode else: - newnode = nodes.reference('', '') - if docname == fromdocname: - newnode['refid'] = labelid - else: - newnode['refuri'] = builder.get_relative_uri( - fromdocname, docname, typ) + '#' + labelid - newnode.append(contnode) + newnode = make_refnode(builder, fromdocname, docname, + labelid, contnode) else: raise RuntimeError('unknown xfileref node encountered: %s' % node) + + # no new node found? try the missing-reference event + if newnode is None: + newnode = builder.app.emit_firstresult( + 'missing-reference', env, node, contnode) except NoUri: newnode = contnode - if newnode: - node.replace_self(newnode) + node.replace_self(newnode or contnode) for node in doctree.traverse(addnodes.only): try: diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 3465403df..2d59edfcd 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -435,6 +435,21 @@ def split_explicit_title(text): else: return False, text, text + +def make_refnode(builder, fromdocname, todocname, targetid, child, title=None): + """Shortcut to create a reference node.""" + node = nodes.reference('', '') + if fromdocname == todocname: + node['refid'] = targetid + else: + node['refuri'] = (builder.get_relative_uri(fromdocname, todocname) + + '#' + targetid) + if title: + node['reftitle'] = title + node.append(child) + return node + + # monkey-patch Node.traverse to get more speed # traverse() is called so many times during a build that it saves # on average 20-25% overall build time!