#!/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.

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>`` is enough to parse
any file in the C++14 trees, 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).
CHECKED_TREES = ("Eigen/", "unsupported/Eigen/", "test/", "unsupported/test/", "failtest/", "blas/", "lapack/")
SRC_TREES = ("Eigen/src/", "unsupported/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 ([^ "]+)')
TIMEOUT_SECONDS = 30


def module_of(rel_path):
    """Return the ``Eigen/src/<Module>`` name owning ``rel_path``, else None."""
    m = re.match(r"^(?:unsupported/)?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 = ("unsupported/Eigen/" if rel_path.startswith("unsupported/") else "Eigen/") + module
    return fallback if os.path.isfile(os.path.join(root, fallback)) else None


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."""
    args = ["-std=c++14", "-I" + root]
    if rel_path.startswith(("test/", "unsupported/test/")):
        args += ["-I" + os.path.join(root, "test")]
    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:
            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")
    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.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())
