[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 06/27] docs/qapi-domain: add QAPI xref roles
From: |
John Snow |
Subject: |
[PATCH 06/27] docs/qapi-domain: add QAPI xref roles |
Date: |
Fri, 19 Apr 2024 00:37:54 -0400 |
Add domain-specific cross-reference syntax. As of this commit, that
means new :qapi:mod:`block-core` and :qapi:obj:`block-core` referencing
syntax.
:mod: will only find modules, but :obj: will find anything registered to
the QAPI domain. (In forthcoming commits, this means commands, events,
enums, etc.)
Creating the cross-references is powered by the QAPIXRefRole class;
resolving them is handled by QAPIDomain.resolve_xref().
QAPIXrefRole is copied almost verbatim from Sphinx's own
PyXrefRole. PyXrefRole (and QAPIXrefRole) adds two features over the
base class:
(1) Creating a cross-reference with e.g. :py:class:`~class.name`
instructs sphinx to omit the fully qualified parts of the resolved name
from the actual link text. This may be useful in the future if we add
namespaces to QAPI documentation, e.g. :qapi:cmd:`~qsd.blockdev-backup`
could link to the QSD-specific documentation for blockdev-backup while
omitting that prefix from the link text.
(2) Prefixing the link target with a "." changes the search behavior to
prefer locally-scoped items first.
I think both of these are worth keeping to help manage future namespace
issues between QEMU, QSD and QGA; but it's possible it's extraneous. It
may possibly be worth keeping just to keep feature parity with Sphinx's
other domains; e.g. "principle of least surprise". Dunno.
Signed-off-by: John Snow <jsnow@redhat.com>
---
docs/qapi/index.rst | 4 +++
docs/sphinx/qapi-domain.py | 67 +++++++++++++++++++++++++++++++++++++-
2 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/docs/qapi/index.rst b/docs/qapi/index.rst
index 39ad405fd93..e2223d5f363 100644
--- a/docs/qapi/index.rst
+++ b/docs/qapi/index.rst
@@ -47,3 +47,7 @@ cross-referencing syntax. Here's a link to `bar-module`, even
though
the actual output of that directive was suppressed. Here's a link to
`block-core`. A link to ```foo-module``` won't resolve because of the
``:no-index:`` option we used for that directive.
+
+Explicit cross-referencing syntax for QAPI modules is available with
+``:qapi:mod:`foo```, here's a link to :qapi:mod:`bar-module` and one to
+:qapi:mod:`block-core`.
diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py
index 4758451ff0e..d28ac1cb9d8 100644
--- a/docs/sphinx/qapi-domain.py
+++ b/docs/sphinx/qapi-domain.py
@@ -29,6 +29,7 @@
ObjType,
)
from sphinx.locale import _, __
+from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective, switch_source_input
from sphinx.util.nodes import (
@@ -56,6 +57,34 @@ class ObjectEntry(NamedTuple):
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")
+ if not has_explicit_title:
+ title = title.lstrip(".") # only has a meaning for the target
+ target = target.lstrip("~") # only has a meaning for the title
+ # if the first character is a tilde, don't display the module
+ # parts of the contents
+ if title[0:1] == "~":
+ title = title[1:]
+ dot = title.rfind(".")
+ if dot != -1:
+ title = title[dot + 1 :]
+ # if the first character is a dot, search more specific namespaces
first
+ # else search builtins first
+ if target[0:1] == ".":
+ target = target[1:]
+ refnode["refspecific"] = True
+ return title, target
+
+
def _nested_parse(directive: SphinxDirective, content_node: Element) -> None:
"""
This helper preserves error parsing context across sphinx versions.
@@ -234,7 +263,13 @@ class QAPIDomain(Domain):
"module": QAPIModule,
}
- 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 = {
+ "mod": QAPIXRefRole(),
+ "obj": QAPIXRefRole(), # reference *any* type of QAPI object.
+ }
# Moved into the data property at runtime;
# this is the internal index of reference-able objects.
@@ -363,6 +398,36 @@ def find_obj(
matches = [m for m in matches if not m[1].aliased]
return matches
+ def resolve_xref(
+ self,
+ env: BuildEnvironment,
+ fromdocname: str,
+ builder: Builder,
+ type: str,
+ target: str,
+ node: pending_xref,
+ contnode: Element,
+ ) -> Element | None:
+ modname = node.get("qapi:module")
+ matches = self.find_obj(modname, target, type)
+ multiple_matches = len(matches) > 1
+
+ if not matches:
+ return None
+ elif multiple_matches:
+ 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(
self,
env: BuildEnvironment,
--
2.44.0
- [PATCH 04/27] docs/qapi-domain: add QAPI index, (continued)
- [PATCH 04/27] docs/qapi-domain: add QAPI index, John Snow, 2024/04/19
- [PATCH 01/27] docs/sphinx: create QAPI domain extension stub, John Snow, 2024/04/19
- [PATCH 10/27] docs/qapi-domain: add "Features:" field lists, John Snow, 2024/04/19
- [PATCH 13/27] docs/qapi-domain: add qapi:enum directive, John Snow, 2024/04/19
- [PATCH 16/27] docs/qapi-domain: add qapi:struct directive, John Snow, 2024/04/19
- [PATCH 15/27] docs/qapi-domain: add qapi:event directive, John Snow, 2024/04/19
- [PATCH 22/27] docs/qapi-domain: add warnings for malformed field lists, John Snow, 2024/04/19
- [PATCH 17/27] docs/qapi-domain: add qapi:union and qapi:branch directives, John Snow, 2024/04/19
- [PATCH 23/27] docs/qapi-domain: RFC patch - delete malformed field lists, John Snow, 2024/04/19
- [PATCH 21/27] docs/qapi-domain: RFC patch - add malformed field list entries, John Snow, 2024/04/19
- [PATCH 06/27] docs/qapi-domain: add QAPI xref roles,
John Snow <=
- [PATCH 05/27] docs/qapi-domain: add resolve_any_xref(), John Snow, 2024/04/19
- [PATCH 07/27] docs/qapi-domain: add qapi:command directive, John Snow, 2024/04/19
- [PATCH 08/27] docs/qapi-domain: add :since: directive option, John Snow, 2024/04/19
- [PATCH 09/27] docs/qapi-domain: add "Arguments:" field lists, John Snow, 2024/04/19
- [PATCH 11/27] docs/qapi-domain: add "Errors:" field lists, John Snow, 2024/04/19
- [PATCH 02/27] docs/qapi-domain: add qapi:module directive, John Snow, 2024/04/19
- [PATCH 12/27] docs/qapi-domain: add "Returns:" field lists, John Snow, 2024/04/19
- [PATCH 14/27] docs/qapi-domain: add qapi:alternate directive, John Snow, 2024/04/19
- [PATCH 18/27] docs/qapi-domain: add :deprecated: directive option, John Snow, 2024/04/19
- [PATCH 19/27] docs/qapi-domain: add :unstable: directive option, John Snow, 2024/04/19