| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723 | 
							- # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
- # file Copyright.txt or https://cmake.org/licensing for details.
 
- # BEGIN imports
 
- import os
 
- import re
 
- from dataclasses import dataclass
 
- from typing import Any, List, Tuple, Type, cast
 
- import sphinx
 
- # The following imports may fail if we don't have Sphinx 2.x or later.
 
- if sphinx.version_info >= (2,):
 
-     from docutils import io, nodes
 
-     from docutils.nodes import Element, Node, TextElement, system_message
 
-     from docutils.parsers.rst import Directive, directives
 
-     from docutils.transforms import Transform
 
-     from docutils.utils.code_analyzer import Lexer, LexerError
 
-     from sphinx import addnodes
 
-     from sphinx.directives import ObjectDescription, nl_escape_re
 
-     from sphinx.domains import Domain, ObjType
 
-     from sphinx.roles import XRefRole
 
-     from sphinx.util import logging, ws_re
 
-     from sphinx.util.docutils import ReferenceRole
 
-     from sphinx.util.nodes import make_refnode
 
- else:
 
-     # Sphinx 2.x is required.
 
-     assert sphinx.version_info >= (2,)
 
- # END imports
 
- # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
- # BEGIN pygments tweaks
 
- # Override much of pygments' CMakeLexer.
 
- # We need to parse CMake syntax definitions, not CMake code.
 
- # For hard test cases that use much of the syntax below, see
 
- # - module/FindPkgConfig.html
 
- #     (with "glib-2.0>=2.10 gtk+-2.0" and similar)
 
- # - module/ExternalProject.html
 
- #     (with http:// https:// git@; also has command options -E --build)
 
- # - manual/cmake-buildsystem.7.html
 
- #     (with nested $<..>; relative and absolute paths, "::")
 
- from pygments.lexer import bygroups  # noqa I100
 
- from pygments.lexers import CMakeLexer
 
- from pygments.token import (Comment, Name, Number, Operator, Punctuation,
 
-                             String, Text, Whitespace)
 
- # Notes on regular expressions below:
 
- # - [\.\+-] are needed for string constants like gtk+-2.0
 
- # - Unix paths are recognized by '/'; support for Windows paths may be added
 
- #   if needed
 
- # - (\\.) allows for \-escapes (used in manual/cmake-language.7)
 
- # - $<..$<..$>..> nested occurrence in cmake-buildsystem
 
- # - Nested variable evaluations are only supported in a limited capacity.
 
- #   Only one level of nesting is supported and at most one nested variable can
 
- #   be present.
 
