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

"""Narrow a compilation database to the entries a changed source needs.

``ci/scripts/run-clang-tidy.sh`` checks a changed source through the build
directory's ``compile_commands.json``.  clang-tidy parses the file once per
entry naming it, and a split test contributes one entry per ``EIGEN_TEST_PART``,
or per range of parts ``cmake/EigenTestPartGroups.cmake`` compiles together
-- 17 for ``test/eigensolver_selfadjoint.cpp``, 14 for ``test/array_cwise.cpp``,
at roughly a minute and 3 GB each.  A merge request touching such a file spends
the job's entire timeout on it, and every file after it goes unchecked without
saying so.

Two entries are interchangeable only when they differ solely in which
``-DEIGEN_TEST_PART_<n>`` they define.  ``blas/complexdots.cpp`` is compiled
both into the static library and, with ``-DEIGEN_BLAS_BUILD_DLL``, into the
shared one; code that only the second configuration enables is parsed only by
the second entry.  Entries are therefore grouped by the arguments that affect
parsing, every group keeps a representative, and only inside a group is a part
chosen.

Within a group the part matters exactly where the source asks for it.  A line
inside a ``CALL_SUBTEST_<n>(...)`` invocation or an
``#if defined(EIGEN_TEST_PART_<n>)`` guard exists only when part ``<n>`` is
defined -- the split helper expands the invocation to nothing otherwise.  Every
other line is parsed under any part, because the checks ``.clang-tidy`` enables
are syntactic: they fire on declarations rather than on template
instantiations.  So each added line is mapped to the parts that can compile it,
and the smallest set of entries covering all of them is retained, up to
``MAX_PARTS``.  Whatever that leaves unchecked is named on stdout: reporting a
file clean without having parsed it is the failure this replaces.

Usage: tidy_compile_db.py <database> <source> <outdir> <line-filter>

``<line-filter>`` is the clang-tidy ``--line-filter`` argument that
``scripts/style_common.py`` builds for the same source.  Writes the reduced
database to ``<outdir>/compile_commands.json`` and prints a one-line summary
when it dropped anything.  Exits 0 when the source is in the database, 1 when
it is not, and 2 when the database cannot be read.
"""

import bisect
import json
import os
import re
import shlex
import sys

# An entry costs about a minute and 2 GB, against a 15 minute job budget shared
# with every other changed file, so keep as many entries as a diff needs only up
# to this many.  Beyond it the summary line names the parts left unchecked
# rather than letting the job run into its timeout, which is the silent failure
# this whole reduction exists to remove.
MAX_PARTS = 4

# Arguments that name an output rather than describe the parse. They differ per
# split part (`bdcsvd_1.dir` against `bdcsvd_2.dir`) and would defeat grouping.
_VALUE_ARGS = ("-o", "-MT", "-MF", "-MQ", "-MJ")
_OUTPUT_FLAGS = ("-c", "-MD", "-MMD", "-MP")
_PART_DEFINE = re.compile(r"^-DEIGEN_TEST_PART_([0-9]+)(=.*)?$")
_PART_ARG = re.compile(r"-DEIGEN_TEST_PART_([0-9]+)\b")
_DIRECTIVE = re.compile(r"[ \t]*#[ \t]*(if|ifdef|ifndef|elif|else|endif)\b(.*)")
_PART_MENTION = re.compile(r"(!\s*)?EIGEN_TEST_PART_([0-9]+|ALL)\b")
_DEFINED_CALL = re.compile(r"defined\s*\(\s*([A-Za-z_]\w*)\s*\)")
_DEFINED_BARE = re.compile(r"defined\s+([A-Za-z_]\w*)")
_CALL_SUBTEST = re.compile(r"\bCALL_SUBTEST_([0-9]+)\s*\(")


def arguments_of(entry):
    """The compile command of a database entry, as an argument list."""
    command = entry.get("command")
    if command:
        return shlex.split(command)
    return list(entry.get("arguments", ()))


def parts_of(entry):
    """The ``EIGEN_TEST_PART``s an entry defines, as a frozenset of strings.

    An entry for a range in ``cmake/EigenTestPartGroups.cmake`` defines every
    part of the range; any other entry of a split test defines one.
    """
    return frozenset(_PART_ARG.findall(entry.get("command") or " ".join(entry.get("arguments", ()))))


