fix(lsp): 包的 __init__ 重导出成员可解析
A 是包时 A/__init__.vp 里的 from .leaf import b 被模块链直接跳过:_ChainFromModule 看到 __init__.vp 就切到包目录,只找子模块。改为先在 __init__ 的模块作用域解析该名字(含 from-import 重导出),未命中再下钻子模块。gate10 增加包重导出 token/跳转断言。
This commit is contained in:
1 parent
4e3331d442
commit
b81e4ae3bf
5 files changed
+35
-8
No files matched your search
+11
-8
@@ -874,19 +874,22 @@ def _ChainFromModule(ws: LspWorkspace.LspWorkspace*, pool: memhub.MemManager*,
|
||||
hops: int) -> LspTarget*:
|
||||
segs: str = rest
|
||||
while segs is not None:
|
||||
if cur_is_file != 0:
|
||||
base: str = LspFiles.BaseName(pool, cur)
|
||||
if base is not None and string.strcmp(base, "__init__.vp") == 0:
|
||||
# A package's __init__.vp is not a symbol table for its submodules; descend from
|
||||
# the package directory for the remaining dotted segments.
|
||||
cur = LspFiles.DirName(pool, cur)
|
||||
cur_is_file = 0
|
||||
continue
|
||||
h: str = None
|
||||
r: str = None
|
||||
LspSymbols._SplitHead(pool, segs, &h, &r)
|
||||
if h is None:
|
||||
return None
|
||||
if cur_is_file != 0:
|
||||
base: str = LspFiles.BaseName(pool, cur)
|
||||
if base is not None and string.strcmp(base, "__init__.vp") == 0:
|
||||
# A package's __init__.vp can re-export members (`from .leaf import X`).
|
||||
# Try those first; only descend into the package directory when the name is
|
||||
# not a member (then it may be a submodule/package).
|
||||
pkg_member: LspSymbols.LspSymbol* = ResolveInFile(pool, table_pool, cur, None, h)
|
||||
if pkg_member is None:
|
||||
cur = LspFiles.DirName(pool, cur)
|
||||
cur_is_file = 0
|
||||
continue
|
||||
if cur_is_file != 0:
|
||||
member: LspSymbols.LspSymbol* = ResolveInFile(pool, table_pool, cur, None, h)
|
||||
if member is None:
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
"""Gate 10 dotted-import package."""
|
||||
from .leaf import reexport_fn
|
||||
@@ -0,0 +1,5 @@
|
||||
"""Gate 10 package re-export leaf module."""
|
||||
|
||||
|
||||
def reexport_fn(x: int) -> int:
|
||||
return x
|
||||
@@ -4,6 +4,7 @@ from .gate10_types import Widget, DOUBLE
|
||||
from .gate10_stub import StubThing
|
||||
from .gate10_extra import *
|
||||
import gate10_types
|
||||
import gate10_pkg
|
||||
import gate10_pkg.sub.mod
|
||||
import gate10_pkg.sub as pkgsub
|
||||
import gate10_pkg.sub as sub
|
||||
@@ -39,6 +40,10 @@ def stub_chain() -> int:
|
||||
return StubThing.count
|
||||
|
||||
|
||||
def reexport_use() -> int:
|
||||
return gate10_pkg.reexport_fn(1)
|
||||
|
||||
|
||||
def else_block(flag: int) -> int:
|
||||
if flag != 0:
|
||||
return 1
|
||||
|
||||
@@ -1522,6 +1522,19 @@ def gate10(exe: str) -> int:
|
||||
raise AssertionError(f"missing definition in {label}: {else_def}")
|
||||
if not else_def[0]["uri"].replace("\\", "/").endswith("gate10_extra.vp"):
|
||||
raise AssertionError(f"wrong definition in {label}: {else_def}")
|
||||
re_pos = _position(text, "gate10_pkg.reexport_fn")
|
||||
re_pos["character"] += len("gate10_pkg.")
|
||||
if not _find_token(sem_tokens, re_pos["line"], re_pos["character"], sem_types.index("function")):
|
||||
raise AssertionError(f"package re-export member is not highlighted: {re_pos}")
|
||||
re_def = client.request(
|
||||
"textDocument/definition",
|
||||
{"textDocument": {"uri": uri}, "position": re_pos},
|
||||
timeout=120.0,
|
||||
).get("result")
|
||||
if not isinstance(re_def, list) or not re_def:
|
||||
raise AssertionError(f"package re-export definition failed: {re_def}")
|
||||
if not re_def[0]["uri"].replace("\\", "/").endswith("gate10_pkg/leaf.vp"):
|
||||
raise AssertionError(f"package re-export definition is wrong: {re_def}")
|
||||
const_pos = _position(text, "EXTRA_CONST")
|
||||
if not _find_token_mods(sem_tokens, const_pos["line"], const_pos["character"],
|
||||
sem_types.index("variable"),
|
||||
|
||||
Reference in new issue
Block a user