- CMakeLexer.tokens["root"] = [
 
-   # fctn(
 
-   (r'\b(\w+)([ \t]*)(\()',
 
-    bygroups(Name.Function, Text, Name.Function), '#push'),
 
-   (r'\(', Name.Function, '#push'),
 
-   (r'\)', Name.Function, '#pop'),
 
-   (r'\[', Punctuation, '#push'),
 
-   (r'\]', Punctuation, '#pop'),
 
-   (r'[|;,.=*\-]', Punctuation),
 
-   # used in commands/source_group
 
-   (r'\\\\', Punctuation),
 
-   (r'[:]', Operator),
 
-   # used in FindPkgConfig.cmake
 
-   (r'[<>]=', Punctuation),
 
-   # $<...>
 
-   (r'\$<', Operator, '#push'),
 
-   # <expr>
 
-   (r'<[^<|]+?>(\w*\.\.\.)?', Name.Variable),
 
-   # ${..} $ENV{..}, possibly nested
 
-   (r'(\$\w*\{)([^\}\$]*)?(?:(\$\w*\{)([^\}]+?)(\}))?([^\}]*?)(\})',
 
-    bygroups(Operator, Name.Tag, Operator, Name.Tag, Operator, Name.Tag,
 
-             Operator)),
 
-   # DATA{ ...}
 
-   (r'([A-Z]+\{)(.+?)(\})', bygroups(Operator, Name.Tag, Operator)),
 
-   # URL, git@, ...
 
-   (r'[a-z]+(@|(://))((\\.)|[\w.+-:/\\])+', Name.Attribute),
 
-   # absolute path
 
-   (r'/\w[\w\.\+-/\\]*', Name.Attribute),
 
-   (r'/', Name.Attribute),
 
-   # relative path
 
-   (r'\w[\w\.\+-]*/[\w.+-/\\]*', Name.Attribute),
 
-   # initial A-Z, contains a-z
 
-   (r'[A-Z]((\\.)|[\w.+-])*[a-z]((\\.)|[\w.+-])*', Name.Builtin),
 
-   (r'@?[A-Z][A-Z0-9_]*', Name.Constant),
 
-   (r'[a-z_]((\\;)|(\\ )|[\w.+-])*', Name.Builtin),
 
-   (r'[0-9][0-9\.]*', Number),
 
-   # "string"
 
-   (r'(?s)"(\\"|[^"])*"', String),
 
-   (r'\.\.\.', Name.Variable),
 
-   # <..|..> is different from <expr>
 
-   (r'<', Operator, '#push'),
 
-   (r'>', Operator, '#pop'),
 
-   (r'\n', Whitespace),
 
-   (r'[ \t]+', Whitespace),
 
-   (r'#.*\n', Comment),
 
-   # fallback, for debugging only
 
-   #  (r'[^<>\])\}\|$"# \t\n]+', Name.Exception),
 
- ]
 
- # END pygments tweaks
 
- # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
- logger = logging.getLogger(__name__)
 
- # RE to split multiple command signatures.
 
- sig_end_re = re.compile(r'(?<=[)])\n')
 
- @dataclass
 
- class ObjectEntry:
 
-     docname: str
 
-     objtype: str
 
-     node_id: str
 
-     name: str
 
- class CMakeModule(Directive):
 
-     required_arguments = 1
 
-     optional_arguments = 0
 
-     final_argument_whitespace = True
 
-     option_spec = {'encoding': directives.encoding}
 
-     def __init__(self, *args, **keys):
 
-         self.re_start = re.compile(r'^#\[(?P<eq>=*)\[\.rst:$')
 
-         Directive.__init__(self, *args, **keys)
 
-     def run(self):
 
-         settings = self.state.document.settings
 
-         if not settings.file_insertion_enabled:
 
-             raise self.warning(f'{self.name!r} directive disabled.')
 
-         env = self.state.document.settings.env
 
-         rel_path, path = env.relfn2path(self.arguments[0])
 
-         path = os.path.normpath(path)
 
-         encoding = self.options.get('encoding', settings.input_encoding)
 
-         e_handler = settings.input_encoding_error_handler
 
-         try:
 
-             settings.record_dependencies.add(path)
 
-             f = io.FileInput(source_path=path, encoding=encoding,
 
-                              error_handler=e_handler)
 
-         except UnicodeEncodeError:
 
-             msg = (f'Problems with {self.name!r} directive path:\n'
 
-                    f'Cannot encode input file path {path!r} (wrong locale?).')
 
-             raise self.severe(msg)
 
-         except IOError as error:
 
-             msg = f'Problems with {self.name!r} directive path:\n{error}.'
 
-             raise self.severe(msg)
 
-         raw_lines = f.read().splitlines()
 
-         f.close()
 
-         rst = None
 
-         lines = []
 
-         for line in raw_lines:
 
-             if rst is not None and rst != '#':
 
-                 # Bracket mode: check for end bracket
 
-                 pos = line.find(rst)
 
-                 if pos >= 0:
 
-                     if line[0] == '#':
 
-                         line = ''
 
-                     else:
 
-                         line = line[0:pos]
 
-                     rst = None
 
-             else:
 
-                 # Line mode: check for .rst start (bracket or line)
 
-                 m = self.re_start.match(line)
 
-                 if m:
 
-                     rst = f']{m.group("eq")}]'
 
-                     line = ''
 
-                 elif line == '#.rst:':
 
-                     rst = '#'
 
-                     line = ''
 
-                 elif rst == '#':
 
-                     if line == '#' or line[:2] == '# ':
 
-                         line = line[2:]
 
-                     else:
 
-                         rst = None
 
-                         line = ''
 
-                 elif rst is None:
 
-                     line = ''
 
-             lines.append(line)
 
-         if rst is not None and rst != '#':
 
-             raise self.warning(f'{self.name!r} found unclosed bracket '
 
-                                f'"#[{rst[1:-1]}[.rst:" in {path!r}')
 
-         self.state_machine.insert_input(lines, path)
 
-         return []
 
- class _cmake_index_entry:
 
-     def __init__(self, desc):
 
-         self.desc = desc
 
-     def __call__(self, title, targetid, main='main'):
 
-         return ('pair', f'{self.desc} ; {title}', targetid, main, None)
 
- _cmake_index_objs = {
 
-     'command':    _cmake_index_entry('command'),
 
-     'cpack_gen':  _cmake_index_entry('cpack generator'),
 
-     'envvar':     _cmake_index_entry('envvar'),
 
-     'generator':  _cmake_index_entry('generator'),
 
-     'genex':      _cmake_index_entry('genex'),
 
-     'guide':      _cmake_index_entry('guide'),
 
-     'manual':     _cmake_index_entry('manual'),
 
-     'module':     _cmake_index_entry('module'),
 
-     'policy':     _cmake_index_entry('policy'),
 
-     'prop_cache': _cmake_index_entry('cache property'),
 
-     'prop_dir':   _cmake_index_entry('directory property'),
 
-     'prop_gbl':   _cmake_index_entry('global property'),
 
-     'prop_inst':  _cmake_index_entry('installed file property'),
 
-     'prop_sf':    _cmake_index_entry('source file property'),
 
-     'prop_test':  _cmake_index_entry('test property'),
 
-     'prop_tgt':   _cmake_index_entry('target property'),
 
-     'variable':   _cmake_index_entry('variable'),
 
-     }
 
- class CMakeTransform(Transform):
 
-     # Run this transform early since we insert nodes we want
 
-     # treated as if they were written in the documents.
 
-     default_priority = 210
 
-     def __init__(self, document, startnode):
 
-         Transform.__init__(self, document, startnode)
 
-         self.titles = {}
 
-     def parse_title(self, docname):
 
-         """Parse a document title as the first line starting in [A-Za-z0-9<$]
 
-            or fall back to the document basename if no such line exists.
 
-            The cmake --help-*-list commands also depend on this convention.
 
-            Return the title or False if the document file does not exist.
 
-         """
 
-         settings = self.document.settings
 
-         env = settings.env
 
-         title = self.titles.get(docname)
 
-         if title is None:
 
-             fname = os.path.join(env.srcdir, docname+'.rst')
 
-             try:
 
-                 f = open(fname, 'r', encoding=settings.input_encoding)
 
-             except IOError:
 
-                 title = False
 
-             else:
 
-                 for line in f:
 
-                     if len(line) > 0 and (line[0].isalnum() or
 
-                                           line[0] == '<' or line[0] == '$'):
 
-                         title = line.rstrip()
 
-                         break
 
-                 f.close()
 
-                 if title is None:
 
-                     title = os.path.basename(docname)
 
-             self.titles[docname] = title
 
-         return title
 
-     def apply(self):
 
-         env = self.document.settings.env
 
-         # Treat some documents as cmake domain objects.
 
-         objtype, sep, tail = env.docname.partition('/')
 
-         make_index_entry = _cmake_index_objs.get(objtype)
 
-         if make_index_entry:
 
-             title = self.parse_title(env.docname)
 
-             # Insert the object link target.
 
-             if objtype == 'command':
 
-                 targetname = title.lower()
 
-             elif objtype == 'guide' and not tail.endswith('/index'):
 
-                 targetname = tail
 
-             else:
 
-                 if objtype == 'genex':
 
-                     m = CMakeXRefRole._re_genex.match(title)
 
-                     if m:
 
-                         title = m.group(1)
 
-                 targetname = title
 
-             targetid = f'{objtype}:{targetname}'
 
-             targetnode = nodes.target('', '', ids=[targetid])
 
-             self.document.note_explicit_target(targetnode)
 
-             self.document.insert(0, targetnode)
 
-             # Insert the object index entry.
 
-             indexnode = addnodes.index()
 
-             indexnode['entries'] = [make_index_entry(title, targetid)]
 
-             self.document.insert(0, indexnode)
 
-             # Add to cmake domain object inventory
 
-             domain = cast(CMakeDomain, env.get_domain('cmake'))
 
-             domain.note_object(objtype, targetname, targetid, targetid)
 
- class CMakeObject(ObjectDescription):
 
-     def __init__(self, *args, **kwargs):
 
-         self.targetname = None
 
-         super().__init__(*args, **kwargs)
 
-     def handle_signature(self, sig, signode):
 
-         # called from sphinx.directives.ObjectDescription.run()
 
-         signode += addnodes.desc_name(sig, sig)
 
-         return sig
 
-     def add_target_and_index(self, name, sig, signode):
 
-         if self.objtype == 'command':
 
-             targetname = name.lower()
 
-         elif self.targetname:
 
-             targetname = self.targetname
 
-         else:
 
-             targetname = name
 
-         targetid = f'{self.objtype}:{targetname}'
 
-         if targetid not in self.state.document.ids:
 
-             signode['names'].append(targetid)
 
-             signode['ids'].append(targetid)
 
-             signode['first'] = (not self.names)
 
-             self.state.document.note_explicit_target(signode)
 
-             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:
 
-             self.indexnode['entries'].append(make_index_entry(name, targetid))
 
- class CMakeGenexObject(CMakeObject):
 
-     option_spec = {
 
-         'target': directives.unchanged,
 
-     }
 
-     def handle_signature(self, sig, signode):
 
-         name = super().handle_signature(sig, signode)
 
-         m = CMakeXRefRole._re_genex.match(sig)
 
-         if m:
 
-             name = m.group(1)
 
-         return name
 
-     def run(self):
 
-         target = self.options.get('target')
 
-         if target is not None:
 
-             self.targetname = target
 
-         return super().run()
 
- class CMakeSignatureObject(CMakeObject):
 
-     object_type = 'signature'
 
-     BREAK_ALL = 'all'
 
-     BREAK_SMART = 'smart'
 
-     BREAK_VERBATIM = 'verbatim'
 
-     BREAK_CHOICES = {BREAK_ALL, BREAK_SMART, BREAK_VERBATIM}
 
-     def break_option(argument):
 
-         return directives.choice(argument, CMakeSignatureObject.BREAK_CHOICES)
 
-     option_spec = {
 
-         'target': directives.unchanged,
 
-         'break': break_option,
 
-     }
 
-     def _break_signature_all(sig: str) -> str:
 
-         return ws_re.sub(' ', sig)
 
-     def _break_signature_verbatim(sig: str) -> str:
 
-         lines = [ws_re.sub('\xa0', line.strip()) for line in sig.split('\n')]
 
-         return ' '.join(lines)
 
-     def _break_signature_smart(sig: str) -> str:
 
-         tokens = []
 
-         for line in sig.split('\n'):
 
-             token = ''
 
-             delim = ''
 
-             for c in line.strip():
 
-                 if len(delim) == 0 and ws_re.match(c):
 
-                     if len(token):
 
-                         tokens.append(ws_re.sub('\xa0', token))
 
-                         token = ''
 
-                 else:
 
-                     if c == '[':
 
-                         delim += ']'
 
-                     elif c == '<':
 
-                         delim += '>'
 
-                     elif len(delim) and c == delim[-1]:
 
-                         delim = delim[:-1]
 
-                     token += c
 
-             if len(token):
 
-                 tokens.append(ws_re.sub('\xa0', token))
 
-         return ' '.join(tokens)
 
-     def __init__(self, *args, **kwargs):
 
-         self.targetnames = {}
 
-         self.break_style = CMakeSignatureObject.BREAK_SMART
 
-         super().__init__(*args, **kwargs)
 
-     def get_signatures(self) -> List[str]:
 
-         content = nl_escape_re.sub('', self.arguments[0])
 
-         lines = sig_end_re.split(content)
 
-         if self.break_style == CMakeSignatureObject.BREAK_VERBATIM:
 
-             fixup = CMakeSignatureObject._break_signature_verbatim
 
-         elif self.break_style == CMakeSignatureObject.BREAK_SMART:
 
-             fixup = CMakeSignatureObject._break_signature_smart
 
-         else:
 
-             fixup = CMakeSignatureObject._break_signature_all
 
-         return [fixup(line.strip()) for line in lines]
 
-     def handle_signature(self, sig, signode):
 
-         language = 'cmake'
 
-         classes = ['code', 'cmake', 'highlight']
 
-         node = addnodes.desc_name(sig, '', classes=classes)
 
-         try:
 
-             tokens = Lexer(sig, language, 'short')
 
-         except LexerError as error:
 
-             if self.state.document.settings.report_level > 2:
 
-                 # Silently insert without syntax highlighting.
 
-                 tokens = Lexer(sig, language, 'none')
 
-             else:
 
-                 raise self.warning(error)
 
-         for classes, value in tokens:
 
-             if value == '\xa0':
 
-                 node += nodes.inline(value, value, classes=['nbsp'])
 
-             elif classes:
 
-                 node += nodes.inline(value, value, classes=classes)
 
-             else:
 
-                 node += nodes.Text(value)
 
-         signode.clear()
 
-         signode += node
 
-         return sig
 
-     def add_target_and_index(self, name, sig, signode):
 
-         sig = sig.replace('\xa0', ' ')
 
-         if sig in self.targetnames:
 
-             sigargs = self.targetnames[sig]
 
-         else:
 
-             def extract_keywords(params):
 
-                 for p in params:
 
-                     if p[0].isalpha():
 
-                         yield p
 
-                     else:
 
-                         return
 
-             keywords = extract_keywords(sig.split('(')[1].split())
 
-             sigargs = ' '.join(keywords)
 
-         targetname = sigargs.lower()
 
-         targetid = nodes.make_id(targetname)
 
-         if targetid not in self.state.document.ids:
 
-             signode['names'].append(targetname)
 
-             signode['ids'].append(targetid)
 
-             signode['first'] = (not self.names)
 
-             self.state.document.note_explicit_target(signode)
 
-             # Register the signature as a command object.
 
-             command = sig.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):
 
-         self.break_style = CMakeSignatureObject.BREAK_ALL
 
-         targets = self.options.get('target')
 
-         if targets is not None:
 
-             signatures = self.get_signatures()
 
-             targets = [t.strip() for t in targets.split('\n')]
 
-             for signature, target in zip(signatures, targets):
 
-                 self.targetnames[signature] = target
 
-         self.break_style = (
 
-             self.options.get('break', CMakeSignatureObject.BREAK_SMART))
 
-         return super().run()
 
- class CMakeReferenceRole:
 
-     # See sphinx.util.nodes.explicit_title_re; \x00 escapes '<'.
 
-     _re = re.compile(r'^(.+?)(\s*)(?<!\x00)<(.*?)>$', re.DOTALL)
 
-     @staticmethod
 
-     def _escape_angle_brackets(text: str) -> str:
 
-         # CMake cross-reference targets frequently contain '<' so escape
 
-         # any explicit `<target>` with '<' not preceded by whitespace.
 
-         while True:
 
-             m = CMakeReferenceRole._re.match(text)
 
