Skip to content

Commit 2b29866

Browse files
committed
Add codeautolink_warn_on_no_backreference config
Highlights where reference documentation does not have a corresponding tutorial or how-to Closes #161
1 parent 28b77b7 commit 2b29866

File tree

6 files changed

+40
-2
lines changed

6 files changed

+40
-2
lines changed

docs/src/reference.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ Configuration
6565
Type: ``bool``. Issue warning when failing to resolve the canonical location
6666
of an object that a code element references. Defaults to :code:`False`.
6767

68+
.. confval:: codeautolink_warn_on_no_backreference
69+
70+
Type: ``bool``. Issue warning when no backreference could be found
71+
from reference documentation using the :rst:dir:`autolink-examples` table.
72+
This highlights objects for which no tutorial, example or how-to exists.
73+
Defaults to :code:`False`.
74+
6875
Directives
6976
----------
7077
.. rst:directive:: .. autolink-examples:: object

docs/src/release_notes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ These release notes are based on
88
sphinx-codeautolink adheres to
99
`Semantic Versioning <https://semver.org>`_.
1010

11+
0.16.3 (unreleased)
12+
-------------------
13+
- Introduce :confval:`codeautolink_warn_on_no_backreference` to highlight
14+
where reference documentation does not appear to have
15+
a corresponding tutorial or how-to (:issue:`161`)
16+
1117
0.16.2 (2025-01-16)
1218
-------------------
1319
- Fix regression in not handling malformed return types (:issue:`159`)

src/sphinx_codeautolink/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ def setup(app: Sphinx):
4343
rebuild="html",
4444
types=[bool],
4545
)
46+
app.add_config_value(
47+
"codeautolink_warn_on_no_backreference",
48+
default=False,
49+
rebuild="html",
50+
types=[bool],
51+
)
4652

4753
app.add_directive("autolink-concat", directive.Concat)
4854
app.add_directive("autolink-examples", directive.Examples)

src/sphinx_codeautolink/extension/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def __init__(self) -> None:
7474
self.inventory_map: dict[str, str] = {}
7575
self.warn_missing_inventory = None
7676
self.warn_failed_resolve = None
77+
self.warn_no_backreference = None
7778

7879
# Populated once
7980
self.outdated_docs: set[str] = set()
@@ -103,6 +104,7 @@ def build_inited(self, app) -> None:
103104
self.inventory_map = app.config.codeautolink_inventory_map
104105
self.warn_missing_inventory = app.config.codeautolink_warn_on_missing_inventory
105106
self.warn_failed_resolve = app.config.codeautolink_warn_on_failed_resolve
107+
self.warn_no_backreference = app.config.codeautolink_warn_on_no_backreference
106108

107109
# Append static resources path so references in setup() are valid
108110
app.config.html_static_path.append(
@@ -255,7 +257,11 @@ def generate_backref_tables(self, app, doctree, docname):
255257
rm_vis = RemoveExtensionVisitor(doctree)
256258
return doctree.walkabout(rm_vis)
257259

258-
visitor = CodeRefsVisitor(doctree, code_refs=self.code_refs)
260+
visitor = CodeRefsVisitor(
261+
doctree,
262+
code_refs=self.code_refs,
263+
warn_no_backreference=self.warn_no_backreference,
264+
)
259265
doctree.walk(visitor)
260266
return None
261267

src/sphinx_codeautolink/extension/backref.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from docutils import nodes
66

7+
from sphinx_codeautolink.warn import logger, warn_type
8+
79
from .directive import DeferredExamples
810

911

@@ -56,10 +58,15 @@ class CodeRefsVisitor(nodes.SparseNodeVisitor):
5658
"""Replace :class:`DeferredCodeReferences` with table of concrete references."""
5759

5860
def __init__(
59-
self, *args, code_refs: dict[str, list[CodeExample]], **kwargs
61+
self,
62+
*args,
63+
code_refs: dict[str, list[CodeExample]],
64+
warn_no_backreference: bool = False,
65+
**kwargs,
6066
) -> None:
6167
super().__init__(*args, **kwargs)
6268
self.code_refs = code_refs
69+
self.warn_no_backreference = warn_no_backreference
6370

6471
def unknown_departure(self, node) -> None:
6572
"""Ignore unknown nodes."""
@@ -79,6 +86,11 @@ def unknown_visit(self, node) -> None:
7986
items = sorted(set(items))
8087

8188
if not items:
89+
if self.warn_no_backreference:
90+
msg = f"No backreference for: '{node.ref}'"
91+
logger.warning(
92+
msg, type=warn_type, subtype="no_backreference", location=node
93+
)
8294
# Remove surrounding paragraph too
8395
node.parent.parent.remove(node.parent)
8496
return

tests/extension/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
}
2727
codeautolink_warn_on_missing_inventory = True
2828
codeautolink_warn_on_failed_resolve = True
29+
codeautolink_warn_on_no_backreference = False
2930
"""
3031

3132
any_whitespace = re.compile(r"\s*")

0 commit comments

Comments
 (0)