#!/usr/bin/env python3
# SPDX-FileCopyrightText: The Eigen Authors
# SPDX-License-Identifier: MPL-2.0

"""Run clang-tidy on the lines an edit added.

``.clang-tidy`` is the authority on the conventions clang-tidy can express, so
rather than restate them this hook runs the real thing on the edited file and
reports only diagnostics on added lines (``--line-filter``).  Without that
restriction the checks would be unusable interactively: ``Eigen/src`` holds
~4100 ``typedef``s, and whole-file output buries the two lines just written.

Editing a header under ``Eigen/src`` cannot be compiled directly — the module's
``InternalHeaderCheck.h`` ``#error``s out — so a driver includes the module
umbrella first and then the edited header.  The umbrella name is read from the
``#error "Please include <X>"`` directive.  This mirrors what
``ci/scripts/run-clang-tidy.sh`` does for merge requests.  Including the edited
header explicitly also covers a new header that the umbrella does not export
yet.  If the umbrella includes the header only when an ``EIGEN_USE_*`` macro is
defined, as ``Eigen/LU`` does ``PartialPivLU_LAPACKE.h``, the driver defines it
first; ``--gate-macros`` prints those macros for the CI script.

LLVM's ``clang-tidy-diff.py`` cannot replace this routing: it invokes changed
headers directly, which trips Eigen's internal-header guard, and a PostToolUse
payload is not a unified diff.

No compilation database is required: ``-std=c++14 -I<repo>`` parses any file
in the C++14 trees, with ``test/`` added for the test sources and
``contrib/`` for the contrib ones, which keeps the hook usable in a
fresh checkout with no build directory.

The hook fails open — a missing clang-tidy, an unparsable file, a translation
unit that does not compile, or any unexpected error exits 0 rather than blocking
the harness. Only real findings on added lines block.
"""

import argparse
import json
import os
import re
import shutil
import subprocess
import sys
import tempfile

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from style_common import (REPO_ROOT, diff_added_lines, hook_edit_snippets,  # noqa: E402
                          hook_post_image_and_added, is_cxx_path, line_filter_json)

# Parsing an umbrella costs about a second, so keep the hook off trees whose
# conventions these checks do not describe (bench/, demos/, doc/ examples).
# unsupported/Eigen/ is kept for the legacy umbrella shims that still live
# there; the implementation tree itself is contrib/, which has no shims and
# so needs the src-tree rules.
CHECKED_TREES = ("Eigen/", "contrib/Eigen/", "unsupported/Eigen/", "test/", "contrib/test/", "failtest/", "blas/",
                 "lapack/")
SRC_TREES = ("Eigen/src/", "contrib/Eigen/src/")
# Modules whose umbrella needs a third-party header we cannot assume is present.
EXTERNAL_DEP_MODULES = ("AccelerateSupport", "CholmodSupport", "KLUSupport", "MetisSupport",
                        "PaStiXSupport", "PardisoSupport", "SPQRSupport", "SuperLUSupport",
                        "UmfPackSupport")
PLEASE_INCLUDE = re.compile(r'"Please include ([^ "]+)')
ISA_BACKEND = re.compile(r"/arch/(?!Default/)[^/]+/")
GATE_CONDITION = re.compile(r"#\s*(?:ifdef\s+(EIGEN_USE_\w+)|if\s+defined\s*\(\s*(EIGEN_USE_\w+)\s*\))$")
TIMEOUT_SECONDS = 30


def module_of(rel_path):
    """Return the ``Eigen/src/<Module>`` name owning ``rel_path``, else None."""
    m = re.match(r"^(?:contrib/)?Eigen/src/([^/]+)/", rel_path)
    return m.group(1) if m else None


def umbrella_for(rel_path, root=REPO_ROOT):
    """Return the module umbrella to include when linting a src-tree header.

    The source of truth is the ``#error "Please include <X>"`` directive on the
    header itself or on its sibling ``InternalHeaderCheck.h``; the
    ``<root>/<Module>`` heuristic covers arch-specific backends nested deeper
    than the module root, which carry no directive of their own.
    """
    module = module_of(rel_path)
    if module is None or module in EXTERNAL_DEP_MODULES:
        return None
    for candidate in (rel_path, os.path.join(os.path.dirname(rel_path), "InternalHeaderCheck.h")):
        try:
            with open(os.path.join(root, candidate), encoding="utf-8", errors="replace") as handle:
                hit = PLEASE_INCLUDE.search(handle.read())
        except OSError:
            continue
        if hit and os.path.isfile(os.path.join(root, hit.group(1))):
            return hit.group(1)
    fallback = ("contrib/Eigen/" if rel_path.startswith("contrib/") else "Eigen/") + module
    return fallback if os.path.isfile(os.path.join(root, fallback)) else None


