fix: vpi stub 注解解析改用被读模块自己的 imports 上下文,根治跨模块误报
This commit is contained in:
1 parent
95a52bb9f6
commit
3197152d4e
1 file changed
+109
-4
@@ -437,6 +437,60 @@ def _extract_sha1_from_path(vpi_path: str) -> str:
|
||||
return sha1_buf
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _stub_add_imported - 追加模块名到空格分隔列表(stub 上下文收集用)
|
||||
#
|
||||
# 与 HandlesImports.add_imported_module 逻辑一致,但内联在本模块,
|
||||
# 避免 VpiReader → HandlesImports → StubMerger → VpiReader 循环依赖。
|
||||
# ============================================================
|
||||
def _stub_add_imported(pool: memhub.MemBuddy | t.CPtr,
|
||||
cur: str, name: str) -> str:
|
||||
"""追加模块名到空格分隔列表(pool 分配),返回新列表"""
|
||||
if name is None:
|
||||
return cur
|
||||
if cur is None:
|
||||
nlen: t.CSizeT = string.strlen(name)
|
||||
buf: str = pool.alloc(nlen + 1)
|
||||
if buf is not None:
|
||||
string.strcpy(buf, name)
|
||||
return buf
|
||||
old_len: t.CSizeT = string.strlen(cur)
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
buf2: str = pool.alloc(old_len + 1 + name_len + 1)
|
||||
if buf2 is not None:
|
||||
string.strcpy(buf2, cur)
|
||||
buf2[old_len] = ' '
|
||||
string.strcpy(buf2 + old_len + 1, name)
|
||||
return buf2
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _stub_add_from - 追加 from-import 映射("local:mod[:orig]" 空格分隔)
|
||||
# ============================================================
|
||||
def _stub_add_from(pool: memhub.MemBuddy | t.CPtr,
|
||||
cur: str, local: str, mod: str, orig: str) -> str:
|
||||
"""追加 from-import 映射(pool 分配),返回新列表"""
|
||||
if local is None or mod is None:
|
||||
return cur
|
||||
entry: str = pool.alloc(256)
|
||||
if entry is None:
|
||||
return cur
|
||||
if orig is not None and string.strcmp(orig, local) != 0:
|
||||
viperlib.snprintf(entry, 256, "%s:%s:%s", local, mod, orig)
|
||||
else:
|
||||
viperlib.snprintf(entry, 256, "%s:%s", local, mod)
|
||||
if cur is None:
|
||||
return entry
|
||||
old_len: t.CSizeT = string.strlen(cur)
|
||||
entry_len: t.CSizeT = string.strlen(entry)
|
||||
buf: str = pool.alloc(old_len + 1 + entry_len + 1)
|
||||
if buf is not None:
|
||||
string.strcpy(buf, cur)
|
||||
buf[old_len] = ' '
|
||||
string.strcpy(buf + old_len + 1, entry)
|
||||
return buf
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ParseVpiIntoModule - 解析 .vpi 文件,将函数声明注入到当前模块
|
||||
#
|
||||
@@ -486,10 +540,6 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy | t.CPtr,
|
||||
if pool is None or mod is None or vpi_path is None or trans is None:
|
||||
return 0
|
||||
|
||||
# 获取当前翻译器的导入信息(供 resolve_annotation_type 使用)
|
||||
imported_modules: str = trans._imported_modules
|
||||
from_imports: str = trans._from_imports
|
||||
|
||||
# 1. 读取 .vpi 文件
|
||||
f: fileio.File | t.CPtr = fileio.File(vpi_path, fileio.MODE.R)
|
||||
if f.closed:
|
||||
@@ -539,6 +589,61 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy | t.CPtr,
|
||||
return 1
|
||||
n: t.CSizeT = ch.__len__()
|
||||
|
||||
# 收集 stub 内被读模块自己的 import 语句,构建独立的注解解析上下文。
|
||||
# .vpi stub 顶部含被读模块的 import(Converter 已写入,如 string.vp 的
|
||||
# "import t, c"),用它替代当前模块的 imported_modules/from_imports 去
|
||||
# 解析注解——根治跨上下文误报(如 t.CArray[str] 需要 't' 已导入)。
|
||||
stub_imported_modules: str = None
|
||||
stub_from_imports: str = None
|
||||
si: t.CSizeT
|
||||
for si in range(n):
|
||||
schild: ast.AST | t.CPtr = ch.get(si)
|
||||
if schild is None:
|
||||
continue
|
||||
sk: int = schild.kind()
|
||||
if sk == ast.ASTKind.Import:
|
||||
simp: ast.Import | t.CPtr = (ast.Import | t.CPtr)(schild)
|
||||
if simp.names is not None:
|
||||
sn_n: t.CSizeT = simp.names.__len__()
|
||||
sni: t.CSizeT
|
||||
for sni in range(sn_n):
|
||||
sal: ast.Alias | t.CPtr = (ast.Alias | t.CPtr)(simp.names.get(sni))
|
||||
if sal is not None and sal.name is not None:
|
||||
stub_imported_modules = _stub_add_imported(
|
||||
pool, stub_imported_modules, sal.name)
|
||||
if sal.asname is not None:
|
||||
stub_imported_modules = _stub_add_imported(
|
||||
pool, stub_imported_modules, sal.asname)
|
||||
elif sk == ast.ASTKind.ImportFrom:
|
||||
sifr: ast.ImportFrom | t.CPtr = (ast.ImportFrom | t.CPtr)(schild)
|
||||
sifr_mod: str = sifr.module
|
||||
if sifr_mod is not None:
|
||||
stub_imported_modules = _stub_add_imported(
|
||||
pool, stub_imported_modules, sifr_mod)
|
||||
if sifr.names is not None:
|
||||
sifr_nn: t.CSizeT = sifr.names.__len__()
|
||||
sifri: t.CSizeT
|
||||
for sifri in range(sifr_nn):
|
||||
sial: ast.Alias | t.CPtr = (ast.Alias | t.CPtr)(sifr.names.get(sifri))
|
||||
if sial is not None and sial.name is not None:
|
||||
# '*' star import 不建 from 映射(lookup 有 star 回退)
|
||||
if string.strcmp(sial.name, "*") != 0:
|
||||
slocal: str = sial.name
|
||||
sorig: str = None
|
||||
if sial.asname is not None:
|
||||
slocal = sial.asname
|
||||
sorig = sial.name
|
||||
stub_from_imports = _stub_add_from(
|
||||
pool, stub_from_imports, slocal, sifr_mod, sorig)
|
||||
|
||||
# 用 stub 自己的 imports 替代当前模块的(stub 注解解析上下文正确性)
|
||||
imported_modules: str = trans._imported_modules
|
||||
from_imports: str = trans._from_imports
|
||||
if stub_imported_modules is not None:
|
||||
imported_modules = stub_imported_modules
|
||||
if stub_from_imports is not None:
|
||||
from_imports = stub_from_imports
|
||||
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
|
||||
Reference in new issue
Block a user