109 lines
4.9 KiB
Python
109 lines
4.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""扫描 TPV .vp 文件:找出"跨模块前缀引用但未 import"的模块(识别 as 别名)。
|
|
用法: python _check_imports.py
|
|
"""
|
|
import os
|
|
import re
|
|
|
|
ROOT = r"d:\Users\TermiNexus\Desktop\TransPyC\TransPyV\App\lib\core"
|
|
DIRS = [os.path.join(ROOT, "Gen"), os.path.join(ROOT, "Handles")]
|
|
# 忽略列表:基础库/枚举成员/llvmlite 属性/类名(大写开头且非模块)
|
|
IGNORE = {
|
|
"ast", "t", "c", "stdint", "stdio", "string", "stdlib", "memhub", "llvmlite",
|
|
"viperlib", "sys", "math", "time", "hashlib", "vthreading", "subprocess",
|
|
"argparse", "w32", "fileio", "win32", "win32console", "win32file",
|
|
"win32base", "win32process", "win32sync", "win32thread", "win32time",
|
|
"win32heap", "win32job", "win32namedpipe", "win32registry", "win32security",
|
|
"win32service", "win32socket", "win32handle", "win32pipe", "win32io",
|
|
"ASTKind", "ASTCtx", "OpKind", "CONST_NONE", "CONST_INT", "CONST_FLOAT",
|
|
"CONST_STR", "CONST_BOOL", "MODE", "ASM_DESCR", "Alloca", "Subscript",
|
|
"DefaultVal", "Arguments", "GenericClassFiles", "GenericClassNames",
|
|
"GenericClassNodes", "GenericClassSha1s", "GenericTpNames", "GenericTypeArgs",
|
|
"CDefineNames", "CDefineValues", "CDefineDoubleFlags", "CDefineStrFlags",
|
|
"XmodCdefNames", "XmodCdefValues", "XmodCdefDoubleFlags", "XmodCdefStrFlags",
|
|
"CTypedefNames", "CTypedefTypeStrs", "CTypedefVisiting", "VisibleStructs",
|
|
"Node", "Pool", "T", "Current", "Scope", "Constant", "List", "Int", "Struct",
|
|
"LocalClass", "RemoteClass", "Trans", "ExprHandle", "Type", "Value", "Function",
|
|
"BasicBlock", "Param", "ParamNode", "GlobalVariable", "LLVMType", "IRBuilder",
|
|
"LLVMModule", "MemBuddy", "Translator", "Generator", "Logger", "File",
|
|
"SymbolTable", "VarEntry", "StructEntry", "FieldEntry", "EnumEntry",
|
|
"EnumMember", "AsmOperand", "FuncEntry", "FuncDefaultsEntry", "TraceFrame",
|
|
"Mixin", "TypeKind", "TypeInfo", "TypeRegistry", "Config", "Exporter",
|
|
"Module", "State", "Default", "Utf8", "Case", "Error", "Handle",
|
|
}
|
|
# Gen Mixin 自引用(同包内类名)
|
|
GEN_MIXINS = {
|
|
"Generator", "BaseGenMixin", "TypeGenMixin", "TypeGenBase", "TypeGenCDef",
|
|
"TypeGenCType", "TypeGenResolve", "TypeGenErr", "StructGenMixin",
|
|
"ExprGenMixin", "ExprGenBase", "ExprGenConst", "ExprGenFstr", "ExprGenOps",
|
|
"ExprGenCdef", "ExprGenName", "ExprGenAttr", "ExprGenCls", "CallGenMixin",
|
|
"CallGenBase", "CallGenLeafKit", "CallGenCBuiltin", "CallGenCtor", "CallGenCall",
|
|
"CallGenProp", "CallGenFd", "CallGenVt", "CallGenVa", "CallGenLib",
|
|
"CallGenDispatch", "FuncGenBase", "FuncGenDef", "FuncGenMixin", "ClassGenMixin",
|
|
"ClassGenBase", "ClassGenEnum", "ClassGenGeneric", "ClassGenVTable",
|
|
"ClassGenDef", "ImportsGenMixin", "StmtGenMixin", "StmtGenDeclMixin",
|
|
"StmtGenCifMixin", "AssignGenMixin", "VarGenMixin", "TranslatorGenMixin",
|
|
"MatchGenMixin", "GenGenerator",
|
|
}
|
|
# 单字母/短名枚举等
|
|
SHORT = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
|
|
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
|
"T", "U", "V", "W", "X", "Y", "Z", "N", "M", "I", "J", "K", "L", "O",
|
|
"P", "Q", "R", "S", "A", "B", "C", "D", "E", "F", "G", "H"}
|
|
|
|
def collect():
|
|
result = {}
|
|
pat_import = re.compile(r'^\s*(?:import|from)\s+([\w\.]+)(?:\s+as\s+(\w+))?')
|
|
pat_ref = re.compile(r'\b([A-Z][A-Za-z0-9_]*)\s*\.')
|
|
for d in DIRS:
|
|
for fn in sorted(os.listdir(d)):
|
|
if not fn.endswith(".vp"):
|
|
continue
|
|
fp = os.path.join(d, fn)
|
|
with open(fp, encoding="utf-8", errors="replace") as f:
|
|
lines = f.readlines()
|
|
imports = set()
|
|
refs = set()
|
|
for ln in lines:
|
|
s = ln.strip()
|
|
if s.startswith("#"):
|
|
continue
|
|
m = pat_import.match(s)
|
|
if m:
|
|
mod = m.group(1)
|
|
alias = m.group(2)
|
|
short = mod.split(".")[-1]
|
|
if alias:
|
|
imports.add(alias)
|
|
imports.add(short)
|
|
imports.add(mod)
|
|
continue
|
|
for rm in pat_ref.finditer(ln):
|
|
refs.add(rm.group(1))
|
|
result[fp] = (imports, refs)
|
|
return result
|
|
|
|
def main():
|
|
files = collect()
|
|
print("=== 使用但未 import(已去误报) ===")
|
|
any_hit = False
|
|
for fp, (imports, refs) in files.items():
|
|
missing = []
|
|
for r in sorted(refs):
|
|
if r in IGNORE or r in GEN_MIXINS or r in SHORT:
|
|
continue
|
|
if r in imports:
|
|
continue
|
|
missing.append(r)
|
|
if missing:
|
|
any_hit = True
|
|
print(f"\n{os.path.relpath(fp, ROOT)}")
|
|
for m in missing:
|
|
print(f" MISSING: {m}")
|
|
if not any_hit:
|
|
print("(无)")
|
|
print("\n=== 完成 ===")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|