- refactor(hud/weather/render): Scoreboard 931→240 + Rain 903→159 + UiMeshGeometry 956→99 (8.5.2) - refactor(chams): Chams 985 → 129 + 4×≤195 (8.5.2) - refactor(module): Module 1031 → 139 + 4×≤134 (8.5.2) - refactor(tooltips): BetterTooltips 960 → 181 + 4×≤199 (8.5.2) - refactor(clickgui): ClickGuiPickerState 970→166 + ModulesMenuScreen 966→145 (8.5.2) - refactor(clickgui): CombatProtocolHeuristicsEditorState 932→79 + 4×≤192 (8.5.2) - refactor(hud): CompactHudStatModel 894 → 125 + 4×≤175 (8.5.2) - refactor(iris): ShaderPatchCompiler 843→66 + 4×≤174 (8.5.2) - refactor(tab): CustomTabList 834→136 + 4×≤166 (8.5.2) - refactor(relations): OnlineRelationPlayerPickerComponent 837→74 + 4×≤192 (8.5.2) - refactor(hits): HitEffect 770→120 + 4×≤176 (8.5.2) - refactor(predict): Predictions 815→150 + 4×≤195 (8.5.2) - refactor(config): ConfigProfilesComponent 799→125 + 4×≤195 (8.5.2) - refactor(sim): PlayerMovementSimulation 757→157 + 4×≤194 (8.5.2) - refactor(predict): ProjectilePuncher 747→104 + 3×≤134 (8.5.2) - refactor(crosshair): Crosshair 743→143 + 4×≤167 (8.5.2) - refactor(mediaplayer): MediaPlayer 743→174 + 4×≤196 (8.5.2) - refactor(hud): Itemizer 699→193 + Cooldowns 707→151 (8.5.2) - refactor(hud): Potions 617→176 + 4×≤166 (8.5.2) - refactor(hud): Admins 702→118 + 4×≤138 (8.5.2) - refactor(hud): Keybinds 611→157 + 4×≤160 (8.5.2) - refactor(hud): ModuleList 499→181 + 3×≤150 (8.5.2) - refactor(hud): Radar 392→161 + 2×≤124 (8.5.2) - refactor(hud): Fps 309→168 + 3×≤107 (8.5.2) - refactor(hud): Memory 304→151 + 3×≤144 (8.5.2) - refactor(hud): Tps 339→154 + 3×≤143 (8.5.2) - refactor(hud): Ping 309→145 + 3×≤125 (8.5.2) - refactor(hud): SpeedBps 334→156 + 3×≤142 (8.5.2) - refactor(hud): GameTime 314→150 + 3×≤127 (8.5.2) - refactor(hud): SystemTime 300→136 + 3×≤130 (8.5.2) - refactor(hud): Coordinates 337→174 + 2×≤172 (8.5.2) - refactor(hud): Armor 324→162 + 2×≤148 (8.5.2) - refactor(hud): Inventory 476→153 + 3×≤181 (8.5.2) - docs(todo): обновлён 8.5.2 — отмечены готовые гиганты (BetterButtons/InventorySwap/Svg/Темы/WorldParticles/Module/Chams и хвост) - docs(api): папка combatant-client-26.2/docs + addons.md (API можно ломать при рефакторе) - refactor(visuals): BlockHighlight 692→271 + 4×≤200 (8.5.2) - refactor(mixins): GameRendererMixin 830→344 (хуки) + 4 хелпера (8.5.2) - refactor(visuals): WorldParticles 821→260 + 6×≤200, режимы добиты (8.5.2) - docs(todo): 8.5.2 — WorldParticles/GameRendererMixin/BlockHighlight отмечены ГОТОВО - refactor(render): MeshBuilder 738→447 (фасад write-API) + 3 хелпера, FrameStats снесён (8.5.2) - docs(todo): Фаза 10 — дизайн платформы (аккаунты/конфиги/аватарки), backlog RPC-чата - docs(todo): Подсистема 3 — Аддоны 2.0 (скрипты/версии) + витрина аддонов + админка - docs(todo): Подсистема 2 — RPC-чат/друзья/виджеты-телеметрия + рейт-лимиты, доп. правки Подсистемы 3 - chore: переименование combatant-client-26.2 -> mod, добавлены backend/ и frontend/ - docs(backend): implementation plan for accounts-service (Подсистема 1, часть 1) - chore: пересоздать backend/frontend через cargo new и bun create vite + tailwind; убрать таблицу компонентов из TODO.md - docs(backend): edition 2024 в плане вместо 2021 - chore: обновить версии до реально актуальных (проверено компиляцией) - docs: правила платформы (лимит 250 строк, антипаттерны backend/frontend по итогам ресёрча) + frontend/ARCHITECTURE.md - docs: добавить правило ≤4 файла на папку в правила платформы (backend/frontend) - docs: commit messages in English from now on - chore: gitignore .superpowers/ scratch directory - docs: commit messages in English from now on (mod) - feat(backend): scaffold accounts-service with health check - chore(backend): remove target/ build artifacts from git, add gitignore - chore: track docs/ in git (was accidentally gitignored, never committed) - chore(backend): convert to Cargo workspace, plan full microservice layout - feat(backend): accounts/avatars/device_links schema + migration - feat(backend): argon2id password hashing
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())
|