import re
from pathlib import Path
import sys
def find_option_box_fields(content: str):
results = []
field_re = re.compile(r"pub\s+(\w+)\s*:\s*Option\s*<\s*Box\s*<\s*([^>]+)\s*>\s*>\s*,")
for m in field_re.finditer(content):
field = m.group(1)
inner = m.group(2).strip()
results.append((field, inner))
return results
def fix_signature(content: str, fields):
if not fields:
return content
sig_re = re.compile(r"pub\s+fn\s+new\(([^)]*)\)")
m = sig_re.search(content)
if not m:
return content
sig = m.group(1)
orig_sig = sig
for field, inner in fields:
param_re = re.compile(rf"(\b{field}\s*:\s*)(?!Option<)([^,\)]+)")
sig = param_re.sub(rf"\1Option<{inner}>", sig)
if sig != orig_sig:
content = content[: m.start(1)] + sig + content[m.end(1) :]
return content
def fix_constructor_body(content: str, fields):
for field, _inner in fields:
content = re.sub(
rf"(\n\s*{field}\s*:\s*)Box::new\({field}\)",
rf"\1{field}.map(Box::new)",
content,
)
content = re.sub(
rf"(\n\s*{field}\s*:\s*)Some\(Box::new\({field}\)\)",
rf"\1{field}.map(Box::new)",
content,
)
return content
def process_file(path: Path) -> bool:
txt = path.read_text()
fields = find_option_box_fields(txt)
if not fields:
return False
new_txt = fix_signature(txt, fields)
new_txt = fix_constructor_body(new_txt, fields)
if new_txt != txt:
path.write_text(new_txt)
return True
return False
def main():
if len(sys.argv) < 2:
print("Usage: fix_option_box_constructor_mismatches.py <project_root>")
sys.exit(1)
root = Path(sys.argv[1])
models_dir = root / "src" / "models"
if not models_dir.exists():
print(f"Models directory not found: {models_dir}")
sys.exit(1)
fixed = 0
for path in models_dir.glob("*.rs"):
if process_file(path):
fixed += 1
print(f"Fixed constructor in {path.name}")
print(f"Fixed {fixed} files with Option<Box<_>> constructor mismatches")
if __name__ == "__main__":
main()