def configuration_of(entry):
    """The arguments of an entry that affect how the source is parsed.

    Output paths and the part define are excluded, so entries that differ only
    in which part they build compare equal and nothing else does.
    """
    configuration = []
    skip = False
    for argument in arguments_of(entry):
        if skip:
            skip = False
        elif argument in _VALUE_ARGS:
            skip = True
        elif argument in _OUTPUT_FLAGS or (argument.startswith("-o") and len(argument) > 2):
            continue
        elif not _PART_DEFINE.match(argument):
            configuration.append(argument)
    return tuple(configuration)


def entries_for(commands, source):
    """The database entries compiling ``source``, in database order."""
    source = os.path.realpath(source)
    matches = []
    for entry in commands:
        if not isinstance(entry, dict):
            continue
        path = entry.get("file")
        if not path:
            continue
        if not os.path.isabs(path):
            path = os.path.join(entry.get("directory", ""), path)
        if os.path.realpath(path) == source:
            matches.append(entry)
    return matches


def _part_mentions(condition, negated=False):
    """The parts a preprocessor condition names, split by sense.

    ``defined`` is elided first so a mention is negated exactly when a ``!``
    precedes it.  ``EIGEN_TEST_PART_ALL`` is one of the mentions: no entry of a
    split test defines it, so a branch that only it can reach is compiled by no
    part rather than by every part.
    """
    text = _DEFINED_CALL.sub(r"\1", condition)
    text = _DEFINED_BARE.sub(r"\1", text)
    positive, negative = set(), set()
    for mention in _PART_MENTION.finditer(text):
        target = negative if bool(mention.group(1)) != negated else positive
        target.add(mention.group(2))
    return positive, negative


def _branch(positive, negative, universe):
    """The parts under which a branch with these mentions is compiled.

    A positive mention is the binding one: ``defined(EIGEN_TEST_PART_3) && X``
    still needs part 3, and ``defined(EIGEN_TEST_PART_3) || X`` is at least
    compiled under part 3, which is all the caller needs to reach the line.
    """
    if positive:
        return universe & positive
    if negative:
        return universe - negative
    return universe


def guard_constraints(lines, universe):
    """Map each 1-based line number to the parts its ``#if`` guards allow."""
    per_line = [universe] * (len(lines) + 2)
    cumulative = [universe]
    # Parts already claimed by an earlier branch of each open conditional, so
    # that an `#else` can exclude them.
    taken = []
    index = 0
    while index < len(lines):
        first = index
        directive = _DIRECTIVE.match(lines[index])
        condition = ""
        if directive:
            condition = directive.group(2)
            while condition.rstrip().endswith("\\") and index + 1 < len(lines):
                index += 1
                condition = condition.rstrip()[:-1] + lines[index]
        for number in range(first + 1, index + 2):
            per_line[number] = cumulative[-1]
        if directive:
            keyword = directive.group(1)
            if keyword in ("if", "ifdef", "ifndef"):
                positive, negative = _part_mentions(condition, negated=keyword == "ifndef")
                branch = _branch(positive, negative, universe)
                taken.append(branch if positive or negative else frozenset())
                cumulative.append(cumulative[-1] & branch)
            elif keyword in ("elif", "else") and taken:
                cumulative.pop()
                if keyword == "elif":
                    positive, negative = _part_mentions(condition)
                    branch = _branch(positive, negative, universe)
                    taken[-1] = taken[-1] | (branch if positive or negative else frozenset())
                else:
                    branch = universe - taken[-1]
                cumulative.append(cumulative[-1] & branch)
            elif keyword == "endif" and taken:
                taken.pop()
                cumulative.pop()
        index += 1
    return per_line


def call_constraints(text, universe):
    """Map each 1-based line number to the parts its ``CALL_SUBTEST`` allows.

    A line can carry more than one invocation, in which case either part
    compiles part of it.
    """
    starts = [0] + [newline.end() for newline in re.finditer(r"\n", text)]
    per_line = {}
    for call in _CALL_SUBTEST.finditer(text):
        depth, offset = 1, call.end()
        while offset < len(text) and depth:
            if text[offset] == "(":
                depth += 1
            elif text[offset] == ")":
                depth -= 1
            offset += 1
        first = bisect.bisect_right(starts, call.start())
        last = bisect.bisect_right(starts, offset - 1)
        allowed = universe & {call.group(1)}
        for number in range(first, last + 1):
            per_line[number] = per_line.get(number, frozenset()) | allowed
    return per_line


