qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Victor Toso de Carvalho" <victortoso@redhat.com>,
	"Peter Maydell" <peter.maydell@linaro.org>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"John Snow" <jsnow@redhat.com>
Subject: [PATCH 03/27] docs/qapi-module: add QAPI domain object registry
Date: Fri, 19 Apr 2024 00:37:51 -0400	[thread overview]
Message-ID: <20240419043820.178731-4-jsnow@redhat.com> (raw)
In-Reply-To: <20240419043820.178731-1-jsnow@redhat.com>

This is the first step towards QAPI domain cross-references and a QAPI
reference index.

For now, just create the object registry and amend the qapi:module
directive to use that registry. Update the merge_domaindata method now
that we have actual data we may need to merge.

RFC: Much of this code is adapted directly from sphinx.domains.python;
it is unclear to me if there ever would be a collision on merge, hence
the assertion. I haven't been able to trigger it or find better code to
use as a template, so probably I'll just leave the assertion in there.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/sphinx/qapi-domain.py | 76 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 73 insertions(+), 3 deletions(-)

diff --git a/docs/sphinx/qapi-domain.py b/docs/sphinx/qapi-domain.py
index 7c5e4407bc1..ab80fd5f634 100644
--- a/docs/sphinx/qapi-domain.py
+++ b/docs/sphinx/qapi-domain.py
@@ -11,6 +11,7 @@
     Dict,
     Iterable,
     List,
+    NamedTuple,
     Tuple,
     cast,
 )
@@ -20,6 +21,7 @@
 
 from sphinx import addnodes
 from sphinx.domains import Domain, ObjType
+from sphinx.locale import _, __
 from sphinx.util import logging
 from sphinx.util.docutils import SphinxDirective, switch_source_input
 from sphinx.util.nodes import make_id, nested_parse_with_titles
@@ -34,6 +36,13 @@
 logger = logging.getLogger(__name__)
 
 
