"""Insert `<field>: <value>,` into struct literals cargo flagged E0063.

usage: python fix_missing.py <cargo-short-output-file> <StructName> <field> <value>
Processes each file bottom-up so offsets stay valid. Keeps CRLF.
"""
import re
import sys
from collections import defaultdict

out, struct, field, value = sys.argv[1:5]
pat = re.compile(r'^(crates[\\/][^:]+):(\d+):(\d+): error\[E0063\]: missing field `' + re.escape(field) + r'` in initializer of `[^`]*' + re.escape(struct) + '`')
hits = defaultdict(set)
for line in open(out, encoding='utf-8', errors='replace'):
    m = pat.match(line.strip())
    if m:
        hits[m.group(1).replace('\\', '/')].add((int(m.group(2)), int(m.group(3))))
for path, locs in hits.items():
    s = open(path, encoding='utf-8', newline='').read()
    nl = '\r\n' if '\r\n' in s else '\n'
    lines = s.split(nl)
    starts = [0]
    for ln in lines[:-1]:
        starts.append(starts[-1] + len(ln) + len(nl))
    for (ln, col) in sorted(locs, reverse=True):
        off = starts[ln - 1] + col - 1
        brace = s.index('{', off)
        depth = 0
        i = brace
        while True:
            c = s[i]
            if c == '{':
                depth += 1
            elif c == '}':
                depth -= 1
                if depth == 0:
                    break
            i += 1
        body = s[brace + 1:i]
        if field + ':' in body:
            continue
        # indentation of the last field line
        stripped = body.rstrip()
        if nl in body.strip():
            last_line = stripped.split(nl)[-1]
            ind = last_line[:len(last_line) - len(last_line.lstrip())]
            sep = '' if stripped.endswith(',') else ','
            ins = sep + nl + ind + field + ': ' + value + ','
            pos = brace + 1 + len(stripped)
            s = s[:pos] + ins + s[pos:]
        else:
            inner = body.strip()
            sep = '' if inner.endswith(',') or not inner else ','
            s = s[:brace + 1] + ' ' + inner + sep + ' ' + field + ': ' + value + ' ' + s[i:]
        print(f'{path}:{ln}')
    open(path, 'w', encoding='utf-8', newline='').write(s)