def required_parts(text, lines, universe):
    """The parts that can compile each of ``lines``, as a list of sets."""
    source_lines = text.splitlines()
    guards = guard_constraints(source_lines, universe)
    calls = call_constraints(text, universe)
    return [guards[number] & calls.get(number, universe)
            for number in lines if number < len(guards)]


def select_entries(required, entries, limit=MAX_PARTS):
    """The fewest entries whose parts cover ``required``, capped at ``limit``.

    ``entries`` holds the parts each entry defines, in database order.  Returns
    the positions chosen in ``entries`` and the requirements the cap left
    uncovered.  Ties go to the entry the database lists first, which is what a
    diff that names no part at all gets.
    """
    chosen = []
    uncovered = [need for need in required if need]
    while uncovered and len(chosen) < limit:
        counts = [sum(1 for need in uncovered if need & members) for members in entries]
        best = max(range(len(entries)), key=lambda position: (counts[position], -position))
        chosen.append(best)
        uncovered = [need for need in uncovered if not need & entries[best]]
    return chosen, uncovered


def reduce_entries(matches, text, lines):
    """The entries of ``matches`` needed to parse ``lines`` of ``text``.

    Returns the retained entries in database order, the parts the cap left out,
    and how many added lines no configured part compiles at all.
    """
    groups = {}
    for index, entry in enumerate(matches):
        groups.setdefault(configuration_of(entry), []).append(index)

    keep, skipped, unreachable = set(), set(), 0
    for group in groups.values():
        parts = [parts_of(matches[index]) for index in group]
        universe = frozenset().union(*parts)
        if len(group) == 1 or not all(parts) or sum(map(len, parts)) != len(universe):
            # Not one configuration split into disjoint parts: every entry here
            # parses something the others do not.
            keep.update(group)
            continue
        required = required_parts(text, lines, universe)
        unreachable = max(unreachable, sum(1 for need in required if not need))
        chosen, uncovered = select_entries(required, parts)
        skipped |= {part for need in uncovered for part in need}
        keep.update(group[position] for position in chosen)
    return [matches[index] for index in sorted(keep)], sorted(skipped, key=int), unreachable


def added_lines(line_filter):
    """The line numbers a clang-tidy ``--line-filter`` argument marks."""
    lines = []
    for item in json.loads(line_filter or "[]"):
        for first, last in item.get("lines", ()):
            lines.extend(range(first, last + 1))
    return sorted(set(lines))


def summarize(matches, keep, skipped, unreachable):
    """A one-line report of what the reduction dropped, or an empty string.

    What the reduction leaves out is stated rather than implied: a job that
    prints "all clean" for a file it never parsed is the failure this replaces.
    """
    if len(keep) == len(matches) and not skipped and not unreachable:
        return ""
    parts = sorted({part for entry in keep for part in parts_of(entry)}, key=int)
    if not parts:
        checking = "%d entries" % len(keep)
    else:
        checking = "part%s %s" % ("" if len(parts) == 1 else "s", ", ".join(parts))
    report = "(%d compilation-database entries; checking %s" % (len(matches), checking)
    if skipped:
        report += "; NOT CHECKED: added lines also need part%s %s" % (
            "" if len(skipped) == 1 else "s", ", ".join(skipped))
    if unreachable:
        report += "; NOT CHECKED: %d added line(s) belong to no configured part" % unreachable
    return report + ")"


def main(argv):
    database, source, outdir, line_filter = argv[1:5]
    try:
        with open(database, encoding="utf-8") as handle:
            commands = json.load(handle)
    except (OSError, ValueError) as error:
        print("ERROR: could not read %s: %s" % (database, error), file=sys.stderr)
        return 2
    if not isinstance(commands, list):
        print("ERROR: %s does not contain a JSON array" % database, file=sys.stderr)
        return 2

    matches = entries_for(commands, source)
    if not matches:
        return 1

    with open(source, encoding="utf-8", errors="replace") as handle:
        text = handle.read()
    keep, skipped, unreachable = reduce_entries(matches, text, added_lines(line_filter))

    os.makedirs(outdir, exist_ok=True)
    with open(os.path.join(outdir, "compile_commands.json"), "w", encoding="utf-8") as handle:
        json.dump(keep, handle)
    report = summarize(matches, keep, skipped, unreachable)
    if report:
        print(report)
    return 0


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