mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-30 22:03:54 -06:00
docs/qapi-domain: add QAPI xref roles
Add domain-specific cross-reference syntax. As of this commit, that means new :qapi:any:`block-core` referencing syntax. The :any: role will find anything registered to the QAPI domain, including modules, commands, events, etc. Creating the cross-references is powered by the QAPIXRefRole class; resolving them is handled by QAPIDomain.resolve_xref(). QAPIXrefRole is based heavily on Sphinx's own PyXrefRole, with modifications necessary for QAPI features. Signed-off-by: John Snow <jsnow@redhat.com> Message-ID: <20250311034303.75779-9-jsnow@redhat.com> Acked-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
parent
dca2f3c471
commit
760b37e1df
1 changed files with 87 additions and 1 deletions
|
@ -26,6 +26,7 @@ from sphinx.domains import (
|
||||||
ObjType,
|
ObjType,
|
||||||
)
|
)
|
||||||
from sphinx.locale import _, __
|
from sphinx.locale import _, __
|
||||||
|
from sphinx.roles import XRefRole
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.nodes import make_refnode
|
from sphinx.util.nodes import make_refnode
|
||||||
|
|
||||||
|
@ -47,6 +48,54 @@ class ObjectEntry(NamedTuple):
|
||||||
aliased: bool
|
aliased: bool
|
||||||
|
|
||||||
|
|
||||||
|
class QAPIXRefRole(XRefRole):
|
||||||
|
|
||||||
|
def process_link(
|
||||||
|
self,
|
||||||
|
env: BuildEnvironment,
|
||||||
|
refnode: Element,
|
||||||
|
has_explicit_title: bool,
|
||||||
|
title: str,
|
||||||
|
target: str,
|
||||||
|
) -> tuple[str, str]:
|
||||||
|
refnode["qapi:module"] = env.ref_context.get("qapi:module")
|
||||||
|
|
||||||
|
# Cross-references that begin with a tilde adjust the title to
|
||||||
|
# only show the reference without a leading module, even if one
|
||||||
|
# was provided. This is a Sphinx-standard syntax; give it
|
||||||
|
# priority over QAPI-specific type markup below.
|
||||||
|
hide_module = False
|
||||||
|
if target.startswith("~"):
|
||||||
|
hide_module = True
|
||||||
|
target = target[1:]
|
||||||
|
|
||||||
|
# Type names that end with "?" are considered optional
|
||||||
|
# arguments and should be documented as such, but it's not
|
||||||
|
# part of the xref itself.
|
||||||
|
if target.endswith("?"):
|
||||||
|
refnode["qapi:optional"] = True
|
||||||
|
target = target[:-1]
|
||||||
|
|
||||||
|
# Type names wrapped in brackets denote lists. strip the
|
||||||
|
# brackets and remember to add them back later.
|
||||||
|
if target.startswith("[") and target.endswith("]"):
|
||||||
|
refnode["qapi:array"] = True
|
||||||
|
target = target[1:-1]
|
||||||
|
|
||||||
|
if has_explicit_title:
|
||||||
|
# Don't mess with the title at all if it was explicitly set.
|
||||||
|
# Explicit title syntax for references is e.g.
|
||||||
|
# :qapi:type:`target <explicit title>`
|
||||||
|
# and this explicit title overrides everything else here.
|
||||||
|
return title, target
|
||||||
|
|
||||||
|
title = target
|
||||||
|
if hide_module:
|
||||||
|
title = target.split(".")[-1]
|
||||||
|
|
||||||
|
return title, target
|
||||||
|
|
||||||
|
|
||||||
class QAPIIndex(Index):
|
class QAPIIndex(Index):
|
||||||
"""
|
"""
|
||||||
Index subclass to provide the QAPI definition index.
|
Index subclass to provide the QAPI definition index.
|
||||||
|
@ -118,7 +167,13 @@ class QAPIDomain(Domain):
|
||||||
object_types: Dict[str, ObjType] = {}
|
object_types: Dict[str, ObjType] = {}
|
||||||
|
|
||||||
directives = {}
|
directives = {}
|
||||||
roles = {}
|
|
||||||
|
# These are all cross-reference roles; e.g.
|
||||||
|
# :qapi:cmd:`query-block`. The keys correlate to the names used in
|
||||||
|
# the object_types table values above.
|
||||||
|
roles = {
|
||||||
|
"any": QAPIXRefRole(), # reference *any* type of QAPI object.
|
||||||
|
}
|
||||||
|
|
||||||
# Moved into the data property at runtime;
|
# Moved into the data property at runtime;
|
||||||
# this is the internal index of reference-able objects.
|
# this is the internal index of reference-able objects.
|
||||||
|
@ -252,6 +307,37 @@ class QAPIDomain(Domain):
|
||||||
matches = [m for m in matches if not m[1].aliased]
|
matches = [m for m in matches if not m[1].aliased]
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
|
def resolve_xref(
|
||||||
|
self,
|
||||||
|
env: BuildEnvironment,
|
||||||
|
fromdocname: str,
|
||||||
|
builder: Builder,
|
||||||
|
typ: str,
|
||||||
|
target: str,
|
||||||
|
node: pending_xref,
|
||||||
|
contnode: Element,
|
||||||
|
) -> nodes.reference | None:
|
||||||
|
modname = node.get("qapi:module")
|
||||||
|
matches = self.find_obj(modname, target, typ)
|
||||||
|
|
||||||
|
if not matches:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if len(matches) > 1:
|
||||||
|
logger.warning(
|
||||||
|
__("more than one target found for cross-reference %r: %s"),
|
||||||
|
target,
|
||||||
|
", ".join(match[0] for match in matches),
|
||||||
|
type="ref",
|
||||||
|
subtype="qapi",
|
||||||
|
location=node,
|
||||||
|
)
|
||||||
|
|
||||||
|
name, obj = matches[0]
|
||||||
|
return make_refnode(
|
||||||
|
builder, fromdocname, obj.docname, obj.node_id, contnode, name
|
||||||
|
)
|
||||||
|
|
||||||
def resolve_any_xref(
|
def resolve_any_xref(
|
||||||
self,
|
self,
|
||||||
env: BuildEnvironment,
|
env: BuildEnvironment,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue