# 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

    # This helper supports docutils < 0.18, which is missing 'findall',
    # and docutils == 0.18.0, which is missing 'traverse'.
    def _document_findall_as_list(self, condition):
        if hasattr(self.document, 'findall'):
            # Fully iterate into a list so the caller can grow 'self.document'
            # while iterating.
            return list(self.document.findall(condition))

        # Fallback to 'traverse' on old docutils, which returns a list.
        return self.document.traverse(condition)

    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_findall_as_list(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 -> ObjectEntry
    }

    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 merge_domaindata(self, docnames, otherdata):
        """Merge domaindata from the workers/chunks when they return.

        Called once per parallelization chunk.
        Only used when sphinx is run in parallel mode.

        :param docnames: a Set of the docnames that are part of the current
                         chunk to merge
        :param otherdata: the partial data calculated by the current chunk
        """
        for refname, obj in otherdata['objects'].items():
            if obj.docname in docnames:
                self.data['objects'][refname] = obj

    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, refname, 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}