def gate_macros(umbrella, rel_path, root=REPO_ROOT):
    """Return the ``EIGEN_USE_*`` macros ``umbrella`` needs to include ``rel_path``.

    ``Eigen/LU`` includes ``PartialPivLU_LAPACKE.h``, and the
    ``lapacke_helpers.h`` that declares its ``lapack_int``, only inside
    ``#ifdef EIGEN_USE_LAPACKE``; without the macro the header does not
    compile.  Only the plain forms ``#ifdef EIGEN_USE_X`` and ``#if
    defined(EIGEN_USE_X)`` count, and only when the include is in the ``#if``
    branch, not an ``#elif`` or ``#else``.
    """
    target = os.path.relpath(rel_path, os.path.dirname(umbrella))
    try:
        with open(os.path.join(root, umbrella), encoding="utf-8", errors="replace") as handle:
            lines = handle.read().splitlines()
    except OSError:
        return []
    stack = []
    for line in lines:
        directive = re.sub(r"/\*.*?\*/|//.*", "", line).strip()
        if re.match(r"#\s*if", directive):
            gate = GATE_CONDITION.match(directive)
            stack.append(gate and (gate.group(1) or gate.group(2)))
        elif re.match(r"#\s*(elif|else)", directive) and stack:
            stack[-1] = None
        elif re.match(r"#\s*endif", directive) and stack:
            stack.pop()
        else:
            include = re.match(r'#\s*include\s*"([^"]+)"', directive)
            if include and os.path.normpath(include.group(1)) == target:
                return [macro for macro in stack if macro]
    return []


def cuda_include_dir(default_root="/usr/local/cuda"):
    """Include directory of an installed CUDA toolkit, or None if there is none.

    Every header in the GPU module that includes ``GpuSupport.h`` reaches
    ``<cuda_runtime.h>``. Without it clang drops the include and every
    declaration behind it, leaving an AST too truncated to check the module
    against; with it the header is checked like any other.

    ``default_root`` is where the toolkit is looked for once the environment
    names none; a test passes a directory that holds no toolkit so the
    negative case does not depend on the host.
    """
    roots = [os.environ.get(name) for name in ("CUDAToolkit_ROOT", "CUDA_HOME", "CUDA_PATH")]
    roots.append(default_root)
    for root in roots:
        if root and os.path.isfile(os.path.join(root, "include", "cuda_runtime.h")):
            return os.path.join(root, "include")
    return None


def compile_args(rel_path, root=REPO_ROOT):
    """Include paths sufficient to parse ``rel_path`` without a compile database.

    Test sources reach ``main.h`` through ``test/``; the contrib ones also
    include their module umbrellas as ``<Eigen/Tensor>``, which resolves only
    with ``contrib/`` on the path.  These are the directories
    ``contrib/test/CMakeLists.txt`` adds for them.
    """
    args = ["-std=c++14", "-I" + root]
    if rel_path.startswith(("test/", "contrib/test/")):
        args += ["-I" + os.path.join(root, "test")]
    if rel_path.startswith("contrib/test/"):
        args += ["-I" + os.path.join(root, "contrib")]
    cuda = cuda_include_dir()
    if cuda:
        args += ["-isystem", cuda]
    return args


def tidy_target(rel_path, tmpdir, root=REPO_ROOT):
    """Return the path clang-tidy should be pointed at, or None to skip.

    Source files are linted directly; src-tree headers go through a generated
    driver that includes their module umbrella followed by the header itself.
    """
    if rel_path.startswith(SRC_TREES) or not os.path.splitext(rel_path)[1]:
        include = umbrella_for(rel_path, root) if rel_path.startswith(SRC_TREES) else rel_path
        if include is None:
            return None
        driver = os.path.join(tmpdir, "tidy_driver_" + rel_path.replace("/", "_") + ".cpp")
        with open(driver, "w", encoding="utf-8") as handle:
            # Skip arch/<ISA>/ headers, as run-clang-tidy.sh does: their macro
            # (EIGEN_USE_SYCL) needs a toolchain this host does not have.
            if rel_path.startswith(SRC_TREES) and not ISA_BACKEND.search(rel_path):
                for macro in gate_macros(include, rel_path, root):
                    handle.write("#define %s\n" % macro)
            handle.write("#include <%s>\n" % include)
            if rel_path.startswith(SRC_TREES):
                handle.write("#include <%s>\n" % rel_path)
        return driver
    if os.path.splitext(rel_path)[1].lower() in (".cpp", ".cc", ".cxx"):
        return os.path.join(root, rel_path)
    return None  # a .h outside the src trees has no reliable standalone TU


