# -*- coding: utf-8 -*- """删掉指定名字的 Java 方法(按大括号配对,不用正则瞎猜)。 == 为什么不用正则 == 方法体里可能有字符串、注释、嵌套大括号。正则很难正确跳过这些, 删一半会把文件搞坏。这里做一个**简单但正确**的扫描器: * 逐字符走 * 跳过 `//` 行注释、`/* */` 块注释、`"..."` 字符串、`'c'` 字符字面量 * 统计 `{` `}` 深度,深度回到 0 就是方法结束 * 顺便把方法**前面的 javadoc / 注解行**一起删干净(否则留下一堆 没头没脑的注释) == 安全措施 == * 名字必须能唯一定位到一个方法定义 * 删完立刻检查大括号总数是否守恒(删之前总的 `{`/`}` 数减去 这个方法里的数量,应该等于删之后的) * 任何一步不对就抛异常,不写文件 """ from __future__ import annotations import re import sys from pathlib import Path JAVA = (Path(__file__).resolve().parent.parent / "android" / "src" / "com" / "lanremote" / "watch" / "MainActivity.java") def find_method_span(text: str, name: str): """返回 (start, end) —— 整个方法(含前面的注释/注解)的字符区间。""" # 找到定义行 pat = re.compile( r"^[ \t]*(?:@\w+(?:\([^)]*\))?\s*)*" r"(?:private|protected|public|static|final|synchronized|\s)*" r"(?:[\w<>\[\],.?\s]+?)\s+" + re.escape(name) + r"\s*\([^)]*\)\s*" r"(?:throws [\w,.\s]+)?\s*\{", re.M) matches = list(pat.finditer(text)) if len(matches) != 1: raise SystemExit("✗ %s: 找到 %d 个定义(要恰好 1 个)" % (name, len(matches))) m = matches[0] def_start = m.start() # 往上吃掉紧邻的注释行和注解行 line_start = text.rfind("\n", 0, def_start) + 1 start = line_start while True: prev_end = start - 1 if prev_end <= 0: break prev_start = text.rfind("\n", 0, prev_end) + 1 line = text[prev_start:prev_end].strip() if not line: break if (line.startswith(("*", "//", "/*")) or line.endswith("*/") or line.startswith("@")): start = prev_start continue break # 从 { 开始找匹配的 } i = text.index("{", m.start()) depth = 0 n = len(text) while i < n: ch = text[i] # 行注释 if ch == "/" and i + 1 < n and text[i + 1] == "/": i = text.find("\n", i) if i < 0: raise SystemExit("✗ %s: 行注释没结束" % name) continue # 块注释 if ch == "/" and i + 1 < n and text[i + 1] == "*": i = text.find("*/", i + 2) if i < 0: raise SystemExit("✗ %s: 块注释没结束" % name) i += 2 continue # 字符串 if ch == '"': i += 1 while i < n and text[i] != '"': if text[i] == "\\": i += 1 i += 1 i += 1 continue # 字符字面量 if ch == "'": i += 1 while i < n and text[i] != "'": if text[i] == "\\": i += 1 i += 1 i += 1 continue if ch == "{": depth += 1 elif ch == "}": depth -= 1 if depth == 0: return start, i + 1 i += 1 raise SystemExit("✗ %s: 大括号没配平" % name) def main() -> int: names = sys.argv[1:] if not names: print("用法: find_orphans.py <方法名> [方法名...]") return 1 text = JAVA.read_text(encoding="utf-8") before_open = text.count("{") before_close = text.count("}") removed_total = 0 for name in names: start, end = find_method_span(text, name) chunk = text[start:end] removed_total += chunk.count("{") # 连同后面的空行一起删 tail = end while tail < len(text) and text[tail] in "\r\n": tail += 1 text = text[:start] + text[tail:] print(" ✓ 删除 %-22s %4d 字符" % (name, tail - start)) # 大括号守恒检查 if text.count("{") != before_open - removed_total: raise SystemExit("✗ 大括号数量不对(删前 %d,删掉 %d,现在 %d)" % (before_open, removed_total, text.count("{"))) if text.count("{") != text.count("}"): raise SystemExit("✗ 大括号不配对:{ %d 个,} %d 个" % (text.count("{"), text.count("}"))) JAVA.write_text(text, encoding="utf-8", newline="\n") print() print(" 大括号守恒 ✓({%d / }%d)" % (text.count("{"), text.count("}"))) return 0 if __name__ == "__main__": sys.exit(main())