Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: kernel_include.py: generate warnings for broken refs

In the past, Sphinx used to warn about broken references. That's
basically the rationale for adding media uAPI files: to get
warnings about missed symbols.

This is not true anymore. So, we need to explicitly check them
after doctree-resolved event.

While here, move setup() to the end, to make it closer to
what we do on other extensions.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/73be9a198746421687e2eee916ccf8bf67980b7d.1755872208.git.mchehab+huawei@kernel.org

authored by

Mauro Carvalho Chehab and committed by
Jonathan Corbet
39f5f2fa 0cb6aee3

+89 -19
+89 -19
Documentation/sphinx/kernel_include.py
··· 26 26 environment variable name. Malformed variable names and references to 27 27 non-existing variables are left unchanged. 28 28 29 - This extension overrides Sphinx include directory, adding two extra 29 + This extension overrides Sphinx include directory, adding some extra 30 30 arguments: 31 31 32 32 1. :generate-cross-refs: ··· 35 35 class, which converts C data structures into cross-references to 36 36 be linked to ReST files containing a more comprehensive documentation; 37 37 38 - Don't use it together with :start-line: and/or :end-line:, as 39 - filtering input file line range is currently not supported. 40 - 41 38 2. :exception-file: 42 39 43 - Used together with :generate-cross-refs:. Points to a file containing 44 - rules to ignore C data structs or to use a different reference name, 45 - optionally using a different reference type. 40 + Used together with :generate-cross-refs 41 + 42 + Points to a file containing rules to ignore C data structs or to 43 + use a different reference name, optionally using a different 44 + reference type. 45 + 46 + 3. :warn-broken: 47 + 48 + Used together with :generate-cross-refs: 49 + 50 + Detect if the auto-generated cross references doesn't exist. 51 + 46 52 """ 47 53 48 54 # ============================================================================== ··· 56 50 # ============================================================================== 57 51 58 52 import os.path 53 + import re 59 54 import sys 60 55 61 56 from docutils import io, nodes, statemachine ··· 65 58 from docutils.parsers.rst.directives.body import CodeBlock, NumberLines 66 59 from docutils.parsers.rst.directives.misc import Include 67 60 61 + from sphinx.util import logging 62 + 68 63 srctree = os.path.abspath(os.environ["srctree"]) 69 64 sys.path.insert(0, os.path.join(srctree, "tools/docs/lib")) 70 65 71 66 from parse_data_structs import ParseDataStructs 72 67 73 68 __version__ = "1.0" 69 + logger = logging.getLogger(__name__) 74 70 75 - 76 - # ============================================================================== 77 - def setup(app): 78 - """Setup Sphinx exension""" 79 - app.add_directive("kernel-include", KernelInclude) 80 - return { 81 - "version": __version__, 82 - "parallel_read_safe": True, 83 - "parallel_write_safe": True, 84 - } 71 + RE_DOMAIN_REF = re.compile(r'\\ :(ref|c:type|c:func):`([^<`]+)(?:<([^>]+)>)?`\\') 72 + RE_SIMPLE_REF = re.compile(r'`([^`]+)`') 85 73 86 74 87 75 # ============================================================================== ··· 88 86 89 87 option_spec.update({ 90 88 'generate-cross-refs': directives.flag, 89 + 'warn-broken': directives.flag, 91 90 'exception-file': directives.unchanged, 92 91 }) 93 92 ··· 106 103 env.note_dependency(os.path.abspath(path)) 107 104 108 105 # return super(KernelInclude, self).run() # won't work, see HINTs in _run() 109 - return self._run() 106 + return self._run(env) 110 107 111 - def _run(self): 108 + def _run(self, env): 112 109 """Include a file as part of the content of this reST file.""" 113 110 114 111 # HINT: I had to copy&paste the whole Include.run method. I'am not happy ··· 154 151 155 152 if "code" not in self.options: 156 153 rawtext = ".. parsed-literal::\n\n" + rawtext 154 + 155 + # Store references on a symbol dict to be used at check time 156 + if 'warn-broken' in self.options: 157 + env._xref_files.add(path) 157 158 else: 158 159 try: 159 160 self.state.document.settings.record_dependencies.add(path) ··· 246 239 return codeblock.run() 247 240 self.state_machine.insert_input(include_lines, path) 248 241 return [] 242 + 243 + # ============================================================================== 244 + 245 + reported = set() 246 + 247 + def check_missing_refs(app, env, node, contnode): 248 + """Check broken refs for the files it creates xrefs""" 249 + if not node.source: 250 + return None 251 + 252 + try: 253 + xref_files = env._xref_files 254 + except AttributeError: 255 + logger.critical("FATAL: _xref_files not initialized!") 256 + raise 257 + 258 + # Only show missing references for kernel-include reference-parsed files 259 + if node.source not in xref_files: 260 + return None 261 + 262 + target = node.get('reftarget', '') 263 + domain = node.get('refdomain', 'std') 264 + reftype = node.get('reftype', '') 265 + 266 + msg = f"can't link to: {domain}:{reftype}:: {target}" 267 + 268 + # Don't duplicate warnings 269 + data = (node.source, msg) 270 + if data in reported: 271 + return None 272 + reported.add(data) 273 + 274 + logger.warning(msg, location=node, type='ref', subtype='missing') 275 + 276 + return None 277 + 278 + def merge_xref_info(app, env, docnames, other): 279 + """ 280 + As each process modify env._xref_files, we need to merge them back. 281 + """ 282 + if not hasattr(other, "_xref_files"): 283 + return 284 + env._xref_files.update(getattr(other, "_xref_files", set())) 285 + 286 + def init_xref_docs(app, env, docnames): 287 + """Initialize a list of files that we're generating cross references¨""" 288 + app.env._xref_files = set() 289 + 290 + # ============================================================================== 291 + 292 + def setup(app): 293 + """Setup Sphinx exension""" 294 + 295 + app.connect("env-before-read-docs", init_xref_docs) 296 + app.connect("env-merge-info", merge_xref_info) 297 + app.add_directive("kernel-include", KernelInclude) 298 + app.connect("missing-reference", check_missing_refs) 299 + 300 + return { 301 + "version": __version__, 302 + "parallel_read_safe": True, 303 + "parallel_write_safe": True, 304 + }