feat: migrate story modules & engine; update assets and structure
This commit is contained in:
81
tools/check_invalid_nodes.py
Normal file
81
tools/check_invalid_nodes.py
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
from collections import defaultdict
|
||||
|
||||
ROOT = os.path.join(os.path.dirname(__file__), "..", "app", "src", "main", "assets", "story")
|
||||
ROOT = os.path.abspath(ROOT)
|
||||
|
||||
NODE_DEF_RE = re.compile(r"^@node\s+([A-Za-z0-9_]+)")
|
||||
TARGET_RE = re.compile(r"->\s*([A-Za-z0-9_]+)\b")
|
||||
|
||||
def scan():
|
||||
node_defs = {}
|
||||
refs = []
|
||||
for dirpath, _, filenames in os.walk(ROOT):
|
||||
for fn in filenames:
|
||||
if not fn.endswith('.story'):
|
||||
continue
|
||||
path = os.path.join(dirpath, fn)
|
||||
try:
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
for ln, raw in enumerate(f, 1):
|
||||
line = raw.strip()
|
||||
m = NODE_DEF_RE.match(line)
|
||||
if m:
|
||||
node_defs[m.group(1)] = path
|
||||
for rm in TARGET_RE.finditer(line):
|
||||
refs.append((rm.group(1), path, ln))
|
||||
except Exception as e:
|
||||
print(f"! failed to read {path}: {e}")
|
||||
invalid = defaultdict(list)
|
||||
for target, path, ln in refs:
|
||||
if target not in node_defs:
|
||||
invalid[target].append({"file": path, "line": ln})
|
||||
return node_defs, refs, invalid
|
||||
|
||||
def module_hint(file_path: str) -> str:
|
||||
base = os.path.basename(file_path)
|
||||
name, _ = os.path.splitext(base)
|
||||
return name
|
||||
|
||||
def main():
|
||||
node_defs, refs, invalid = scan()
|
||||
items = []
|
||||
for t in sorted(invalid.keys()):
|
||||
locs = invalid[t]
|
||||
modules = sorted({module_hint(l['file']) for l in locs})
|
||||
items.append({
|
||||
"node": t,
|
||||
"modules": modules,
|
||||
"references": locs,
|
||||
"ref_count": len(locs)
|
||||
})
|
||||
|
||||
report = {
|
||||
"story_root": ROOT,
|
||||
"defined_nodes": len(node_defs),
|
||||
"total_refs": len(refs),
|
||||
"invalid_count": len(items),
|
||||
"items": items,
|
||||
}
|
||||
|
||||
# Print a human-readable summary followed by JSON
|
||||
print("=== Invalid (referenced but undefined) nodes ===")
|
||||
if not items:
|
||||
print("None")
|
||||
else:
|
||||
for it in items:
|
||||
mods = ",".join(it["modules"]) or "unknown"
|
||||
print(f"- {it['node']} [modules: {mods}] refs: {it['ref_count']}")
|
||||
for r in it["references"]:
|
||||
file_rel = os.path.relpath(r["file"], os.path.dirname(ROOT))
|
||||
print(f" · {file_rel}:{r['line']}")
|
||||
print("\n--- JSON ---")
|
||||
print(json.dumps(report, ensure_ascii=False, indent=2))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user