summaryrefslogtreecommitdiff
path: root/Utilities
diff options
context:
space:
mode:
authorMatthew Woehlke <matthew.woehlke@kitware.com>2023-03-08 13:19:50 -0500
committerMatthew Woehlke <matthew.woehlke@kitware.com>2023-03-08 13:19:50 -0500
commit37e015d4a65566386266a99c70226b4082defce2 (patch)
tree08d9cae4da6e2593be1b2a16b2441225afcbf4f4 /Utilities
parent3d6075da4df6a4f93a835e446c2bbf29488f50bd (diff)
downloadcmake-37e015d4a65566386266a99c70226b4082defce2.tar.gz
Utilities/Sphinx: Refactor Sphinx reference recording
Rewrite how we record objects in our Sphinx extensions to more closely conform to how other domains do likewise, and to store more information than was previously being stored. This is a first step toward being able to record and reference signatures.
Diffstat (limited to 'Utilities')
-rw-r--r--Utilities/Sphinx/cmake.py57
1 files changed, 39 insertions, 18 deletions
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index 9043709f9f..fb227671fa 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -4,6 +4,9 @@
import os
import re
+from dataclasses import dataclass
+from typing import Any, cast
+
# Override much of pygments' CMakeLexer.
# We need to parse CMake syntax definitions, not CMake code.
@@ -69,9 +72,11 @@ from sphinx.directives import ObjectDescription, nl_escape_re
from sphinx.domains import Domain, ObjType
from sphinx.roles import XRefRole
from sphinx.util.nodes import make_refnode
-from sphinx.util import ws_re
+from sphinx.util import logging, ws_re
from sphinx import addnodes
+logger = logging.getLogger(__name__)
+
sphinx_before_1_4 = False
sphinx_before_1_7_2 = False
try:
@@ -104,6 +109,14 @@ if sphinx_before_1_7_2:
return new_items
QtHelpBuilder.build_keywords = new_build_keywords
+@dataclass
+class ObjectEntry:
+ docname: str
+ objtype: str
+ node_id: str
+ name: str
+
+
class CMakeModule(Directive):
required_arguments = 1
optional_arguments = 0
@@ -205,14 +218,6 @@ _cmake_index_objs = {
'variable': _cmake_index_entry('variable'),
}
-def _cmake_object_inventory(env, document, line, objtype, targetid):
- inv = env.domaindata['cmake']['objects']
- if targetid in inv:
- document.reporter.warning(
- 'CMake object "%s" also described in "%s".' %
- (targetid, env.doc2path(inv[targetid][0])), line=line)
- inv[targetid] = (env.docname, objtype)
-
class CMakeTransform(Transform):
# Run this transform early since we insert nodes we want
@@ -275,8 +280,10 @@ class CMakeTransform(Transform):
indexnode = addnodes.index()
indexnode['entries'] = [make_index_entry(title, targetid)]
self.document.insert(0, indexnode)
+
# Add to cmake domain object inventory
- _cmake_object_inventory(env, self.document, 1, objtype, targetid)
+ domain = cast(CMakeDomain, env.get_domain('cmake'))
+ domain.note_object(objtype, targetname, targetid, targetid)
class CMakeObject(ObjectDescription):
@@ -300,8 +307,10 @@ class CMakeObject(ObjectDescription):
signode['ids'].append(targetid)
signode['first'] = (not self.names)
self.state.document.note_explicit_target(signode)
- _cmake_object_inventory(self.env, self.state.document,
- self.lineno, self.objtype, targetid)
+
+ domain = cast(CMakeDomain, self.env.get_domain('cmake'))
+ domain.note_object(self.objtype, targetname, targetid, targetid,
+ location=signode)
make_index_entry = _cmake_index_objs.get(self.objtype)
if make_index_entry:
@@ -518,25 +527,37 @@ class CMakeDomain(Domain):
def clear_doc(self, docname):
to_clear = set()
- for fullname, (fn, _) in self.data['objects'].items():
- if fn == docname:
+ for fullname, obj in self.data['objects'].items():
+ if obj.docname == docname:
to_clear.add(fullname)
for fullname in to_clear:
del self.data['objects'][fullname]
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
- targetid = '%s:%s' % (typ, target)
+ targetid = f'{typ}:{target}'
obj = self.data['objects'].get(targetid)
if obj is None:
# TODO: warn somehow?
return None
- return make_refnode(builder, fromdocname, obj[0], targetid,
+
+ return make_refnode(builder, fromdocname, obj.docname, obj.node_id,
contnode, target)
+ def note_object(self, objtype: str, name: str, target_id: str,
+ node_id: str, location: Any = None):
+ if target_id in self.data['objects']:
+ other = self.data['objects'][target_id].docname
+ logger.warning(
+ f'CMake object {target_id!r} also described in {other!r}',
+ location=location)
+
+ self.data['objects'][target_id] = ObjectEntry(
+ self.env.docname, objtype, node_id, name)
+
def get_objects(self):
- for refname, (docname, type) in self.data['objects'].items():
- yield (refname, refname, type, docname, refname, 1)
+ for refname, obj in self.data['objects'].items():
+ yield (refname, obj.name, obj.objtype, obj.docname, obj.node_id, 1)
def setup(app):
app.add_directive('cmake-module', CMakeModule)