fix(phase1): 容器扫描覆盖表达式字段,修复 _list/_dict 按需注入失效
TPV 的 AST 中表达式/注解树挂在结构体字段(value/slice/func/args/ annotation/targets/returns/bases/left/right),只有语句块在 children。 原 _ScanTreeForContainers 只递归 children,漏掉 list[...] | t.CPtr (BinOp 包裹)、list[...](...)(Call.func)、字段注解等,导致 base.vp 等 includes 的 list/dict 使用检测不到,_list 不进可达集合,泛型模板 未注册。重写为字段递归 + children 递归,覆盖全部表达式承载点。
This commit is contained in:
1 parent
dfb86380a6
commit
f09b6962f9
1 file changed
+102
-7
+102
-7
@@ -229,14 +229,17 @@ def _FindClassDefSha1(class_names_buf: bytes, def_sha1s_buf: bytes,
|
||||
# ============================================================
|
||||
# _ScanTreeForContainers - 递归扫描 AST 检测 list/dict 容器使用
|
||||
#
|
||||
# 覆盖:裸名(list/dict)、泛型下标(list[T] 的 Subscript.value)、
|
||||
# 字面量([]/{})。命中即置 need_list/need_dict 标志。
|
||||
# 误报无害(最多多编译 _list/_dict 两个空壳模块)。
|
||||
# TPV 的 AST 中,语句块挂在 children,而表达式/注解树全部以结构体
|
||||
# 字段挂载(value/slice/func/args/annotation/targets/returns/bases/
|
||||
# left/right 等)。只递归 children 会漏掉 list[...] | t.CPtr(BinOp
|
||||
# 包裹)、list[...](...)(Call.func)、字段注解等一切非语句块位置。
|
||||
# 因此每个节点先递归其表达式承载字段,再递归 children 语句块。
|
||||
# 命中即置 need_list/need_dict;误报无害(最多多编译两个空壳模块)。
|
||||
# ============================================================
|
||||
def _ScanTreeForContainers(node: ast.AST | t.CPtr,
|
||||
need_list_box: t.CPtr,
|
||||
need_dict_box: t.CPtr):
|
||||
"""递归扫描 AST,检测 list/dict 容器使用"""
|
||||
"""递归扫描 AST(字段 + 语句块),检测 list/dict 容器使用"""
|
||||
if node is None:
|
||||
return
|
||||
k_s: int = node.kind()
|
||||
@@ -249,15 +252,107 @@ def _ScanTreeForContainers(node: ast.AST | t.CPtr,
|
||||
need_dict_box[0] = 1
|
||||
elif k_s == ast.ASTKind.Subscript:
|
||||
sub_s: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
|
||||
if sub_s.value is not None:
|
||||
_ScanTreeForContainers(sub_s.value, need_list_box, need_dict_box)
|
||||
_ScanTreeForContainers(sub_s.value, need_list_box, need_dict_box)
|
||||
_ScanTreeForContainers(sub_s.slice, need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.BinOp:
|
||||
bop_s: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
_ScanTreeForContainers(bop_s.left, need_list_box, need_dict_box)
|
||||
_ScanTreeForContainers(bop_s.right, need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.Call:
|
||||
cl_s2: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||||
_ScanTreeForContainers(cl_s2.func, need_list_box, need_dict_box)
|
||||
cl_args_s: list[ast.AST | t.CPtr] | t.CPtr = cl_s2.args
|
||||
if cl_args_s is not None:
|
||||
na_s: t.CSizeT = len(cl_args_s)
|
||||
i_a2: t.CSizeT
|
||||
for i_a2 in range(na_s):
|
||||
_ScanTreeForContainers(cl_args_s.get(i_a2), need_list_box, need_dict_box)
|
||||
cl_kws_s: list[ast.AST | t.CPtr] | t.CPtr = cl_s2.keywords
|
||||
if cl_kws_s is not None:
|
||||
nk_s: t.CSizeT = len(cl_kws_s)
|
||||
i_k2: t.CSizeT
|
||||
for i_k2 in range(nk_s):
|
||||
kw_s: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(cl_kws_s.get(i_k2))
|
||||
if kw_s is not None:
|
||||
_ScanTreeForContainers(kw_s.value, need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.Assign:
|
||||
asn_s: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(node)
|
||||
_ScanTreeForContainers(asn_s.value, need_list_box, need_dict_box)
|
||||
tgts_s: list[ast.AST | t.CPtr] | t.CPtr = asn_s.targets
|
||||
if tgts_s is not None:
|
||||
nt_s: t.CSizeT = len(tgts_s)
|
||||
i_t2: t.CSizeT
|
||||
for i_t2 in range(nt_s):
|
||||
_ScanTreeForContainers(tgts_s.get(i_t2), need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.AnnAssign:
|
||||
aa_s2: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
_ScanTreeForContainers(aa_s2.annotation, need_list_box, need_dict_box)
|
||||
_ScanTreeForContainers(aa_s2.value, need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.FunctionDef:
|
||||
fn_s: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node)
|
||||
_ScanTreeForContainers(fn_s.returns, need_list_box, need_dict_box)
|
||||
fn_args_s: ast.Arguments | t.CPtr = fn_s.args
|
||||
if fn_args_s is not None:
|
||||
fa_s: list[ast.AST | t.CPtr] | t.CPtr = fn_args_s.args
|
||||
if fa_s is not None:
|
||||
nf_s: t.CSizeT = len(fa_s)
|
||||
i_f2: t.CSizeT
|
||||
for i_f2 in range(nf_s):
|
||||
arg_s: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(fa_s.get(i_f2))
|
||||
if arg_s is not None:
|
||||
_ScanTreeForContainers(arg_s.annotation, need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.ClassDef:
|
||||
cd_s: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(node)
|
||||
bases_s: list[ast.AST | t.CPtr] | t.CPtr = cd_s.bases
|
||||
if bases_s is not None:
|
||||
nb_s: t.CSizeT = len(bases_s)
|
||||
i_b2: t.CSizeT
|
||||
for i_b2 in range(nb_s):
|
||||
_ScanTreeForContainers(bases_s.get(i_b2), need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.Attribute:
|
||||
at_s: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
_ScanTreeForContainers(at_s.value, need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.Tuple:
|
||||
tu_s: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(node)
|
||||
elts_s: list[ast.AST | t.CPtr] | t.CPtr = tu_s.elts
|
||||
if elts_s is not None:
|
||||
ne_s: t.CSizeT = len(elts_s)
|
||||
i_e2: t.CSizeT
|
||||
for i_e2 in range(ne_s):
|
||||
_ScanTreeForContainers(elts_s.get(i_e2), need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.UnaryOp:
|
||||
uop_s: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
|
||||
_ScanTreeForContainers(uop_s.operand, need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.Expr:
|
||||
ex_s: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node)
|
||||
_ScanTreeForContainers(ex_s.value, need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.Return:
|
||||
rt_s: ast.Return | t.CPtr = (ast.Return | t.CPtr)(node)
|
||||
_ScanTreeForContainers(rt_s.value, need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.Compare:
|
||||
cp_s: ast.Compare | t.CPtr = (ast.Compare | t.CPtr)(node)
|
||||
_ScanTreeForContainers(cp_s.left, need_list_box, need_dict_box)
|
||||
cps_s: list[ast.AST | t.CPtr] | t.CPtr = cp_s.comparators
|
||||
if cps_s is not None:
|
||||
nc_s: t.CSizeT = len(cps_s)
|
||||
i_c2: t.CSizeT
|
||||
for i_c2 in range(nc_s):
|
||||
_ScanTreeForContainers(cps_s.get(i_c2), need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.BoolOp:
|
||||
bo_s: ast.BoolOp | t.CPtr = (ast.BoolOp | t.CPtr)(node)
|
||||
bvs_s: list[ast.AST | t.CPtr] | t.CPtr = bo_s.values
|
||||
if bvs_s is not None:
|
||||
nv_s: t.CSizeT = len(bvs_s)
|
||||
i_v2: t.CSizeT
|
||||
for i_v2 in range(nv_s):
|
||||
_ScanTreeForContainers(bvs_s.get(i_v2), need_list_box, need_dict_box)
|
||||
elif k_s == ast.ASTKind.List:
|
||||
# [] 字面量
|
||||
need_list_box[0] = 1
|
||||
elif k_s == ast.ASTKind.Dict:
|
||||
# {} 字面量
|
||||
need_dict_box[0] = 1
|
||||
# 递归子节点
|
||||
# 递归语句块子节点
|
||||
if node.children is not None:
|
||||
ch_s: list[ast.AST | t.CPtr] | t.CPtr = node.children
|
||||
n_s: t.CSizeT = len(ch_s)
|
||||
|
||||
Reference in new issue
Block a user