+class ObjectEntry(NamedTuple):
+    docname: str
+    node_id: str
+    objtype: str
+    aliased: bool
+
+
 def _nested_parse(directive: SphinxDirective, content_node: Element) -> None:
     """
     This helper preserves error parsing context across sphinx versions.
@@ -101,6 +110,7 @@ class QAPIModule(SphinxDirective):
     }
 
     def run(self) -> List[Node]:
+        domain = cast(QAPIDomain, self.env.get_domain("qapi"))
         modname = self.arguments[0].strip()
         no_index = "no-index" in self.options or "noindex" in self.options
 
@@ -113,11 +123,14 @@ def run(self) -> List[Node]:
         inode = addnodes.index(entries=[])
 
         if not no_index:
+            # note module to the domain
             node_id = make_id(self.env, self.state.document, "module", modname)
             target = nodes.target("", "", ids=[node_id], ismod=True)
             self.set_source_info(target)
             self.state.document.note_explicit_target(target)
 
+            domain.note_object(modname, "module", node_id, location=target)
+
             indextext = f"QAPI module; {modname}"
             inode = addnodes.index(
                 entries=[
@@ -148,7 +161,12 @@ class QAPIDomain(Domain):
     name = "qapi"
     label = "QAPI"
 
-    object_types: Dict[str, ObjType] = {}
+    # This table associates cross-reference object types (key) with an
+    # ObjType instance, which defines the valid cross-reference roles
+    # for each object type.
+    object_types: Dict[str, ObjType] = {
+        "module": ObjType(_("module"), "mod", "obj"),
+    }
 
     # Each of these provides a ReST directive,
     # e.g. .. qapi:module:: block-core
@@ -157,11 +175,63 @@ class QAPIDomain(Domain):
     }
 
     roles = {}
-    initial_data: Dict[str, Dict[str, Tuple[Any]]] = {}
+
+    # Moved into the data property at runtime;
+    # this is the internal index of reference-able objects.
+    initial_data: Dict[str, Dict[str, Tuple[Any]]] = {
+        "objects": {},  # fullname -> ObjectEntry
+    }
+
     indices = []
 
+    @property
+    def objects(self) -> Dict[str, ObjectEntry]:
+        return self.data.setdefault("objects", {})  # type: ignore[no-any-return]
+
+    def note_object(
+        self,
+        name: str,
+        objtype: str,
+        node_id: str,
+        aliased: bool = False,
+        location: Any = None,
+    ) -> None:
+        """Note a QAPI object for cross reference."""
+        if name in self.objects:
+            other = self.objects[name]
+            if other.aliased and aliased is False:
+                # The original definition found. Override it!
+                pass
+            elif other.aliased is False and aliased:
+                # The original definition is already registered.
+                return
+            else:
+                # duplicated
+                logger.warning(
+                    __(
+                        "duplicate object description of %s, "
+                        "other instance in %s, use :no-index: for one of them"
+                    ),
+                    name,
+                    other.docname,
+                    location=location,
+                )
+        self.objects[name] = ObjectEntry(self.env.docname, node_id, objtype, aliased)
+
+    def clear_doc(self, docname: str) -> None:
+        for fullname, obj in list(self.objects.items()):
+            if obj.docname == docname:
+                del self.objects[fullname]
+
     def merge_domaindata(self, docnames: List[str], otherdata: Dict[str, Any]) -> None:
-        pass
+        for fullname, obj in otherdata["objects"].items():
+            if obj.docname in docnames:
+                # FIXME: Unsure of the implications of merge conflicts.
+                # Sphinx's own python domain doesn't appear to bother.
+                assert (
+                    fullname not in self.objects
+                ), f"!?!? collision on merge? {fullname=} {obj=} {self.objects[fullname]=}"
+                self.objects[fullname] = obj
 
 
 def setup(app: Sphinx) -> Dict[str, Any]:
-- 
2.44.0



  parent reply	other threads:[~2024-04-19  4:39 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-19  4:37 [PATCH 00/27] Add qapi-domain Sphinx extension John Snow
2024-04-19  4:37 ` [PATCH 01/27] docs/sphinx: create QAPI domain extension stub John Snow
2024-04-19  4:37 ` [PATCH 02/27] docs/qapi-domain: add qapi:module directive John Snow
2024-04-19  4:37 ` John Snow [this message]
2024-04-19  4:37 ` [PATCH 04/27] docs/qapi-domain: add QAPI index John Snow
2024-04-19  4:37 ` [PATCH 05/27] docs/qapi-domain: add resolve_any_xref() John Snow
2024-04-19  4:37 ` [PATCH 06/27] docs/qapi-domain: add QAPI xref roles John Snow
2024-04-19  4:37 ` [PATCH 07/27] docs/qapi-domain: add qapi:command directive John Snow
2024-04-19  4:37 ` [PATCH 08/27] docs/qapi-domain: add :since: directive option John Snow
2024-04-19  4:37 ` [PATCH 09/27] docs/qapi-domain: add "Arguments:" field lists John Snow
2024-04-19  4:37 ` [PATCH 10/27] docs/qapi-domain: add "Features:" " John Snow
2024-04-19  4:37 ` [PATCH 11/27] docs/qapi-domain: add "Errors:" " John Snow
2024-04-19  4:38 ` [PATCH 12/27] docs/qapi-domain: add "Returns:" " John Snow
2024-04-19  4:38 ` [PATCH 13/27] docs/qapi-domain: add qapi:enum directive John Snow
2024-04-19  4:38 ` [PATCH 14/27] docs/qapi-domain: add qapi:alternate directive John Snow
2024-04-19  4:38 ` [PATCH 15/27] docs/qapi-domain: add qapi:event directive John Snow
2024-04-19  4:38 ` [PATCH 16/27] docs/qapi-domain: add qapi:struct directive John Snow
2024-04-19  4:38 ` [PATCH 17/27] docs/qapi-domain: add qapi:union and qapi:branch directives John Snow
2024-04-19  4:38 ` [PATCH 18/27] docs/qapi-domain: add :deprecated: directive option John Snow
2024-04-19  4:38 ` [PATCH 19/27] docs/qapi-domain: add :unstable: " John Snow
2024-04-19  4:38 ` [PATCH 20/27] docs/qapi-domain: add :ifcond: " John Snow
2024-04-19  4:38 ` [PATCH 21/27] docs/qapi-domain: RFC patch - add malformed field list entries John Snow
2024-04-19  4:38 ` [PATCH 22/27] docs/qapi-domain: add warnings for malformed field lists John Snow
2024-04-19  4:38 ` [PATCH 23/27] docs/qapi-domain: RFC patch - delete " John Snow
2024-04-19  4:38 ` [PATCH 24/27] docs/qapi-domain: add type cross-refs to " John Snow
2024-04-19 16:58   ` John Snow
2024-04-19  4:38 ` [PATCH 25/27] docs/qapi-domain: implement error context reporting fix John Snow
2024-04-19  4:38 ` [PATCH 26/27] docs/qapi-domain: RFC patch - Add one last sample command John Snow
2024-04-19  4:38 ` [PATCH 27/27] docs/qapi-domain: add CSS styling John Snow
2024-04-19 14:45 ` [PATCH 00/27] Add qapi-domain Sphinx extension Markus Armbruster
2024-04-19 15:10   ` Markus Armbruster
2024-04-19 16:31   ` John Snow
2024-04-22  9:19     ` Markus Armbruster
2024-04-22 16:38       ` John Snow
2024-04-23  1:56         ` John Snow
2024-04-23  7:48           ` Markus Armbruster
2024-04-23 18:32             ` John Snow
2024-04-24 14:13               ` Markus Armbruster
2024-04-23  7:19         ` Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240419043820.178731-4-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=armbru@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=victortoso@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).