Commits

Georg Brandl committed 65c3dc1

#572: Show warnings by default when reference labels cannot be found.

Comments (0)

Files changed (5)

 Release 1.0.7 (in development)
 ==============================
 
+* #572: Show warnings by default when reference labels cannot be
+  found.
+
 * #536: Include line number when complaining about missing reference
   targets in nitpicky mode.
 

sphinx/domains/__init__.py

     roles = {}
     #: a list of Index subclasses
     indices = []
+    #: role name -> a warning message if reference is missing
+    dangling_warnings = {}
 
     #: data value for a fresh environment
     initial_data = {}

sphinx/domains/std.py

         # links to tokens in grammar productions
         'token':   XRefRole(),
         # links to terms in glossary
-        'term':    XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
+        'term':    XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
+                            warn_dangling=True),
         # links to headings or arbitrary labels
-        'ref':     XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
+        'ref':     XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
+                            warn_dangling=True),
         # links to labels, without a different title
-        'keyword': XRefRole(),
+        'keyword': XRefRole(warn_dangling=True),
     }
 
     initial_data = {
         },
     }
 
+    dangling_warnings = {
+        'term': 'term not in glossary: %(target)s',
+        'ref':  'undefined label: %(target)s (if the link has no caption '
+                'the label must precede a section header)',
+        'keyword': 'unknown keyword: %(target)s',
+    }
+
     def clear_doc(self, docname):
         for key, (fn, _) in self.data['progoptions'].items():
             if fn == docname:
     def resolve_xref(self, env, fromdocname, builder,
                      typ, target, node, contnode):
         if typ == 'ref':
-            #refdoc = node.get('refdoc', fromdocname)
             if node['refexplicit']:
                 # reference to anonymous label; the reference uses
                 # the supplied link caption
                 docname, labelid = self.data['anonlabels'].get(target, ('',''))
                 sectname = node.astext()
-                # XXX warn somehow if not resolved by intersphinx
-                #if not docname:
-                #    env.warn(refdoc, 'undefined label: %s' %
-                #              target, node.line)
             else:
                 # reference to named label; the final node will
                 # contain the section name after the label
                 docname, labelid, sectname = self.data['labels'].get(target,
                                                                      ('','',''))
-                # XXX warn somehow if not resolved by intersphinx
-                #if not docname:
-                #    env.warn(refdoc,
-                #        'undefined label: %s' % target + ' -- if you '
-                #        'don\'t give a link caption the label must '
-                #        'precede a section header.', node.line)
             if not docname:
                 return None
             newnode = nodes.reference('', '', internal=True)
             # keywords are oddballs: they are referenced by named labels
             docname, labelid, _ = self.data['labels'].get(target, ('','',''))
             if not docname:
-                #env.warn(refdoc, 'unknown keyword: %s' % target)
                 return None
-            else:
-                return make_refnode(builder, fromdocname, docname,
-                                    labelid, contnode)
+            return make_refnode(builder, fromdocname, docname,
+                                labelid, contnode)
         elif typ == 'option':
             progname = node['refprogram']
             docname, labelid = self.data['progoptions'].get((progname, target),
                                                             ('', ''))
             if not docname:
                 return None
-            else:
-                return make_refnode(builder, fromdocname, docname,
-                                    labelid, contnode)
+            return make_refnode(builder, fromdocname, docname,
+                                labelid, contnode)
         else:
             objtypes = self.objtypes_for_role(typ) or []
             for objtype in objtypes:
             else:
                 docname, labelid = '', ''
             if not docname:
-                if typ == 'term':
-                    env.warn(node.get('refdoc', fromdocname),
-                             'term not in glossary: %s' % target, node.line)
                 return None
-            else:
-                return make_refnode(builder, fromdocname, docname,
-                                    labelid, contnode)
+            return make_refnode(builder, fromdocname, docname,
+                                labelid, contnode)
 
     def get_objects(self):
         for (prog, option), info in self.data['progoptions'].iteritems():

sphinx/environment.py

             target = node['reftarget']
             refdoc = node.get('refdoc', fromdocname)
             warned = False
+            domain = None
 
             try:
-                if node.has_key('refdomain') and node['refdomain']:
+                if 'refdomain' in node and node['refdomain']:
                     # let the domain try to resolve the reference
                     try:
                         domain = self.domains[node['refdomain']]
                     newnode = builder.app.emit_firstresult(
                         'missing-reference', self, node, contnode)
                     # still not found? warn if in nit-picky mode
-                    if newnode is None and not warned and self.config.nitpicky:
-                        self.warn(refdoc,
-                            'reference target not found: %stype %s, target %s'
-                            % (node.get('refdomain') and
-                               'domain %s, ' % node['refdomain'] or '',
-                               typ, target), node.line)
+                    if newnode is None and not warned and \
+                       (self.config.nitpicky or node.get('refwarn')):
+                        if domain and typ in domain.dangling_warnings:
+                            msg = domain.dangling_warnings[typ]
+                        elif node.get('refdomain') != 'std':
+                            msg = '%s:%s reference target not found: ' \
+                                  '%%(target)s' % (node['refdomain'], typ)
+                        else:
+                            msg = '%s reference target not found: ' \
+                                  '%%(target)s' % typ
+                        self.warn(refdoc, msg % {'target': target}, node.line)
             except NoUri:
                 newnode = contnode
             node.replace_self(newnode or contnode)
     innernodeclass = nodes.literal
 
     def __init__(self, fix_parens=False, lowercase=False,
-                 nodeclass=None, innernodeclass=None):
+                 nodeclass=None, innernodeclass=None, warn_dangling=False):
         self.fix_parens = fix_parens
         self.lowercase = lowercase
+        self.warn_dangling = warn_dangling
         if nodeclass is not None:
             self.nodeclass = nodeclass
         if innernodeclass is not None:
         refnode += self.innernodeclass(rawtext, title, classes=classes)
         # we also need the source document
         refnode['refdoc'] = env.docname
+        refnode['refwarn'] = self.warn_dangling
         # result_nodes allow further modification of return values
         return self.result_nodes(inliner.document, env, refnode, is_ref=True)
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.