Commits

Georg Brandl  committed 46fdf1d Merge

merge with 1.0

  • Participants
  • Parent commits ee93803, 65c3dc1

Comments (0)

Files changed (6)

 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.
+
 * #590: Fix inline display of graphviz diagrams in LaTeX output.
 
 * #589: Build using app.build() in setup command.

File 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 = {}

File sphinx/domains/cpp.py

                                 contnode, name)
 
         parser = DefinitionParser(target)
-        # XXX: warn?
         try:
             expr = parser.parse_type().get_name()
             parser.skip_ws()
             if not parser.eof or expr is None:
-                return None
+                raise DefinitionError('')
         except DefinitionError:
+            refdoc = node.get('refdoc', fromdocname)
+            env.warn(refdoc, 'unparseable C++ definition: %r' % target,
+                     node.line)
             return None
 
         parent = node['cpp:parent']

File 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():

File 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))
+                    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)

File sphinx/roles.py

     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)