# -*- coding: utf-8 -*- """临时:扫描 .vp 源码中真实可能掉出末尾的函数 (有 -> 返回注解、非 extern/export 声明、末句非 return 且非控制流关键字开头)""" import re import glob ROOTS = [ r"D:\Users\TermiNexus\Desktop\TransPyC\TransPyV\App\lib", r"D:\Users\TermiNexus\Desktop\TransPyC\includes", ] pat_def = re.compile(r'^(\s*)def (\w+)\(.*\)\s*(->\s*.+)?:') CTRL = ('if', 'match', 'while', 'for', 'try', 'with', 'return', 'raise', 'pass', 'def', 'class', 'extern', 'export') total = 0 for root in ROOTS: for path in sorted(glob.glob(root + r"\**\*.vp", recursive=True)): lines = open(path, encoding='utf-8').read().split('\n') defs = [] for i, ln in enumerate(lines): m = pat_def.match(ln) if m: defs.append((i, m.group(2), m.group(3), len(m.group(1)))) for idx, (start, name, ret_ann, indent) in enumerate(defs): if not ret_ann: continue ret = ret_ann.strip() # 排除 extern/export 声明(| t.State / | t.CExport) if '| t.State' in ret or '| t.CExport' in ret: continue # 排除 void 返回(-> None / -> t.CVoid:掉出末尾 ret void 合法) if ret in ('-> None', '-> t.CVoid') or ret.startswith('-> t.CVoid |'): continue end = defs[idx + 1][0] if idx + 1 < len(defs) else len(lines) body = lines[start + 1:end] last = None for ln in reversed(body): s = ln.strip() if s and not s.startswith('#'): # 末行缩进必须大于 def 缩进(否则是模块级语句,非函数体) lead = len(ln) - len(ln.lstrip(' ')) if lead <= indent: last = None break last = s break if last is None or last.startswith('return'): continue # 排除 docstring 误报(末行是字符串字面量 docstring) if last.startswith('"""') or last.startswith("'''"): continue first = last.split('(', 1)[0].split(' ', 1)[0] # 排除"末句是控制流/声明关键字"(TPV 会正确收尾) if first in CTRL: continue print(f"MISS {path}:L{start+1} def {name} {ret} 末行: {last!r}") total += 1 print(f"\n共 {total} 个真实掉出候选(有返回注解 + 末句普通语句)")