- refactor(8.5.1): split render/engine/uniform/impl 28 classes into hand/sky/esp/post/ui/world(+liquid) leaves - refactor(8.5.1): split renderer/ui top 28 files into blur/batches(+ordered)/item/deferred(+sched)/pass/dispatch leaves; add tools/pkgsplit scripts (split_struct.py, promote.py) for reproducible waves - refactor(8.5.1): split render/engine/text 24 files into font(+faces/info)/glyph/msdf/render/command leaves; fiximports tool; disambiguate Font/GlyphAtlasManager shadowing - refactor(8.5.1): split nondraggable/impl into bars(+jump)/locator(+panel)/buttons/tooltips/dynamicisland/overlay; promote.py +8-indent & ctor support - refactor(8.5.1): nondraggable dynamicisland 5->4 files (IslandUiUtil into controls) - refactor(8.5.1): split features/gui/clickgui top 20 files into render/screen/editor/input/tabs/picker/font; ClickGuiModel records nested - refactor(8.5.1): picker 6->5+screen leaf - refactor(8.5.1): picker catalog leaf (picker=2: state+icon manager) - refactor(tools): improve pkgsplit import handling (fiximports v2) - refactor(8.5.1): split util/text 8 -> mask/format/edit leaves (≤4) - refactor(8.5.1): split util/network 5, util/player/effect 5, util/media 5 (+ shadow fix) - refactor(8.5.1): split util/pvp 13, util/projectile 13, util/block 8 - refactor(8.5.1): split util/wav 9, util/item 9, util/combat 9, util/player/inventory 9 - refactor(8.5.1): split render/helpers 16 + config/values 16 - refactor(8.5.1): split renderer/ui/draw 23 -> shape/box/corner/edge/paint/effect - refactor(8.5.1): split render/engine/command 17 -> core/shape/effect/texture/world - refactor(8.5.1): split renderer/ui/runtime/script 23 -> engine/runtime/module/registry/render/patch - refactor(8.5.1): split profiler 14 + hud 14 + addon 14 - refactor(8.5.1): split iris 13 + profile 13 + text/backend 12 - refactor(8.5.1): split config 12 + module 12 + cosmetic 11 - refactor(8.5.1): split rhi/pipeline 11 + mixininterface 11 + config/common/impl 11 - refactor(8.5.1): split util/player 10 + rhi/resource 10 + runtime/render 10 - refactor(8.5.1): split rhi 9 + svg 9 + command 8 - refactor(8.5.1): split core 9 + postprocess 9 + combat 9 - refactor(8.5.1): split command/impl 16 + modules/player 14 + modules/misc 12 - refactor(8.5.1): split ui/runtime 43 -> core/style/input/reconcile/asset - refactor(8.5.1): split session/microsoft 8 + relations 7 + animation 7 - refactor(8.5.1): split engine/world 7 + postprocess/graph 7 + api/v0/render 7 - refactor(8.5.1): split sodium 12 + aiming 21 - refactor(8.5.1): split хвост 13 папок 34 файла - fix(8.5.1): видимость членов и enum после расщепления пакетов - refactor(8.5.1): FailRotationProcessor -> processors root (impl 5 -> 4) - docs(8.5.1): TODO — волна 8.5.1 завершена (0 папок >4 файлов) - refactor(8.5.2): split LoVisualAltManagerScreen 1113 -> 11 файлов alt/ (≤200 строк) - docs(8.5.2): LoVisualAltManagerScreen сплит завершён - refactor(8.5.2): split UiPrimitiveRenderer 1053 -> фасад 188 + primitive/ + rect/ (7 файлов ≤200); fix readPoints индексация - docs(8.5.2): UiPrimitiveRenderer сплит завершён
152 lines
5.8 KiB
Python
152 lines
5.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Compile-fix helper (Phase 8.5.1): promote declarations to public until
|
|
compileJava+compileTestJava are green. Brace-depth-aware class-body tracking;
|
|
statement lines are never touched. Run from project root.
|
|
Usage: python3 promote.py BASE_DIR"""
|
|
import os, re, subprocess, sys
|
|
|
|
MODS = {"public","private","protected","static","final","abstract","transient","volatile","native","strictfp"}
|
|
PRIMS = {"int","float","double","boolean","long","byte","short","char","void"}
|
|
IDENT = re.compile(r"[A-Za-z_][\w.]*")
|
|
BASE = "."
|
|
|
|
|
|
def clean_line(l):
|
|
s = re.sub(r"//[^\n]*", "", l)
|
|
s = re.sub(r'"(\\.|[^"\\])*"', '""', s)
|
|
s = re.sub(r"'(\\.|[^'\\])*'", "''", s)
|
|
return s
|
|
|
|
|
|
def class_body_flags(p):
|
|
"""(line, in_class_body) per line using a stack over '{' scopes."""
|
|
lines = open(p).read().splitlines(keepends=True)
|
|
stack = []
|
|
out = []
|
|
for l in lines:
|
|
out.append((l, not stack or stack[-1] == "class"))
|
|
c = clean_line(l)
|
|
pos = 0
|
|
while True:
|
|
o = c.find("{", pos)
|
|
cl = c.find("}", pos)
|
|
if o == -1 and cl == -1:
|
|
break
|
|
if cl != -1 and (o == -1 or cl < o):
|
|
if stack:
|
|
stack.pop()
|
|
pos = cl + 1
|
|
else:
|
|
head = c[:o]
|
|
kind = "class" if re.search(r"\b(class|interface|enum|record|@interface)\s+\w", head) else "other"
|
|
stack.append(kind)
|
|
pos = o + 1
|
|
return out
|
|
|
|
|
|
def build_maps():
|
|
typemap, cfiles = {}, {}
|
|
for dp, dns, fns in os.walk(BASE):
|
|
for fn in fns:
|
|
if not fn.endswith(".java"):
|
|
continue
|
|
p = os.path.join(dp, fn)
|
|
cfiles.setdefault(fn[:-5], p)
|
|
txt = open(p).read()
|
|
for m in re.finditer(r"^ {0,8}(?:public\s+|private\s+|protected\s+|static\s+|final\s+|abstract\s+|sealed\s+)*(class|interface|enum|record)\s+(\w+)", txt, re.M):
|
|
typemap.setdefault(m.group(2), p)
|
|
return typemap, cfiles
|
|
|
|
|
|
def promote(typemap, cfiles, cls, member):
|
|
p = typemap.get(cls) or cfiles.get(cls)
|
|
if not p:
|
|
return False
|
|
for i, (l, in_class) in enumerate(class_body_flags(p)):
|
|
if not in_class:
|
|
continue
|
|
s = l.lstrip()
|
|
ind = l[:len(l) - len(s)]
|
|
if ind not in (" ", " "):
|
|
continue
|
|
if s.startswith(("public ", "protected ", "private ", "@", "//", "*", "}", "{")):
|
|
continue
|
|
if re.match(r"^(?:(?:public|static|final|abstract)\s+)*(class|interface|enum|record)\s+%s\b" % re.escape(member), s):
|
|
lines = open(p).read().splitlines(keepends=True)
|
|
lines[i] = ind + "public " + s + "\n"
|
|
open(p, "w").write("".join(lines))
|
|
return True
|
|
# constructor of a nested class named `member`
|
|
if re.match(r"^%s\s*\(" % re.escape(member), s):
|
|
lines = open(p).read().splitlines(keepends=True)
|
|
lines[i] = ind + "public " + s + "\n"
|
|
open(p, "w").write("".join(lines))
|
|
return True
|
|
m = re.search(r"(?<![\w.])%s\b\s*(\(|=|;|,)" % re.escape(member), s)
|
|
if not m or not s[:m.start()].strip():
|
|
continue
|
|
toks = s[:m.start()].replace("<", " < ").replace(">", " > ").replace(",", " , ").split()
|
|
ok = bool(toks)
|
|
for t in toks:
|
|
b = IDENT.match(t)
|
|
core = b.group(0) if b else ""
|
|
if core in MODS or core in PRIMS or (core and core[0].isupper()) or t in ("<", ">", ",", "?", "extends"):
|
|
continue
|
|
ok = False
|
|
break
|
|
if not ok:
|
|
continue
|
|
lines = open(p).read().splitlines(keepends=True)
|
|
if s.startswith("private "):
|
|
s = s[len("private "):]
|
|
lines[i] = ind + "public " + s + ("\n" if l.endswith("\n") else "")
|
|
open(p, "w").write("".join(lines))
|
|
return True
|
|
return False
|
|
|
|
|
|
def main():
|
|
global BASE
|
|
BASE = sys.argv[1] if len(sys.argv) > 1 else BASE
|
|
typemap, cfiles = build_maps()
|
|
for it in range(150):
|
|
r = subprocess.run(["./gradlew", "compileJava", "compileTestJava", "--offline", "-q"],
|
|
capture_output=True, text=True)
|
|
err = r.stderr + r.stdout
|
|
if r.returncode == 0:
|
|
print("COMPILE GREEN after", it, "iterations")
|
|
return 0
|
|
pend = set()
|
|
for msg, c in re.findall(r"error: (.*?) is not public in (\w+);", err):
|
|
tok = re.sub(r"<N>", "", msg).split("(")[0].split(".")[-1].strip()
|
|
if tok:
|
|
pend.add((tok, c))
|
|
for msg, c in re.findall(r"reason:\s+(?:<N>)?([\w.]+)\(.*?\) is not public in (\w+);", err):
|
|
pend.add((msg.split(".")[-1], c))
|
|
for m2, c2 in re.findall(r"method ([\w]+) in class (\w+) cannot be accessed", err):
|
|
pend.add((m2, c2))
|
|
for m2, c2 in re.findall(r"([A-Z]\w+)\.[\w.]* is defined in an inaccessible class", err):
|
|
pass
|
|
for cls_name in re.findall(r"([A-Z]\w*) is defined in an inaccessible class or interface", err):
|
|
pend.add((cls_name, cls_name))
|
|
done = 0
|
|
for mem, cls in sorted(pend):
|
|
if promote(typemap, cfiles, cls, mem):
|
|
done += 1
|
|
typemap, cfiles = build_maps()
|
|
if done == 0:
|
|
print("STUCK at iter", it)
|
|
seen, uniq = set(), []
|
|
for line in err.splitlines():
|
|
if "error:" in line and line not in seen:
|
|
seen.add(line)
|
|
uniq.append(line)
|
|
for u in uniq[:30]:
|
|
print(" ", u.replace("/storage/project/jvm/LoVisual/combatant-client-26.2/", "")[:170])
|
|
return 1
|
|
print(f"iter {it}: promoted {done}/{len(pend)}")
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|