mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-21 14:40:48 +08:00
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.
This commit is contained in:
@@ -4,6 +4,9 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any, cast
|
||||||
|
|
||||||
# Override much of pygments' CMakeLexer.
|
# Override much of pygments' CMakeLexer.
|
||||||
# We need to parse CMake syntax definitions, not CMake code.
|
# 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.domains import Domain, ObjType
|
||||||
from sphinx.roles import XRefRole
|
from sphinx.roles import XRefRole
|
||||||
from sphinx.util.nodes import make_refnode
|
from sphinx.util.nodes import make_refnode
|
||||||
from sphinx.util import ws_re
|
from sphinx.util import logging, ws_re
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
sphinx_before_1_4 = False
|
sphinx_before_1_4 = False
|
||||||
sphinx_before_1_7_2 = False
|
sphinx_before_1_7_2 = False
|
||||||
try:
|
try:
|
||||||
@@ -104,6 +109,14 @@ if sphinx_before_1_7_2:
|
|||||||
return new_items
|
return new_items
|
||||||
QtHelpBuilder.build_keywords = new_build_keywords
|
QtHelpBuilder.build_keywords = new_build_keywords
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ObjectEntry:
|
||||||
|
docname: str
|
||||||
|
objtype: str
|
||||||
|
node_id: str
|
||||||
|
name: str
|
||||||
|
|
||||||
|
|
||||||
class CMakeModule(Directive):
|
class CMakeModule(Directive):
|
||||||
required_arguments = 1
|
required_arguments = 1
|
||||||
optional_arguments = 0
|
optional_arguments = 0
|
||||||
@@ -205,14 +218,6 @@ _cmake_index_objs = {
|
|||||||
'variable': _cmake_index_entry('variable'),
|
'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):
|
class CMakeTransform(Transform):
|
||||||
|
|
||||||
# Run this transform early since we insert nodes we want
|
# Run this transform early since we insert nodes we want
|
||||||
@@ -275,8 +280,10 @@ class CMakeTransform(Transform):
|
|||||||
indexnode = addnodes.index()
|
indexnode = addnodes.index()
|
||||||
indexnode['entries'] = [make_index_entry(title, targetid)]
|
indexnode['entries'] = [make_index_entry(title, targetid)]
|
||||||
self.document.insert(0, indexnode)
|
self.document.insert(0, indexnode)
|
||||||
|
|
||||||
# Add to cmake domain object inventory
|
# 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):
|
class CMakeObject(ObjectDescription):
|
||||||
|
|
||||||
@@ -300,8 +307,10 @@ class CMakeObject(ObjectDescription):
|
|||||||
signode['ids'].append(targetid)
|
signode['ids'].append(targetid)
|
||||||
signode['first'] = (not self.names)
|
signode['first'] = (not self.names)
|
||||||
self.state.document.note_explicit_target(signode)
|
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)
|
make_index_entry = _cmake_index_objs.get(self.objtype)
|
||||||
if make_index_entry:
|
if make_index_entry:
|
||||||
@@ -518,25 +527,37 @@ class CMakeDomain(Domain):
|
|||||||
|
|
||||||
def clear_doc(self, docname):
|
def clear_doc(self, docname):
|
||||||
to_clear = set()
|
to_clear = set()
|
||||||
for fullname, (fn, _) in self.data['objects'].items():
|
for fullname, obj in self.data['objects'].items():
|
||||||
if fn == docname:
|
if obj.docname == docname:
|
||||||
to_clear.add(fullname)
|
to_clear.add(fullname)
|
||||||
for fullname in to_clear:
|
for fullname in to_clear:
|
||||||
del self.data['objects'][fullname]
|
del self.data['objects'][fullname]
|
||||||
|
|
||||||
def resolve_xref(self, env, fromdocname, builder,
|
def resolve_xref(self, env, fromdocname, builder,
|
||||||
typ, target, node, contnode):
|
typ, target, node, contnode):
|
||||||
targetid = '%s:%s' % (typ, target)
|
targetid = f'{typ}:{target}'
|
||||||
obj = self.data['objects'].get(targetid)
|
obj = self.data['objects'].get(targetid)
|
||||||
if obj is None:
|
if obj is None:
|
||||||
# TODO: warn somehow?
|
# TODO: warn somehow?
|
||||||
return None
|
return None
|
||||||
return make_refnode(builder, fromdocname, obj[0], targetid,
|
|
||||||
|
return make_refnode(builder, fromdocname, obj.docname, obj.node_id,
|
||||||
contnode, target)
|
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):
|
def get_objects(self):
|
||||||
for refname, (docname, type) in self.data['objects'].items():
|
for refname, obj in self.data['objects'].items():
|
||||||
yield (refname, refname, type, docname, refname, 1)
|
yield (refname, obj.name, obj.objtype, obj.docname, obj.node_id, 1)
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
app.add_directive('cmake-module', CMakeModule)
|
app.add_directive('cmake-module', CMakeModule)
|
||||||
|
Reference in New Issue
Block a user