docs: kernel_include.py: propose alternatives

Specially when using c::namespace, it is not hard to break
a reference by forgetting to add a domain. Also, different
cases and using "-"/"_" the wrong way are typical cases that
people often gets wrong.

We might use a more complex logic here to also check for typos,
but let's keep it plain, simple.

This is enough to get thos exeptions from media controller:

  .../include/uapi/linux/media.h:26: WARNING: Invalid xref: c:type:`media_device_info`. Possible alternatives:
	c:type:`MC.media_device_info` (from mediactl/media-ioc-device-info)
  .../include/uapi/linux/media.h:149: WARNING: Invalid xref: c:type:`media_entity_desc`. Possible alternatives:
	c:type:`MC.media_entity_desc` (from mediactl/media-ioc-enum-entities)
  .../include/uapi/linux/media.h:228: WARNING: Invalid xref: c:type:`media_link_desc`. Possible alternatives:
	c:type:`MC.media_link_desc` (from mediactl/media-ioc-enum-links)
  .../include/uapi/linux/media.h:235: WARNING: Invalid xref: c:type:`media_links_enum`. Possible alternatives:
	c:type:`MC.media_links_enum` (from mediactl/media-ioc-enum-links)
  .../include/uapi/linux/media.h:212: WARNING: Invalid xref: c:type:`media_pad_desc`. Possible alternatives:
	c:type:`MC.media_pad_desc` (from mediactl/media-ioc-enum-links)
  .../include/uapi/linux/media.h:298: WARNING: Invalid xref: c:type:`media_v2_entity`. Possible alternatives:
	c:type:`MC.media_v2_entity` (from mediactl/media-ioc-g-topology)
  .../include/uapi/linux/media.h:312: WARNING: Invalid xref: c:type:`media_v2_interface`. Possible alternatives:
	c:type:`MC.media_v2_interface` (from mediactl/media-ioc-g-topology)
  .../include/uapi/linux/media.h:307: WARNING: Invalid xref: c:type:`media_v2_intf_devnode`. Possible alternatives:
	c:type:`MC.media_v2_intf_devnode` (from mediactl/media-ioc-g-topology)
  .../include/uapi/linux/media.h:341: WARNING: Invalid xref: c:type:`media_v2_link`. Possible alternatives:
	c:type:`MC.media_v2_link` (from mediactl/media-ioc-g-topology)
  .../include/uapi/linux/media.h:333: WARNING: Invalid xref: c:type:`media_v2_pad`. Possible alternatives:
	c:type:`MC.media_v2_pad` (from mediactl/media-ioc-g-topology)
  .../include/uapi/linux/media.h:349: WARNING: Invalid xref: c:type:`media_v2_topology`. Possible alternatives:
	c:type:`MC.media_v2_topology` (from mediactl/media-ioc-g-topology)

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Message-ID: <4c75d277e950e619ea00ba2dea336853a4aac976.1759329363.git.mchehab+huawei@kernel.org>
pull/1354/merge
Mauro Carvalho Chehab 2025-10-01 16:49:27 +02:00 committed by Jonathan Corbet
parent 3ed9521772
commit 641a4a13f3
3 changed files with 77 additions and 4 deletions

View File

@ -105,6 +105,7 @@ logger = logging.getLogger(__name__)
RE_DOMAIN_REF = re.compile(r'\\ :(ref|c:type|c:func):`([^<`]+)(?:<([^>]+)>)?`\\')
RE_SIMPLE_REF = re.compile(r'`([^`]+)`')
RE_LINENO_REF = re.compile(r'^\s*-\s+LINENO_(\d+):\s+(.*)')
RE_SPLIT_DOMAIN = re.compile(r"(.*)\.(.*)")
def ErrorString(exc): # Shamelessly stolen from docutils
return f'{exc.__class__.__name}: {exc}'
@ -399,6 +400,67 @@ class KernelInclude(Directive):
reported = set()
DOMAIN_INFO = {}
def fill_domain_info(env):
"""
Get supported reference types for each Sphinx domain and C namespaces
"""
if DOMAIN_INFO:
return
for domain_name, domain_instance in env.domains.items():
try:
object_types = list(domain_instance.object_types.keys())
DOMAIN_INFO[domain_name] = object_types
except AttributeError:
# Ignore domains that we can't retrieve object types, if any
pass
def get_suggestions(app, env, node,
original_target, original_domain, original_reftype):
"""Check if target exists in the other domain or with different reftypes."""
original_target = original_target.lower()
# Remove namespace if present
if '.' in original_target:
original_target = original_target.split(".")[-1]
targets = set([
original_target,
original_target.replace("-", "_"),
original_target.replace("_", "-"),
])
# Propose some suggestions, if possible
# The code below checks not only variants of the target, but also it
# works when .. c:namespace:: targets setting a different C namespace
# is in place
suggestions = []
for target in sorted(targets):
for domain in DOMAIN_INFO.keys():
domain_obj = env.get_domain(domain)
for name, dispname, objtype, docname, anchor, priority in domain_obj.get_objects():
lower_name = name.lower()
if domain == "c":
# Check if name belongs to a different C namespace
match = RE_SPLIT_DOMAIN.match(name)
if match:
if target != match.group(2).lower():
continue
else:
if target != lower_name:
continue
else:
if target != lower_name:
continue
suggestions.append(f"\t{domain}:{objtype}:`{name}` (from {docname})")
return suggestions
def check_missing_refs(app, env, node, contnode):
"""Check broken refs for the files it creates xrefs"""
if not node.source:
@ -414,11 +476,13 @@ def check_missing_refs(app, env, node, contnode):
if node.source not in xref_files:
return None
fill_domain_info(env)
target = node.get('reftarget', '')
domain = node.get('refdomain', 'std')
reftype = node.get('reftype', '')
msg = f"can't link to: {domain}:{reftype}:: {target}"
msg = f"Invalid xref: {domain}:{reftype}:`{target}`"
# Don't duplicate warnings
data = (node.source, msg)
@ -426,6 +490,10 @@ def check_missing_refs(app, env, node, contnode):
return None
reported.add(data)
suggestions = get_suggestions(app, env, node, target, domain, reftype)
if suggestions:
msg += ". Possible alternatives:\n" + '\n'.join(suggestions)
logger.warning(msg, location=node, type='ref', subtype='missing')
return None

View File

@ -2,10 +2,12 @@
.. _videodev:
*******************************
Video For Linux Two Header File
*******************************
***************************************
Video For Linux Two Header uAPI Symbols
***************************************
.. kernel-include:: include/uapi/linux/videodev2.h
:generate-cross-refs:
:exception-file: videodev2.h.rst.exceptions
:toc:
:warn-broken:

View File

@ -1,5 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
# All symbols are mapped inside V4L C domain namespace
namespace V4L
# Ignore header name
ignore define _UAPI__LINUX_VIDEODEV2_H