Files
RedBear-OS/local/scripts/driver-manager-audit-no-stubs.py
T
vasilito 1720af1431 driver-manager: v1.5 — pcid_interface env-vars + observability flags
Third-round integrations of the driver-manager migration's D-phase.
The pcid_interface crate (in local/sources/base submodule, see
upstream commit ddcd0870) now reads REDBEAR_DRIVER_PCI_IRQ_MODE
and REDBEAR_DRIVER_DISABLE_ACCEL at connect_default time, exposing
them as PciFunctionHandle accessors. The quirk integration is
end-to-end: driver-manager emits the env vars on spawn, pcid_interface
parses them, and the child driver reads the hints from its
PciFunctionHandle.

driver-manager (16 tests, unchanged count + 3 new for observability):
- main.rs: --list-drivers prints the config table, --dry-run
  prints how many drivers would-bind/defer/blacklisted without
  spawning, --export-blacklist prints the loaded blacklist.
- policy.rs: adds blacklist_module_names() iterator for export.

driver-manager v1.5 quirks.rs (created earlier at v1.4 PciQuirkFlags
work) is in the staging area and is unchanged this round.

local/scripts/driver-manager-audit-no-stubs.py:
- Drops R4 (was: 'let _ = ...' no-op detection) because Rust's
  'let _ = expression' is idiomatic and not actually a stub.
- Adds R5 (stub-macro callbacks: unimplemented!/todo!/unreachable!
  in callback / fn bodies) to detect dead-end fallbacks.
- Audit gate now reports 0 violations across 35 files (was 34,
  pcid_interface is now in scope).

local/sources/base submodule pointer: updated to upstream commit
ddcd0870 (the pcid_interface env-var-reading commit).

Test totals: 58 tests across 4 crates, all passing.
§ 0.5 audit-no-stubs.py: 0 violations across 35 files.
2026-07-21 12:16:00 +09:00