-             if m and len(m.group(2)) == 0:
 
-                 text = f'{m.group(1)}\x00<{m.group(3)}>'
 
-             else:
 
-                 break
 
-         return text
 
-     def __class_getitem__(cls, parent: Any):
 
-         class Class(parent):
 
-             def __call__(self, name: str, rawtext: str, text: str,
 
-                          *args, **kwargs
 
-                          ) -> Tuple[List[Node], List[system_message]]:
 
-                 text = CMakeReferenceRole._escape_angle_brackets(text)
 
-                 return super().__call__(name, rawtext, text, *args, **kwargs)
 
-         return Class
 
- class CMakeCRefRole(CMakeReferenceRole[ReferenceRole]):
 
-     nodeclass: Type[Element] = nodes.reference
 
-     innernodeclass: Type[TextElement] = nodes.literal
 
-     classes: List[str] = ['cmake', 'literal']
 
-     def run(self) -> Tuple[List[Node], List[system_message]]:
 
-         refnode = self.nodeclass(self.rawtext)
 
-         self.set_source_info(refnode)
 
-         refnode['refid'] = nodes.make_id(self.target)
 
-         refnode += self.innernodeclass(self.rawtext, self.title,
 
-                                        classes=self.classes)
 
-         return [refnode], []
 
- class CMakeXRefRole(CMakeReferenceRole[XRefRole]):
 
-     _re_sub = re.compile(r'^([^()\s]+)\s*\(([^()]*)\)$', re.DOTALL)
 
-     _re_genex = re.compile(r'^\$<([^<>:]+)(:[^<>]+)?>$', re.DOTALL)
 
-     _re_guide = re.compile(r'^([^<>/]+)/([^<>]*)$', re.DOTALL)
 
-     def __call__(self, typ, rawtext, text, *args, **kwargs):
 
-         if typ == 'cmake:command':
 
-             # Translate a CMake command cross-reference of the form:
 
-             #  `command_name(SUB_COMMAND)`
 
-             # to be its own explicit target:
 
-             #  `command_name(SUB_COMMAND) <command_name(SUB_COMMAND)>`
 
-             # so the XRefRole `fix_parens` option does not add more `()`.
 
-             m = CMakeXRefRole._re_sub.match(text)
 
-             if m:
 
-                 text = f'{text} <{text}>'
 
-         elif typ == 'cmake:genex':
 
-             m = CMakeXRefRole._re_genex.match(text)
 
-             if m:
 
-                 text = f'{text} <{m.group(1)}>'
 
-         elif typ == 'cmake:guide':
 
-             m = CMakeXRefRole._re_guide.match(text)
 
-             if m:
 
-                 text = f'{m.group(2)} <{text}>'
 
-         return super().__call__(typ, rawtext, text, *args, **kwargs)
 
-     # We cannot insert index nodes using the result_nodes method
 
-     # because CMakeXRefRole is processed before substitution_reference
 
-     # nodes are evaluated so target nodes (with 'ids' fields) would be
 
-     # duplicated in each evaluated substitution replacement.  The
 
-     # docutils substitution transform does not allow this.  Instead we
 
-     # use our own CMakeXRefTransform below to add index entries after
 
-     # substitutions are completed.
 
-     #
 
-     # def result_nodes(self, document, env, node, is_ref):
 
-     #     pass
 
- class CMakeXRefTransform(Transform):
 
-     # Run this transform early since we insert nodes we want
 
-     # treated as if they were written in the documents, but
 
-     # after the sphinx (210) and docutils (220) substitutions.
 
-     default_priority = 221
 
-     def apply(self):
 
-         env = self.document.settings.env
 
-         # Find CMake cross-reference nodes and add index and target
 
-         # nodes for them.
 
-         for ref in self.document.traverse(addnodes.pending_xref):
 
-             if not ref['refdomain'] == 'cmake':
 
-                 continue
 
-             objtype = ref['reftype']
 
-             make_index_entry = _cmake_index_objs.get(objtype)
 
