Repository: astral-sh/ruff
File: scripts/conformance.py (Python)

Code before:
        )

        grouped = GroupedDiagnostics(
            key=key,
            sources={d.source for d in group},
            old=old_group,
            new=new_group,
            expected=expected_group,
        )
        grouped_diagnostics.append(grouped)

    return grouped_diagnostics


def compute_stats(
    grouped_diagnostics: list[GroupedDiagnostics],
    source: Source,
) -> Statistics:
    if source == source.EXPECTED:
        num_errors = sum(1 for g in grouped_diagnostics if source.EXPECTED in g.sources)
        return Statistics(
            true_positives=num_errors, false_positives=0, false_negatives=0
        )

    def increment(statistics: Statistics, grouped: GroupedDiagnostics) -> Statistics:
        classification = grouped.classify(source)
        if classification == Classification.TRUE_POSITIVE:
            statistics.true_positives += 1
        elif classification == Classification.FALSE_POSITIVE:
            statistics.false_positives += 1
        elif classification == Classification.FALSE_NEGATIVE:
            statistics.false_negatives += 1

        statistics.total_diagnostics += len(grouped.diagnostics_by_source(source))
        return statistics

    grouped_diagnostics = [diag for diag in grouped_diagnostics if not diag.optional]

    return reduce(increment, grouped_diagnostics, Statistics())


def render_grouped_diagnostics(
    grouped: list[GroupedDiagnostics],
    *,
    changed_only: bool = True,
    format: Literal["diff", "github"] = "diff",
) -> str:
    if changed_only:
        grouped = [
            diag for diag in grouped if diag.change in (Change.ADDED, Change.REMOVED)
        ]

Review comment (refactor):
GitHub doesn't really allow me to comment on that line but you could simplify your code a good amount by removing `None` from `old`, `new` and `expected`. Unless I miss a place where you create a `GroupedDiagnostics` instance where those fields are `None`

Code after:
            "--output-format=gitlab",
            "--exit-zero",
            *map(str, test_files),
        ],
        capture_output=True,
        text=True,
        check=True,
        timeout=15,
    )

    if process.returncode != 0:
        print(process.stderr)
        raise RuntimeError(f"ty check failed with exit code {process.returncode}")

    return [
        Diagnostic.from_gitlab_output(dct, source=source)
        for dct in json.loads(process.stdout)
        if dct["severity"] == "major"
    ]


def group_diagnostics_by_key(
    old: list[Diagnostic],
    new: list[Diagnostic],
    expected: list[Diagnostic],
) -> list[GroupedDiagnostics]:
    # propagate tags from expected diagnostics to old and new diagnostics
    tagged_lines = {
        (d.location.path.name, d.location.positions.begin.line): d.tag
        for d in expected
        if d.tag is not None
    }

    for diag in chain(old, new):
        diag.tag = tagged_lines.get(
            (diag.location.path.name, diag.location.positions.begin.line), None
        )

    diagnostics = [
        *old,
        *new,
        *expected,
    ]

    diagnostics = sorted(diagnostics, key=attrgetter("key"))
    grouped_diagnostics = []
    for key, group in groupby(diagnostics, key=attrgetter("key")):
        old_diagnostics: list[Diagnostic] = []
        new_diagnostics: list[Diagnostic] = []
        expected_diagnostics: list[Diagnostic] = []
        sources: set[Source] = set()