| # -*- coding: utf-8 -*- | |
| """Sphinx extension for llvm-project checks/lints. | |
| Enable by adding "llvm_sphinx.checks" to the sphinx `extensions` list. | |
| """ | |
| import sys | |
| from typing import Dict, List | |
| from llvm_sphinx.help import venv_help | |
| try: | |
| from sphinx.application import Sphinx | |
| from sphinx.environment import BuildEnvironment | |
| from sphinx.util import logging | |
| from sphinx.errors import ExtensionError | |
| except ImportError as err: | |
| print(venv_help(err), file=sys.stderr) | |
| raise | |
| __version__ = "1.0" | |
| logger = logging.getLogger("llvm_sphinx.ext.checks") | |
| def setup(app: Sphinx) -> Dict[str, object]: | |
| app.connect("env-updated", check_env) | |
| return { | |
| "version": __version__, | |
| "parallel_read_safe": True, | |
| "parallel_write_safe": True, | |
| } | |
| def check_env(app: Sphinx, env: BuildEnvironment) -> None: | |
| toc_parents: Dict[str, List[str]] = {} | |
| for parent, children in env.toctree_includes.items(): | |
| for child in children: | |
| toc_parents.setdefault(child, []).append(parent) | |
| for doc, parents in sorted(toc_parents.items()): | |
| if len(parents) > 1: | |
| # sphinx considers this an `info` only, and silently picks one | |
| # parent arbitrarily. We upgrade this to an `error` to ensure | |
| # we don't accumulate a growing list of offending toctrees. | |
| logger.error( | |
| "document is referenced in multiple toctrees: %s", | |
| parents, | |
| location=doc, | |
| ) |