-             if not make_index_entry:
 
-                 continue
 
-             objname = ref['reftarget']
 
-             if objtype == 'guide' and CMakeXRefRole._re_guide.match(objname):
 
-                 # 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(f'index-{objtype}:{objname}')
 
-             targetid = f'index-{targetnum}-{objtype}:{objname}'
 
-             targetnode = nodes.target('', '', ids=[targetid])
 
-             self.document.note_explicit_target(targetnode)
 
-             indexnode = addnodes.index()
 
-             indexnode['entries'] = [make_index_entry(objname, targetid, '')]
 
-             ref.replace_self([indexnode, targetnode, ref])
 
- class CMakeDomain(Domain):
 
-     """CMake domain."""
 
-     name = 'cmake'
 
-     label = 'CMake'
 
-     object_types = {
 
-         'command':    ObjType('command',    'command'),
 
-         'cpack_gen':  ObjType('cpack_gen',  'cpack_gen'),
 
-         'envvar':     ObjType('envvar',     'envvar'),
 
-         'generator':  ObjType('generator',  'generator'),
 
-         'genex':      ObjType('genex',      'genex'),
 
-         'guide':      ObjType('guide',      'guide'),
 
-         'variable':   ObjType('variable',   'variable'),
 
-         'module':     ObjType('module',     'module'),
 
-         'policy':     ObjType('policy',     'policy'),
 
-         'prop_cache': ObjType('prop_cache', 'prop_cache'),
 
-         'prop_dir':   ObjType('prop_dir',   'prop_dir'),
 
-         'prop_gbl':   ObjType('prop_gbl',   'prop_gbl'),
 
-         'prop_inst':  ObjType('prop_inst',  'prop_inst'),
 
-         'prop_sf':    ObjType('prop_sf',    'prop_sf'),
 
-         'prop_test':  ObjType('prop_test',  'prop_test'),
 
-         'prop_tgt':   ObjType('prop_tgt',   'prop_tgt'),
 
-         'manual':     ObjType('manual',     'manual'),
 
-     }
 
-     directives = {
 
-         'command':    CMakeObject,
 
-         'envvar':     CMakeObject,
 
-         'genex':      CMakeGenexObject,
 
-         'signature':  CMakeSignatureObject,
 
-         'variable':   CMakeObject,
 
-         # Other `object_types` cannot be created except by the `CMakeTransform`
 
-     }
 
-     roles = {
 
-         'cref':       CMakeCRefRole(),
 
-         'command':    CMakeXRefRole(fix_parens=True, lowercase=True),
 
-         'cpack_gen':  CMakeXRefRole(),
 
-         'envvar':     CMakeXRefRole(),
 
-         'generator':  CMakeXRefRole(),
 
-         'genex':      CMakeXRefRole(),
 
-         'guide':      CMakeXRefRole(),
 
-         'variable':   CMakeXRefRole(),
 
-         'module':     CMakeXRefRole(),
 
-         'policy':     CMakeXRefRole(),
 
-         'prop_cache': CMakeXRefRole(),
 
-         'prop_dir':   CMakeXRefRole(),
 
-         'prop_gbl':   CMakeXRefRole(),
 
-         'prop_inst':  CMakeXRefRole(),
 
-         'prop_sf':    CMakeXRefRole(),
 
-         'prop_test':  CMakeXRefRole(),
 
-         'prop_tgt':   CMakeXRefRole(),
 
-         'manual':     CMakeXRefRole(),
 
-     }
 
-     initial_data = {
 
-         'objects': {},  # fullname -> docname, objtype
 
-     }
 
-     def clear_doc(self, docname):
 
-         to_clear = set()
 
-         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 = 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
 
-         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, 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)
 
-     app.add_transform(CMakeTransform)
 
-     app.add_transform(CMakeXRefTransform)
 
-     app.add_domain(CMakeDomain)
 
-     return {"parallel_read_safe": True}
 
 
  |