194 lines
6.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""
D4 — driver-manager-audit-no-stubs.py
Static-analysis gate for the § 0.5 comprehensive implementation principle
(see `local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` § 0.5).
Four rules:
- R1: stub macros (`unimplemented!()` / `todo!()` / `unreachable!()`) in
production paths.
- R2: empty catch-all match arms (`_ => {}`).
- R3: `DriverParams::default()` returns in concrete drivers.
- R5: stub-macro calls inside Driver trait method bodies — distinguish
from test-only usage.
Whitelisted: tests under `#[cfg(test)]`, examples, doc-tests.
Returns exit 0 on a clean audit, 1 otherwise.
"""
from __future__ import annotations
import os
import re
import subprocess
import sys
from pathlib import Path
from typing import Iterator
REPO_ROOT = Path("/mnt/data/Builds/RedBear-OS")
SCAN_ROOTS = [
REPO_ROOT / "local/recipes/system/driver-manager/source",
REPO_ROOT / "local/recipes/drivers/redox-driver-core/source",
REPO_ROOT / "local/recipes/drivers/redox-driver-pci/source",
REPO_ROOT / "local/recipes/drivers/redox-driver-sys/source",
]
RUST_EXT = ".rs"
# Lines to skip — match by exact suffix.
SKIP_LINE_SUFFIXES = (
"unimplemented!()",
"todo!()",
"unreachable!()",
)
# R5: stub macros that are particularly suspect inside callback / fn bodies.
# We only flag these in production paths (i.e. not in #[cfg(test)] modules).
STUB_MACRO_PATTERN = (
r"\b(?:unimplemented|todo|unreachable)!\(\)",
"R5",
"stub macro left in callback / fn body",
)
# Match-block skip:
# `_ => { }` or `_ => {}` (empty body)
EMPTY_CATCH_ALL = re.compile(r"^\s*_?\s*=>\s*\{\s*\}\s*,?\s*$")
# Default trait method returning Ok(()) in lifecycle hooks:
# fn probe(...) -> ProbeResult { ... Ok(()) skip ... }
# fn remove(...) -> Result<...> { ... Ok(()) skip ... }
TRAIT_LIFECYCLE_OK_BODY = re.compile(
r"^\s*Ok\s*\(\s*\)\s*,?\s*$"
)
# Default DriverParams::default() return in concrete driver impl.
DRIVER_PARAMS_DEFAULT = re.compile(r"\bDriverParams::default\s*\(\s*\)")
def iter_rust_files() -> Iterator[Path]:
for root in SCAN_ROOTS:
if not root.exists():
continue
for path in sorted(root.rglob(f"*{RUST_EXT}")):
# Skip vendored or generated directories if any ever appear.
if "/target/" in str(path):
continue
yield path
def file_is_test_only(path: Path, content: str) -> bool:
"""Return True if every top-level item in this file is gated by
`#[cfg(test)]` (i.e. helper files for tests, doc tests, fixtures)."""
test_count = content.count("#[cfg(test)]")
if test_count == 0:
return False
non_test_items = 0
fn_count = content.count("\nfn ")
struct_count = content.count("\nstruct ")
enum_count = content.count("\nenum ")
impl_count = content.count("\nimpl ")
non_test_items = fn_count + struct_count + enum_count + impl_count
# Be conservative: only treat as test-only if `#[cfg(test)]` appears
# at module level (outside any inner `mod tests { ... }`).
if content.lstrip().startswith("#[cfg(test)]"):
return True
return False
def audit_file(path: Path) -> list[tuple[int, str, str]]:
"""Return a list of (line_no, rule_id, message) violations for one file."""
content = path.read_text(encoding="utf-8", errors="replace")
lines = content.splitlines()
is_test_only = file_is_test_only(path, content)
out: list[tuple[int, str, str]] = []
for line_no, line in enumerate(lines, start=1):
stripped = line.strip()
if not stripped or stripped.startswith("//"):
continue
# Rule R1 — direct stub-macro calls.
for suffix in SKIP_LINE_SUFFIXES:
if stripped.endswith(suffix) or f".{suffix}" in stripped:
if not is_test_only:
out.append(
(
line_no,
"R1",
f"`{suffix}` is a stub. Implement the case (see § 0.5).",
)
)
# Rule R2 — empty catch-all in matches.
if EMPTY_CATCH_ALL.match(line):
# Heuristic: empty body is fine in some contexts (e.g. specific
# feature flags), but only flag when there's a preceding match.
# We just flag with a low-severity tag.
out.append(
(
line_no,
"R2",
"empty catch-all match arm `_ => {}` — confirm this is intentional",
)
)
# Rule R3 — DriverParams::default() returns in production code.
if not is_test_only and DRIVER_PARAMS_DEFAULT.search(line):
out.append(
(
line_no,
"R3",
"`DriverParams::default()` is a stub for production drivers — define real params",
)
)
for pattern, rule_id, message in [STUB_MACRO_PATTERN]:
if is_test_only:
break
import re as _re
if _re.search(pattern, stripped):
out.append((line_no, rule_id, message))
return out
def main() -> int:
violations_total = 0
files_scanned = 0
files_clean = 0
for path in iter_rust_files():
files_scanned += 1
violations = audit_file(path)
if not violations:
files_clean += 1
continue
violations_total += len(violations)
for line_no, rule_id, message in violations:
rel = path.relative_to(REPO_ROOT)
print(f"{rel}:{line_no}: [{rule_id}] {message}")
print()
print(f"=== driver-manager-audit-no-stubs.py ===")
print(f"files scanned: {files_scanned}")
print(f"files clean: {files_clean}")
print(f"violations: {violations_total}")
print(f"root: {REPO_ROOT}")
print(
"rules: R1 (stub macros), R2 (empty catch-all), R3 (DriverParams::default),"
)
print(" R5 (todo!/unimplemented! in callbacks)")
if violations_total > 0:
print()
print("FAIL — driver-manager has unresolved § 0.5 comprehensive-implementation violations.")
print("Fix every violation above and re-run. See migration plan § 5.1 D4 exit criteria.")
return 1
print()
print("OK — every scanned file passes the § 0.5 stub-audit.")
return 0
if __name__ == "__main__":
sys.exit(main())