"""Волны поверх vfbuild13: G=retype+usage-cast, H=for-each/toArray, I=this-cast+text, J=(Object[])→float[], K=int/boolean, M=структурные (nb, Cif, sh, Pair, импорты). Таблицы жёстко привязаны к номерам строк vfbuild13. Все line-правки применяются по убыванию номера строки внутри файла. Запуск: python3 tools/waves_ghik.py """ import re, os, sys, collections ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) JAVA = os.path.join(ROOT, "src/main/java") stats = collections.Counter() files = {} def get(rel): p = rel if os.path.isabs(rel) else os.path.join(JAVA, rel) if p not in files: files[p] = open(p, encoding="utf-8", errors="replace").read().splitlines() return files[p] def edit_line(rel, ln, old, new, tag): L = get(rel) i = ln - 1 if i >= len(L): stats[tag + "_MISS"] += 1 print(f"MISS {rel}:{ln} (file has {len(L)} lines)") return if old in L[i]: L[i] = L[i].replace(old, new, 1) stats[tag] += 1 elif new in L[i]: stats[tag + "_skip"] += 1 else: stats[tag + "_MISS"] += 1 print(f"MISS {rel}:{ln}: {old!r}\n got: {L[i].strip()!r}") def edit_all(rel, old, new, tag): L = get(rel) c = 0 for i, l in enumerate(L): if old in l: L[i] = l.replace(old, new) c += 1 if c: stats[tag] += c else: if any(new in l for l in L): stats[tag + "_skip"] += 1 else: stats[tag + "_MISS"] += 1 print(f"MISS-ALL {rel}: {old!r}") DECL_PAT = lambda var: re.compile( r"^\s*[A-Za-z_][\w.\[\]<>]*\s+%s\s*=" % re.escape(var) ) def find_decl(rel, ln, var): """Индекс строки-декларации `Type var = ...` выше ln в пределах метода.""" L = get(rel) i = ln - 2 pat = DECL_PAT(var) while i >= 0: l = L[i] if l.strip() and (len(l) - len(l.lstrip())) <= 3: return None if pat.match(l): return i i -= 1 return None def retype(rel, err_ln, var, newtype, tag): idx = find_decl(rel, err_ln, var) if idx is None: stats[tag + "_MISS"] += 1 print(f"DECL-MISS {rel}:{err_ln} var={var}") return L = get(rel) old = L[idx] L[idx] = re.sub( r"^(\s*)[A-Za-z_][\w.\[\]<>]*\s+%s\s*=" % re.escape(var), r"\g<1>%s %s =" % (newtype, var), old, count=1, ) if L[idx] == old and ("%s %s =" % (newtype, var)) in old: stats[tag + "_skip"] += 1 elif L[idx] == old: stats[tag + "_MISS"] += 1 print(f"RETYPE-MISS {rel}:{idx + 1}: {old!r}") else: stats[tag] += 1 def cast_usage(rel, ln, var, ctype, tag): L = get(rel) i = ln - 1 if i >= len(L): stats[tag + "_MISS"] += 1 print(f"CAST-MISS {rel}:{ln} (oob)") return needle = "%s." % var already = "((%s)%s)." % (ctype, var) if already in L[i]: stats[tag + "_skip"] += 1 return if needle not in L[i]: stats[tag + "_MISS"] += 1 print(f"CAST-MISS {rel}:{ln}: {needle!r}\n got: {L[i].strip()!r}") return L[i] = L[i].replace(needle, "((%s)%s)." % (ctype, var)) stats[tag] += 1 FOREACH_PAT = re.compile(r"^(.*\bfor \()([A-Za-z_][\w.\[\]]*) (\w+) : (.*)$") PRIM = { "long": "Long", "int": "Integer", "double": "Double", "float": "Float", "boolean": "Boolean", "char": "Character", "byte": "Byte", "short": "Short", } def foreach_cast(rel, ln, tag): L = get(rel) i = ln - 1 if i >= len(L): stats[tag + "_MISS"] += 1 print(f"FE-MISS {rel}:{ln} (oob)") return l = L[i] if "(Iterable<" in l: stats[tag + "_skip"] += 1 return m = FOREACH_PAT.match(l) if not m: stats[tag + "_MISS"] += 1 print(f"FE-MISS {rel}:{ln}: {l.strip()!r}") return pfx, typ, var, rest = m.groups() ityp = PRIM.get(typ, typ) L[i] = f"{pfx}{typ} {var} : (Iterable<{ityp}>){rest}" stats[tag] += 1 def wrap_assign_rhs(rel, ln, tag): """Обернуть RHS бинарного присваивающего оператора в `(EXPR) ? 1 : 0` перед `;`.""" L = get(rel) i = ln - 1 if i >= len(L) or "? 1 : 0" in L[i]: if i < len(L) and "? 1 : 0" in L[i]: stats[tag + "_skip"] += 1 return depth = 0 for j in range(i, len(L)): for k, ch in enumerate(L[j]): if ch in "([{": depth += 1 elif ch in ")]}": depth -= 1 elif ch == ";" and depth == 0: L[j] = L[j][:k] + " ? 1 : 0" + L[j][k:] stats[tag] += 1 return stats[tag + "_MISS"] += 1 print(f"WRAP-MISS {rel}:{ln}") def insert_after(rel, anchor, newline, tag): L = get(rel) if newline in L: stats[tag + "_skip"] += 1 return for i, l in enumerate(L): if l.strip() == anchor: L.insert(i + 1, newline) stats[tag] += 1 return stats[tag + "_MISS"] += 1 print(f"IMPORT-MISS {rel}: anchor {anchor!r}") # ============================ G: retype ============================ # (rel, err_line, var, newtype) RETYPE = [ ("defpackage/gq.java", 88, "var2x", "Int2FloatMap"), ("defpackage/ed.java", 345, "var7", "File"), ("defpackage/acf.java", 187, "var8", "String"), ("defpackage/acf.java", 586, "var1", "Optional"), ("defpackage/ajq.java", 135, "var4", "Info"), ("defpackage/akz.java", 126, "var5", "File"), ("defpackage/akz.java", 802, "var9", "String"), ("defpackage/aua.java", 251, "var19", "Vertex"), ("defpackage/aua.java", 276, "var15", "Polygon"), ("defpackage/auv.java", 359, "var8", "Direction"), ("defpackage/bt.java", 20, "var4", "Method"), ("defpackage/bx.java", 19, "var5", "Method"), ("defpackage/cc.java", 18, "var4", "Field"), ("defpackage/op.java", 1334, "var4", "od"), ("defpackage/qs.java", 1269, "var5", "ItemStack"), ("defpackage/im.java", 66, "var5", "StackTraceElement"), ("defpackage/cm.java", 178, "var5", "String"), ("defpackage/mw.java", 573, "var9", "Enum"), ("defpackage/aah.java", 2471, "var11", "ArrayList"), ("defpackage/aah.java", 1115, "var3", "ArrayList"), ("defpackage/aah.java", 1291, "var3", "ArrayList"), ("defpackage/aah.java", 1504, "var3", "ArrayList"), ("defpackage/aah.java", 1813, "var3", "ArrayList"), ("defpackage/ahn.java", 751, "var22", "ArrayList"), ("defpackage/je.java", 447, "var1", "ArrayList"), ("defpackage/je.java", 431, "var9", "ArrayList"), ("defpackage/jz.java", 60, "var1", "ArrayList"), ("defpackage/jz.java", 50, "var9", "ArrayList"), ("defpackage/ms.java", 197, "var8", "Object"), ("defpackage/auk.java", 65, "var2", "Set"), ("defpackage/auk.java", 114, "var2", "Set"), ] # ======================= G2: usage-casts ======================= # (rel, line, var, casttype) CASTS = [ # ms (merged slots; var8 retype to Object + ItemStack casts) ("defpackage/ms.java", 175, "var5", "Iterator"), ("defpackage/ms.java", 182, "var7", "Iterator"), ("defpackage/ms.java", 189, "var6", "Iterator"), ("defpackage/ms.java", 196, "var6", "Iterator"), ("defpackage/ms.java", 197, "var7", "Entry"), ("defpackage/ms.java", 198, "var5", "List"), ("defpackage/ms.java", 200, "var7", "Entry"), ("defpackage/ms.java", 219, "var7", "Iterator"), ("defpackage/ms.java", 229, "var5", "Iterator"), # ahn ("defpackage/ahn.java", 272, "var2", "Iterator"), ("defpackage/ahn.java", 279, "var2", "Iterator"), ("defpackage/ahn.java", 284, "var3", "Iterator"), ("defpackage/ahn.java", 292, "var2", "List"), ("defpackage/ahn.java", 301, "var2", "List"), ("defpackage/ahn.java", 312, "var3", "Iterator"), # aid (JsonArray | Iterator) ("defpackage/aid.java", 280, "var5", "Iterator"), ("defpackage/aid.java", 287, "var5", "Iterator"), ("defpackage/aid.java", 302, "var5", "JsonArray"), ("defpackage/aid.java", 303, "var5", "JsonArray"), ("defpackage/aid.java", 304, "var5", "JsonArray"), ("defpackage/aid.java", 309, "var5", "JsonArray"), ("defpackage/aid.java", 310, "var5", "JsonArray"), ("defpackage/aid.java", 311, "var5", "JsonArray"), # adv (Entry) ("defpackage/adv.java", 907, "var8", "Entry"), ("defpackage/adv.java", 908, "var8", "Entry"), ("defpackage/adv.java", 938, "var8", "Entry"), # gt (Iterator) ("defpackage/gt.java", 504, "var21", "Iterator"), ("defpackage/gt.java", 513, "var21", "Iterator"), ] # ms: профилактические касты после retype var8→Object (строки не в логе ошибок) MS_EXTRA = [ (220, "stackKey(var8)", "stackKey((ItemStack)var8)"), (222, "var8.getItem()", "((ItemStack)var8).getItem()"), (223, "= var3.computeIfAbsent(var9,", "= (long[])var3.computeIfAbsent(var9,"), (225, "var8.getCount()", "((ItemStack)var8).getCount()"), ] # ============================ H: for-each ============================ # (rel, line) FOREACH = [ ("defpackage/aah.java", 190), ("defpackage/aah.java", 1819), ("defpackage/aaj.java", 659), ("defpackage/aaj.java", 663), ("defpackage/aaj.java", 1970), ("defpackage/aaj.java", 1978), ("defpackage/aaj.java", 1989), ("defpackage/abs.java", 141), ("defpackage/afp.java", 547), ("defpackage/afp.java", 558), ("defpackage/afp.java", 581), ("defpackage/afp.java", 592), ("defpackage/ahf.java", 436), ("defpackage/ahi.java", 217), ("defpackage/aiq.java", 181), ("defpackage/aiq.java", 190), ("defpackage/akd.java", 44), ("defpackage/ajx.java", 105), ("defpackage/akt.java", 828), ("defpackage/ald.java", 105), ("defpackage/an.java", 76), ("defpackage/anb.java", 574), ("defpackage/anb.java", 623), ("defpackage/anb.java", 632), ("defpackage/anb.java", 636), ("defpackage/anb.java", 687), ("defpackage/ans.java", 759), ("defpackage/hl.java", 94), ("defpackage/hl.java", 170), ("defpackage/hn.java", 565), ("defpackage/j.java", 495), ("defpackage/j.java", 502), ("defpackage/je.java", 431), ("defpackage/jt.java", 255), ("defpackage/jt.java", 276), ("defpackage/jt.java", 342), ("defpackage/jz.java", 50), ("defpackage/ka.java", 78), ("defpackage/ko.java", 48), ("defpackage/ko.java", 55), ("defpackage/mk.java", 132), ("defpackage/mr.java", 48), ("defpackage/ql.java", 32), ("defpackage/ri.java", 1249), ("defpackage/ue.java", 1449), ("defpackage/uq.java", 252), ("defpackage/uq.java", 269), ("defpackage/vp.java", 885), ("defpackage/ado.java", 147), ] # ==================== H2: toArray cast result ==================== # (rel, line, old, new) TOARRAY = [ ( "defpackage/ahi.java", 131, "var3.toArray(new aho[0])", "(aho[])var3.toArray(new aho[0])", ), ( "defpackage/ahi.java", 327, "var1.values().toArray(new String[0])", "(String[])var1.values().toArray(new String[0])", ), ( "defpackage/akz.java", 449, "var44.toArray(new BlockState[0])", "(BlockState[])var44.toArray(new BlockState[0])", ), ( "defpackage/akz.java", 522, "var20.toArray(new BlockState[0])", "(BlockState[])var20.toArray(new BlockState[0])", ), ( "defpackage/akz.java", 586, "var7.toArray(new BlockState[0])", "(BlockState[])var7.toArray(new BlockState[0])", ), ( "defpackage/ald.java", 127, "var6.toArray(new BakedQuad[0])", "(BakedQuad[])var6.toArray(new BakedQuad[0])", ), ( "defpackage/aua.java", 101, "var1.toArray(new ModelPart[0])", "(ModelPart[])var1.toArray(new ModelPart[0])", ), ] # ====================== I: this-cast миксины ====================== # (rel, line, old, new) THISCAST = [ ("b/ag.java", 16, "(LocalPlayer)this", "(LocalPlayer)(Object)this"), ("b/ap.java", 27, "(TitleScreen)this", "(TitleScreen)(Object)this"), ( "b/bd.java", 17, "this instanceof ModelFeatureRenderer", "((Object)this) instanceof ModelFeatureRenderer", ), ("b/be.java", 17, "(Screen)this", "(Screen)(Object)this"), ( "b/bm.java", 89, "this instanceof InventoryScreen", "((Object)this) instanceof InventoryScreen", ), ( "b/bp.java", 55, "(AbstractContainerScreen)this", "(AbstractContainerScreen)(Object)this", ), ( "b/bp.java", 67, "(AbstractContainerScreen)this", "(AbstractContainerScreen)(Object)this", ), ( "b/bp.java", 74, "(AbstractContainerScreen)this", "(AbstractContainerScreen)(Object)this", ), ( "b/br.java", 32, "(AbstractContainerScreen)this", "(AbstractContainerScreen)(Object)this", ), ("b/bt.java", 17, "this != mc.player", "(Object)this != mc.player"), ("b/bt.java", 22, "this == mc.player", "(Object)this == mc.player"), ("b/bt.java", 29, "this == mc.player", "(Object)this == mc.player"), ( "b/bu.java", 28, "this instanceof LocalPlayer player", "((Object)this) instanceof LocalPlayer player", ), ( "b/bu.java", 39, "this instanceof LocalPlayer player", "((Object)this) instanceof LocalPlayer player", ), ("b/bu.java", 48, "(Player)this", "(Player)(Object)this"), ( "b/cb.java", 30, "(RenderLayer)this", "(RenderLayer)(Object)this", ), ("b/cv.java", 15, "(PlayerModel)this", "(PlayerModel)(Object)this"), ( "b/dd.java", 22, "this instanceof ClientLevel", "((Object)this) instanceof ClientLevel", ), ( "b/dd.java", 83, "!(this instanceof ClientLevel)", "!(((Object)this) instanceof ClientLevel)", ), ( "b/q.java", 18, "(AbstractClientPlayer)this", "(AbstractClientPlayer)(Object)this", ), ("b/z.java", 20, "this == mc.player", "(Object)this == mc.player"), ( "b/z.java", 30, "this instanceof LocalPlayer", "((Object)this) instanceof LocalPlayer", ), ( "b/z.java", 35, "this instanceof LocalPlayer", "((Object)this) instanceof LocalPlayer", ), ("b/bg.java", 83, "((aqe)line.parent())", "((aqe)(Object)line.parent())"), ("a/f.java", 137, "this == Minecraft.getInstance().player", "(Object)this == Minecraft.getInstance().player"), ] # =================== I2: квалификации/одиночные =================== # (rel, line, old, new) TEXTC = [ ("b/bx.java", 27, "defpackage.defpackage.bz", "defpackage.bz"), ("b/t.java", 49, "defpackage.defpackage.bz", "defpackage.bz"), ("b/cr.java", 18, "((defpackage.b.ck)this)", "((ck)this)"), ( "b/dd.java", 18, "private final ct evo$smoothSkipAnim", "private final defpackage.ct evo$smoothSkipAnim", ), ( "b/z.java", 40, "bz evolution = defpackage.bz.getInstance()", "defpackage.bz evolution = defpackage.bz.getInstance()", ), ("a/o.java", 62, "((b.l)this)", "((l)this)"), ("defpackage/sh.java", 14, "this(var1, var2);", "this(var1, var2, new String[0]);"), ("a/l.java", 385, "((x)item)", "((x)(Object)item)"), ("defpackage/bn.java", 241, "((x)var1)", "((x)(Object)var1)"), ("defpackage/bn.java", 295, "((x)var1)", "((x)(Object)var1)"), ("defpackage/bn.java", 305, "((x)var1)", "((x)(Object)var1)"), ("defpackage/bn.java", 358, "((x)var1)", "((x)(Object)var1)"), ("defpackage/bn.java", 410, "((x)var1)", "((x)(Object)var1)"), ] # ======================== J: (Object[])→float[] ======================== ARRAYS = [ ("defpackage/aah.java", "((Object[])var15)", "((float[])var15)"), ("defpackage/adf.java", "((Object[])var8)", "((float[])var8)"), ("defpackage/adv.java", "((Object[])var12)", "((float[])var12)"), ] # ======================== K: int/boolean ======================== # (rel, line, old, new) INTBOOL = [ ("defpackage/ajn.java", 324, "if (!var2 &&", "if (var2 == 0 &&"), ("defpackage/ajn.java", 329, "if (!var3 &&", "if (var3 == 0 &&"), ("defpackage/ajn.java", 334, "if (var3 &&", "if (var3 != 0 &&"), ("defpackage/ajn.java", 340, "if (var2 &&", "if (var2 != 0 &&"), ("defpackage/ajn.java", 346, "} else if (var6 &&", "} else if (var6 != 0 &&"), ("defpackage/afp.java", 637, "int var16x = var29 &&", "int var16x = var29 != 0 &&"), ( "defpackage/afp.java", 647, "apply(var30, var13, var31, var16x,", "apply(var30, var13, var31, (var16x != 0),", ), ("defpackage/agx.java", 398, "int var18 = var10 &&", "int var18 = var10 != 0 &&"), ( "defpackage/agx.java", 401, "apply(var11, var7, var6, var18,", "apply(var11, var7, var6, (var18 != 0),", ), ("defpackage/anl.java", 145, "sharing = var1;", "sharing = var1 != 0;"), ("defpackage/anl.java", 146, "if (!var1) {", "if (var1 == 0) {"), ("defpackage/vr.java", 101, "return var2;", "return var2 != 0;"), ("defpackage/up.java", 444, "return var2;", "return var2 != 0;"), ("defpackage/ajm.java", 22, "return 0;", "return false;"), ( "defpackage/zk.java", 54, "this.val$syncing[0] = 1;", "this.val$syncing[0] = true;", ), ( "defpackage/zk.java", 56, "this.val$syncing[0] = 0;", "this.val$syncing[0] = false;", ), ( "defpackage/zm.java", 46, "this.val$pushed[0] = (IsEnabled == true ? 1 : 0) == true ? 1 : 0;", "this.val$pushed[0] = IsEnabled;", ), ("defpackage/zm.java", 47, ", IsEnabled == true ? 1 : 0);", ", IsEnabled);"), ( "defpackage/zm.java", 61, "this.val$pushed[0] = (flag == true ? 1 : 0) == true ? 1 : 0;", "this.val$pushed[0] = flag;", ), ("defpackage/zm.java", 62, "setEnabled(flag == true ? 1 : 0)", "setEnabled(flag)"), ( "defpackage/zr.java", 215, "if (var1x != var2[0]) {", "if ((var1x != 0) != var2[0]) {", ), ( "defpackage/zr.java", 228, "if (var2x != var2[0]) {", "if ((var2x != 0) != var2[0]) {", ), ( "defpackage/aab.java", 151, "if (var1 != this.lastEnabled) {", "if ((var1 != 0) != this.lastEnabled) {", ), ( "defpackage/anh.java", 189, "if (var5 != var2.visible) {", "if ((var5 != 0) != var2.visible) {", ), ("defpackage/yy.java", 356, "if (var4 != var6) {", "if (var4 != (var6 != 0)) {"), ( "defpackage/atf.java", 918, "shapeCommands[var20] != var14", "(shapeCommands[var20] ? 1 : 0) != var14", ), ( "defpackage/aul.java", 248, "if (var0 == shaderPackConflict) {", "if ((var0 != 0) == shaderPackConflict) {", ), ("defpackage/aid.java", 636, "byte var33 = var18;", "byte var33 = var18 ? 1 : 0;"), ("defpackage/aid.java", 639, "var33 = (byte)(var18 == 0", "var33 = (byte)(!var18"), ( "defpackage/aid.java", 640, "? 1: (1597328994 | -1597328994) + (1597328994 & -1597328994));", "? 1: 0);", ), ( "defpackage/aid.java", 641, '} else if (var18 != 0 && "east".equals(var0)) {', '} else if (var18 && "east".equals(var0)) {', ), ( "defpackage/aid.java", 643, '} else if (var18 != 0 && "west".equals(var0)) {', '} else if (var18 && "west".equals(var0)) {', ), ("defpackage/ww.java", 558, " (boolean)var6,", " (var6 != 0),"), ( "defpackage/bn.java", 533, "new ad((boolean)var8, (boolean)var7,", "new ad((var8 != 0), (var7 != 0),", ), ( "defpackage/apm.java", 171, "new Input((boolean)var4, (boolean)var5,", "new Input((var4 != 0), (var5 != 0),", ), ( "defpackage/im.java", 187, 'var4 |= var9.getClassName().startsWith("evo.");', 'var4 |= var9.getClassName().startsWith("evo.") ? 1 : 0;', ), ( "defpackage/aod.java", 729, "this.reap(var4, var5, var3, var6)", "this.reap(var4, var5, var3, var6 != 0)", ), ("defpackage/aod.java", 795, "if (!var5) {", "if (var5 == 0) {"), ( "defpackage/agt.java", 69, "var8, var9, var3, var10)", "var8, var9, var3, var10 != 0)", ), ("defpackage/ld.java", 281, "if (!var6) {", "if (var6 == 0) {"), ("defpackage/jb.java", 21, "return i;", "return i != 0;"), ("defpackage/anu.java", 40, "return i;", "return i != 0;"), ("defpackage/kk.java", 25, "return i;", "return i != 0;"), ] # многострочные `|= boolean` (vl): обёртка RHS VL_WRAP = [ ("defpackage/vl.java", 1844), ("defpackage/vl.java", 1975), ("defpackage/vl.java", 1998), ("defpackage/vl.java", 2021), ("defpackage/vl.java", 2049), ("defpackage/vl.java", 2086), ("defpackage/vl.java", 2222), ] # ==================== M: структурные фиксы ==================== NB_CONSTS = """ NORMAL("Normal", null), PROTANOPIA("Protanopia", new float[]{0.152286F, 1.052583F, -0.204868F, 0.114503F, 0.786281F, 0.099216F, -0.003882F, -0.048116F, 1.051998F}), DEUTERANOPIA("Deuteranopia", new float[]{0.367322F, 0.860646F, -0.227968F, 0.280085F, 0.672501F, 0.047413F, -0.01182F, 0.04294F, 0.968881F}), TRITANOPIA("Tritanopia", new float[]{1.255528F, -0.076749F, -0.178779F, 0.147602F, 0.930809F, -0.078411F, 0.004733F, 0.691367F, 0.3039F}), ACHROMATOPSIA("Achromatopsia", new float[]{0.2126F, 0.7152F, 0.0722F, 0.2126F, 0.7152F, 0.0722F, 0.2126F, 0.7152F, 0.0722F});""" def fix_nb(): rel = "defpackage/nb.java" L = get(rel) # 1) константы в заголовке try: i0 = next(i for i, l in enumerate(L) if l.strip().startswith("NORMAL(")) i1 = next(i for i, l in enumerate(L) if l.strip().startswith("ACHROMATOPSIA;")) except StopIteration: if any("0.152286F" in l for l in L): stats["nb_skip"] += 1 else: stats["nb_MISS"] += 1 print("NB-MISS: constants header not found") return L[i0 : i1 + 1] = NB_CONSTS.splitlines() stats["nb"] += 1 # 2) удалить static-блок с присваиваниями try: s = next(i for i, l in enumerate(L) if "Failed to inline enum fields" in l) except StopIteration: stats["nb_block_MISS"] += 1 print("NB-MISS: static block not found") return # конец блока: строка ` }` после ACHROMATOPSIA = new nb(...) e = next(i for i in range(s, len(L)) if "ACHROMATOPSIA = new nb(" in L[i]) e2 = next(i for i in range(e, len(L)) if L[i].strip() == "}") del L[s : e2 + 1] stats["nb_block"] += 1 CIF_CONST_RE = re.compile(r"^\s*public static final Cif (\w+) = new Cif\((.*)\);\s*$") def fix_cif(): rel = "defpackage/Cif.java" L = get(rel) if not any(l.strip().startswith("public final class Cif") for l in L): if any(l.strip().startswith("public enum Cif") for l in L): stats["Cif_skip"] += 1 else: stats["Cif_MISS"] += 1 print("CIF-MISS: class decl not found") return # собрать константы consts = [] keep = [] for l in L: m = CIF_CONST_RE.match(l) if m: consts.append((m.group(1), m.group(2))) else: keep.append(l) if len(consts) != 15: stats["Cif_MISS"] += 1 print(f"CIF-MISS: found {len(consts)} constants") return L = keep # class → enum for i, l in enumerate(L): if l.strip().startswith("public final class Cif"): L[i] = l.replace("public final class Cif", "public enum Cif") break # вставить константы сразу после заголовка enum hi = next(i for i, l in enumerate(L) if l.strip().startswith("public enum Cif")) lines = [] for n, (name, args) in enumerate(consts): sep = "," if n < len(consts) - 1 else ";" lines.append(f" {name}({args}){sep}") L[hi + 1 : hi + 1] = lines stats["Cif"] += 1 out = [] skip_until = None mode = None i = 0 while i < len(L): l = L[i] s = l.strip() if s.startswith("private static final /* synthetic */ Cif[] $VALUES"): i += 1 continue if s.startswith("public static Cif[] values()") or s.startswith( "public static Cif valueOf(" ): # пропустить до закрывающей скобки метода (уровень отступа метода) ind = len(l) - len(l.lstrip()) i += 1 while i < len(L) and not ( L[i].strip() == "}" and (len(L[i]) - len(L[i].lstrip())) == ind ): i += 1 i += 1 continue if s.startswith("private static /* synthetic */ Cif[] $values()"): ind = len(l) - len(l.lstrip()) i += 1 while i < len(L) and not ( L[i].strip() == "}" and (len(L[i]) - len(L[i].lstrip())) == ind ): i += 1 i += 1 # и пустая строка после if i < len(L) and not L[i].strip(): i += 1 continue if s == "super(str, i);": i += 1 continue if s == "return 0;": out.append(l.replace("return 0;", "return false;")) i += 1 continue if s == "return i;": out.append(l.replace("return i;", "return i != 0;")) i += 1 continue out.append(l) i += 1 files[os.path.join(JAVA, rel)] = out stats["Cif_cleanup"] += 1 PAIR_SRC = """package kotlin; public class Pair { private final A first; private final B second; public Pair(A var1, B var2) { this.first = var1; this.second = var2; } public A getFirst() { return this.first; } public B getSecond() { return this.second; } } """ def write_pair(): p = os.path.join(JAVA, "kotlin/Pair.java") os.makedirs(os.path.dirname(p), exist_ok=True) if os.path.exists(p): stats["Pair_skip"] += 1 return with open(p, "w", encoding="utf-8") as f: f.write(PAIR_SRC) stats["Pair"] += 1 def main(): # line-правки по убыванию внутри файла def apply_line_edits(table, tag): by = collections.defaultdict(list) for row in table: by[row[0]].append(row) for rel, rows in by.items(): for row in sorted(rows, key=lambda r: -r[1]): edit_line(rel, row[1], row[2], row[3], tag) for rel, ln, var, nt in sorted(RETYPE, key=lambda r: -r[1]): retype(rel, ln, var, nt, "retype") for rel, ln, var, ct in sorted(CASTS, key=lambda r: -r[1]): cast_usage(rel, ln, var, ct, "cast") for ln, old, new in sorted(MS_EXTRA, key=lambda r: -r[0]): edit_line("defpackage/ms.java", ln, old, new, "ms_extra") for rel, ln in sorted(FOREACH, key=lambda r: -r[1]): foreach_cast(rel, ln, "foreach") apply_line_edits(TOARRAY, "toarray") apply_line_edits(THISCAST, "thiscast") apply_line_edits(TEXTC, "text") for rel, old, new in ARRAYS: edit_all(rel, old, new, "array") apply_line_edits(INTBOOL, "intbool") for rel, ln in VL_WRAP: wrap_assign_rhs(rel, ln, "vlwrap") # структурные fix_nb() fix_cif() write_pair() # импорты insert_after( "defpackage/acf.java", "import net.fabricmc.loader.api.FabricLoader;", "import net.fabricmc.loader.api.ModContainer;", "import", ) insert_after("a/o.java", "import defpackage.*;", "import b.l;", "import") # сохранить for p, L in files.items(): with open(p, "w", encoding="utf-8") as f: f.write("\n".join(L) + "\n") print(dict(stats)) miss = {k: v for k, v in stats.items() if k.endswith("_MISS")} if miss: print("MISSES:", dict(miss)) sys.exit(1) if __name__ == "__main__": main()