diff options
author | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2020-08-08 20:06:46 +0900 |
---|---|---|
committer | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2020-11-03 02:27:43 +0900 |
commit | 0e98e9b1a8ade24acf1d91f59aa90e8b1e179b19 (patch) | |
tree | 6fdb9ca354e92e1fe28efb6fbf9fdabf45e77f15 | |
parent | 487b8436c6e8dc596db4b8d4d06e9145105a2ac2 (diff) | |
download | sphinx-git-0e98e9b1a8ade24acf1d91f59aa90e8b1e179b19.tar.gz |
Fix #6914: Emit a detailed warning when failed to resolve :ref:
To be clear the ambiguous warning for missing-reference :ref:,
this separates the warning to missing-label and missing-caption.
To emit a warning dynamically, this also adds a new event:
`warn-missing-reference` to customize warning messages via event
handlers.
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | doc/extdev/appapi.rst | 9 | ||||
-rw-r--r-- | sphinx/domains/std.py | 17 | ||||
-rw-r--r-- | sphinx/events.py | 1 | ||||
-rw-r--r-- | sphinx/transforms/post_transforms/__init__.py | 5 | ||||
-rw-r--r-- | tests/roots/test-domain-py-xref-warning/conf.py | 0 | ||||
-rw-r--r-- | tests/roots/test-domain-py-xref-warning/index.rst | 7 | ||||
-rw-r--r-- | tests/test_domain_py.py | 8 |
8 files changed, 48 insertions, 3 deletions
@@ -13,6 +13,10 @@ Deprecated Features added -------------- +* #6914: Add a new event :event:`warn-missing-reference` to custom warning + messages when failed to resolve a cross-reference +* #6914: Emit a detailed warning when failed to resolve a ``:ref:`` reference + Bugs fixed ---------- diff --git a/doc/extdev/appapi.rst b/doc/extdev/appapi.rst index df3eb3d67..9f2c10676 100644 --- a/doc/extdev/appapi.rst +++ b/doc/extdev/appapi.rst @@ -186,6 +186,7 @@ type for that event:: 13. apply post-transforms (by priority): docutils.document -> docutils.document 14. event.doctree-resolved(app, doctree, docname) - (for any reference node that fails to resolve) event.missing-reference(env, node, contnode) + - (for any reference node that fails to resolve) event.warn-missing-reference(domain, node) 15. Generate output files 16. event.build-finished(app, exception) @@ -284,6 +285,14 @@ Here is a more detailed list of these events. .. versionadded:: 0.5 +.. event:: warn-missing-reference (app, domain, node) + + Emitted when a cross-reference to an object cannot be resolved even after + :event:`missing-reference`. If the event handler can emit warnings for + the missing reference, it should return ``True``. + + .. versionadded:: 3.4 + .. event:: doctree-resolved (app, doctree, docname) Emitted when a doctree has been "resolved" by the environment, that is, all diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index 39f67b54e..7ea468404 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -610,8 +610,6 @@ class StandardDomain(Domain): 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)', 'numref': 'undefined label: %(target)s', 'keyword': 'unknown keyword: %(target)s', 'doc': 'unknown document: %(target)s', @@ -1107,8 +1105,23 @@ class StandardDomain(Domain): RemovedInSphinx40Warning, stacklevel=2) +def warn_missing_reference(app: "Sphinx", domain: Domain, node: pending_xref) -> bool: + if domain.name != 'std' or node['reftype'] != 'ref': + return None + else: + target = node['reftarget'] + if target not in domain.anonlabels: # type: ignore + msg = __('undefined label: %s') + else: + msg = __('Failed to create a cross reference. A title or caption not found: %s') + + logger.warning(msg % target, location=node, type='ref', subtype=node['reftype']) + return True + + def setup(app: "Sphinx") -> Dict[str, Any]: app.add_domain(StandardDomain) + app.connect('warn-missing-reference', warn_missing_reference) return { 'version': 'builtin', diff --git a/sphinx/events.py b/sphinx/events.py index 82a52d762..214654706 100644 --- a/sphinx/events.py +++ b/sphinx/events.py @@ -46,6 +46,7 @@ core_events = { 'doctree-read': 'the doctree before being pickled', 'env-merge-info': 'env, read docnames, other env instance', 'missing-reference': 'env, node, contnode', + 'warn-missing-reference': 'domain, node', 'doctree-resolved': 'doctree, docname', 'env-updated': 'env', 'html-collect-pages': 'builder', diff --git a/sphinx/transforms/post_transforms/__init__.py b/sphinx/transforms/post_transforms/__init__.py index 7dc14af52..6633d6434 100644 --- a/sphinx/transforms/post_transforms/__init__.py +++ b/sphinx/transforms/post_transforms/__init__.py @@ -166,7 +166,10 @@ class ReferencesResolver(SphinxPostTransform): warn = False if not warn: return - if domain and typ in domain.dangling_warnings: + + if self.app.emit_firstresult('warn-missing-reference', domain, node): + return + elif domain and typ in domain.dangling_warnings: msg = domain.dangling_warnings[typ] elif node.get('refdomain', 'std') not in ('', 'std'): msg = (__('%s:%s reference target not found: %%(target)s') % diff --git a/tests/roots/test-domain-py-xref-warning/conf.py b/tests/roots/test-domain-py-xref-warning/conf.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/roots/test-domain-py-xref-warning/conf.py diff --git a/tests/roots/test-domain-py-xref-warning/index.rst b/tests/roots/test-domain-py-xref-warning/index.rst new file mode 100644 index 000000000..6f2cab795 --- /dev/null +++ b/tests/roots/test-domain-py-xref-warning/index.rst @@ -0,0 +1,7 @@ +test-domain-py-xref-warning +=========================== + +.. _existing-label: + +:ref:`no-label` +:ref:`existing-label` diff --git a/tests/test_domain_py.py b/tests/test_domain_py.py index ceea51508..d81b406c2 100644 --- a/tests/test_domain_py.py +++ b/tests/test_domain_py.py @@ -859,3 +859,11 @@ def test_noindexentry(app): assert_node(doctree, (addnodes.index, desc, addnodes.index, desc)) assert_node(doctree[0], addnodes.index, entries=[('single', 'f (built-in class)', 'f', '', None)]) assert_node(doctree[2], addnodes.index, entries=[]) + + +@pytest.mark.sphinx('dummy', testroot='domain-py-xref-warning') +def test_warn_missing_reference(app, status, warning): + app.build() + assert 'index.rst:6: WARNING: undefined label: no-label' in warning.getvalue() + assert ('index.rst:6: WARNING: Failed to create a cross reference. A title or caption not found: existing-label' + in warning.getvalue()) |