def run_clang_tidy(per_file, root=REPO_ROOT, tidy=None):
    """Lint the added lines of each file in ``per_file``.

    Returns (diagnostics, skipped): ``diagnostics`` are clang-tidy's warning
    lines, ``skipped`` a list of (path, reason) for files that could not be
    checked.  A file whose translation unit does not compile is one of those:
    clang-tidy emits no useful check output for it, and reporting it as clean
    would claim a check that never ran.
    """
    tidy = shutil.which(tidy or "clang-tidy")
    if tidy is None:
        return None, []
    diagnostics, skipped = [], []
    with tempfile.TemporaryDirectory() as tmpdir:
        for rel_path, added in sorted(per_file.items()):
            if not added or not is_cxx_path(rel_path) or not rel_path.startswith(CHECKED_TREES):
                continue
            target = tidy_target(rel_path, tmpdir, root)
            if target is None:
                skipped.append((rel_path, "no standalone translation unit"))
                continue
            cmd = [tidy, "--quiet",
                   "--config-file=" + os.path.join(root, ".clang-tidy"),
                   "--header-filter=" + re.escape(rel_path),
                   "--line-filter=" + line_filter_json({rel_path: added}),
                   target, "--"] + compile_args(rel_path, root)
            try:
                done = subprocess.run(cmd, capture_output=True, text=True, timeout=TIMEOUT_SECONDS)
            except OSError:
                skipped.append((rel_path, "clang-tidy could not be run"))
                continue
            except subprocess.TimeoutExpired:
                skipped.append((rel_path, "clang-tidy timed out after %ds" % TIMEOUT_SECONDS))
                continue
            broke = False
            output = "\n".join(part for part in (done.stdout, done.stderr) if part)
            for line in output.splitlines():
                if not re.search(r": (warning|error): ", line):
                    continue
                if "clang-diagnostic-error" in line or ": error: " in line:
                    broke = True
                    continue
                diagnostics.append(re.sub(r"^" + re.escape(root) + "/", "", line))
            if broke:
                skipped.append((rel_path, "translation unit did not compile"))
            elif done.returncode != 0:
                skipped.append((rel_path, "clang-tidy failed"))
    return diagnostics, skipped


def run_hook_mode(tidy=None):
    try:
        payload = json.load(sys.stdin)
    except Exception:
        return 0
    rel_path, snippets = hook_edit_snippets(payload)
    if rel_path is None or not is_cxx_path(rel_path) or not rel_path.startswith(CHECKED_TREES):
        return 0
    _, added, exact = hook_post_image_and_added(payload, rel_path, snippets)
    if not exact or not added:
        # Without real line numbers a line filter would point at the wrong
        # lines; silence beats a misplaced diagnostic.
        return 0
    diagnostics, skipped = run_clang_tidy({rel_path: added}, tidy=tidy)
    if not diagnostics:
        broken = [reason for path, reason in (skipped or []) if reason == "translation unit did not compile"]
        if broken:
            # A header edited mid-refactor routinely fails to parse on its own,
            # so show the user a non-blocking notice rather than feeding Claude
            # an error with no finding to act on.
            message = "clang-tidy (%s): not checked — the translation unit did not compile." % rel_path
            sys.stdout.write(json.dumps({"systemMessage": message}) + "\n")
            return 0
        return 0
    sys.stderr.write("clang-tidy (%s) — added lines only:\n" % rel_path)
    for line in diagnostics[:8]:
        sys.stderr.write("  %s\n" % line)
    if len(diagnostics) > 8:
        sys.stderr.write("  ... and %d more\n" % (len(diagnostics) - 8))
    sys.stderr.write("Advisory: these are Eigen conventions from .clang-tidy; keep a flagged construct "
                     "only if it is justified, and say why at the construct.\n")
    return 2


def run_diff_mode(base, tidy=None):
    per_file = diff_added_lines(base)
    diagnostics, skipped = run_clang_tidy(per_file, tidy=tidy)
    if diagnostics is None:
        sys.stderr.write("%s not found; skipping.\n" % (tidy or "clang-tidy"))
        return 0
    for line in diagnostics:
        print(line)
    for rel_path, reason in skipped:
        print("%s: not checked (%s)" % (rel_path, reason))
    if diagnostics:
        print("\n%d clang-tidy finding(s) on added lines." % len(diagnostics))
    return 1 if diagnostics else 0


def main():
    parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    mode = parser.add_mutually_exclusive_group(required=True)
    mode.add_argument("--diff", metavar="BASE", help="lint lines added since merge-base(BASE, HEAD)")
    mode.add_argument("--claude-hook", action="store_true", help="run as a Claude Code PostToolUse hook")
    mode.add_argument("--gate-macros", nargs=2, metavar=("UMBRELLA", "HEADER"),
                      help="print the EIGEN_USE_* macros UMBRELLA needs defined to include HEADER, one per line")
    parser.add_argument("-b", "--binary", metavar="CLANG_TIDY",
                        help="clang-tidy executable to use, as a PATH name or a full path "
                             "(e.g. clang-tidy-19 from LLVM's version-suffixed packages); "
                             "default: clang-tidy")
    args = parser.parse_args()
    if args.gate_macros:
        for macro in gate_macros(*args.gate_macros):
            print(macro)
        return 0
    if args.claude_hook:
        try:
            return run_hook_mode(tidy=args.binary)
        except Exception:
            return 0  # a broken hook must not block the harness
    if args.binary and shutil.which(args.binary) is None:
        # In diff mode an explicitly named binary that is absent is a usage
        # error; silently skipping would claim a check that never ran.  Hook
        # mode above keeps the fail-open contract instead.
        parser.error("--binary %s not found" % args.binary)
    return run_diff_mode(args.diff, tidy=args.binary)


if __name__ == "__main__":
    sys.exit(main())
