#!/usr/bin/env bash
# tooling/godot-parse-sweep — open every project .gd and fail on any that won't parse.
#
# Complements `godot-cold-parse`, which does NOT cover this. That script only
# ever sees scripts on the STARTUP path (autoloads + the main scene chain) —
# correct for the registration-ORDER bug it was built for, far narrower than
# its name implies. Verified 2026-07-27 by breaking a non-startup UI script
# and a test file in turn: cold-parse reported "clean", exit 0, for both.
#
# Division of labour, deliberate:
#   godot-cold-parse   — cold-cache STARTUP ordering (class_name/autoload race)
#   godot-parse-sweep  — does every file in the project parse at all
#
# The GDScript half (client/tools/parse_sweep.gd) only opens files; it makes no
# verdict, because no Godot API reports GDScript parse failure reliably (see
# that file's header — one segfaults, one false-positives 150/226, and plain
# load() returns non-null for a broken script). The engine's own stderr is the
# only honest signal, so the verdict is made here by scraping it.
#
# Exit 0 + "clean" if every script parsed. Exit 1 + the offending lines if not.
set -euo pipefail

REPO_ROOT="$(git rev-parse --show-toplevel)"

set +e
RAW=$(godot --headless --path "$REPO_ROOT/client" -s res://tools/parse_sweep.gd 2>&1)
GODOT_EXIT=$?
set -e

if [ "$GODOT_EXIT" -ne 0 ]; then
    echo "godot-parse-sweep: godot itself exited $GODOT_EXIT — not a parse verdict" >&2
    printf '%s\n' "$RAW" | tail -20 >&2
    exit "$GODOT_EXIT"
fi

# The sweep must actually have run. Without this, a future change that breaks
# the walk (or renames the script) would produce zero error lines and read as
# a clean sweep — the same false-green shape this tool exists to close.
if ! printf '%s\n' "$RAW" | grep -q '^parse-sweep: opened'; then
    echo "godot-parse-sweep: the sweep did not report completion — no verdict possible" >&2
    printf '%s\n' "$RAW" | tail -20 >&2
    exit 1
fi
SUMMARY=$(printf '%s\n' "$RAW" | grep '^parse-sweep: opened')

# NOTE: unlike godot-cold-parse, "Cannot infer the type" is NOT filtered here.
# That filter is why cold-parse stayed silent about tests/util/scene_helper.gd,
# which genuinely does not parse — the suppressed class was hiding a real
# failure, not noise.
MATCHES=$(printf '%s\n' "$RAW" \
  | grep -E 'Parse Error|Failed to load script' \
  | grep -v "Failed loading resource: res://assets" || true)

if [ -n "$MATCHES" ]; then
    echo "PARSE SWEEP FAILED — at least one script does not parse." >&2
    printf '%s\n' "$MATCHES" | head -40 >&2
    echo "" >&2
    echo "  ${SUMMARY}" >&2
    echo "  An unparseable file cannot run. If it is a test suite, it did not" >&2
    echo "  execute, and any pass count reported elsewhere excludes it." >&2
    exit 1
fi

echo "godot-parse-sweep: clean — ${SUMMARY#parse-sweep: }"
