summaryrefslogtreecommitdiff
path: root/Utilities
diff options
context:
space:
mode:
authorMatthew Woehlke <matthew.woehlke@kitware.com>2023-03-09 11:32:07 -0500
committerMatthew Woehlke <matthew.woehlke@kitware.com>2023-03-09 11:32:07 -0500
commitcc21d0e47802fb1d054eb56b8bb4bd8ee66f9caa (patch)
tree0a63ab5ce52622dae91def59212c39ffb942eb4f /Utilities
parent37e015d4a65566386266a99c70226b4082defce2 (diff)
downloadcmake-cc21d0e47802fb1d054eb56b8bb4bd8ee66f9caa.tar.gz
Utilities/Sphinx: Make signatures linkable
Add signatures to the collection of observed objects (which can be referenced elsewhere). Don't automatically strip parameters from a :command: reference, as these may now link signatures. (Do, however, munge them into 'text <ref>' form if they aren't already, as not doing so adds an extra '()' for some reason.) Correspondingly, change xref resolution to try to match 'command' when a ref like 'command(args)' is not matched, so that existing links to commands that have not been converted to use the new signature directive don't immediately break.
Diffstat (limited to 'Utilities')
-rw-r--r--Utilities/Sphinx/cmake.py39
1 files changed, 29 insertions, 10 deletions
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index fb227671fa..a07b6e9091 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -360,7 +360,7 @@ class CMakeSignatureObject(CMakeObject):
def add_target_and_index(self, name, sig, signode):
if name in self.targetnames:
- targetname = self.targetnames[name].lower()
+ sigargs = self.targetnames[name]
else:
def extract_keywords(params):
for p in params:
@@ -370,7 +370,8 @@ class CMakeSignatureObject(CMakeObject):
return
keywords = extract_keywords(name.split('(')[1].split())
- targetname = ' '.join(keywords).lower()
+ sigargs = ' '.join(keywords)
+ targetname = sigargs.lower()
targetid = nodes.make_id(targetname)
if targetid not in self.state.document.ids:
@@ -379,6 +380,15 @@ class CMakeSignatureObject(CMakeObject):
signode['first'] = (not self.names)
self.state.document.note_explicit_target(signode)
+ # Register the signature as a command object.
+ command = name.split('(')[0].lower()
+ refname = f'{command}({sigargs})'
+ refid = f'command:{command}({targetname})'
+
+ domain = cast(CMakeDomain, self.env.get_domain('cmake'))
+ domain.note_object('command', name=refname, target_id=refid,
+ node_id=targetid, location=signode)
+
def run(self):
targets = self.options.get('target')
if targets is not None:
@@ -393,19 +403,15 @@ class CMakeXRefRole(XRefRole):
# See sphinx.util.nodes.explicit_title_re; \x00 escapes '<'.
_re = re.compile(r'^(.+?)(\s*)(?<!\x00)<(.*?)>$', re.DOTALL)
- _re_sub = re.compile(r'^([^()\s]+)\s*\(([^()]*)\)$', re.DOTALL)
+ _re_ref = re.compile(r'^.*\s<\w+([(][\w\s]+[)])?>$', re.DOTALL)
_re_genex = re.compile(r'^\$<([^<>:]+)(:[^<>]+)?>$', re.DOTALL)
_re_guide = re.compile(r'^([^<>/]+)/([^<>]*)$', re.DOTALL)
def __call__(self, typ, rawtext, text, *args, **keys):
- # Translate CMake command cross-references of the form:
- # `command_name(SUB_COMMAND)`
- # to have an explicit target:
- # `command_name(SUB_COMMAND) <command_name>`
if typ == 'cmake:command':
- m = CMakeXRefRole._re_sub.match(text)
- if m:
- text = '%s <%s>' % (text, m.group(1))
+ m = CMakeXRefRole._re_ref.match(text)
+ if m is None:
+ text = f'{text} <{text}>'
elif typ == 'cmake:genex':
m = CMakeXRefRole._re_genex.match(text)
if m:
@@ -461,6 +467,10 @@ class CMakeXRefTransform(Transform):
# Do not index cross-references to guide sections.
continue
+ if objtype == 'command':
+ # Index signature references to their parent command.
+ objname = objname.split('(')[0].lower()
+
targetnum = env.new_serialno('index-%s:%s' % (objtype, objname))
targetid = 'index-%s-%s:%s' % (targetnum, objtype, objname)
@@ -537,6 +547,15 @@ class CMakeDomain(Domain):
typ, target, node, contnode):
targetid = f'{typ}:{target}'
obj = self.data['objects'].get(targetid)
+
+ if obj is None and typ == 'command':
+ # If 'command(args)' wasn't found, try just 'command'.
+ # TODO: remove this fallback? warn?
+ # logger.warning(f'no match for {targetid}')
+ command = target.split('(')[0]
+ targetid = f'{typ}:{command}'
+ obj = self.data['objects'].get(targetid)
+
if obj is None:
# TODO: warn somehow?
return None