fix(vipeye): 修复 REnum 变体字段语义高亮为 property

REnum 变体字段(如 LLVMType.Ptr 的 Pointee)常规声明查找找不到,语义 token 误显示 undefined。根因:描述符协议在 Viper 结构体字段上失效,CPtr 等 C 类型类的 __get__ 查找返回 Unknown 而非 undefined,把字段类型(Value.Ty)污染为 Unknown,导致 x.Ty.Pointee 无法解析。

- typeEvaluator: applyDescriptorAccessMethod 的 isAnyOrUnknown 分支在 Viper 方言下返回 memberType 保留原始字段类型;新增 REnum 变体字段查找辅助(getViperREnumVariantFieldInfo)覆盖诊断与符号查找
- semanticTokenProvider: 空 declInfo 成员访问时用 getTypeOfExpression 求值,非 Unknown/Unbound 渲染为 property
This commit is contained in:
TermiNexus committed 2026-08-08 11:07:37 +08:00
1 parent 5e07800c7c
commit 2b752a7aec
2 files changed
+101 -2

No files matched your search

@@ -6370,6 +6370,24 @@ export function createTypeEvaluator(
}
}
if (!typeResult) {
// Viper 扩展:REnum 变体字段访问(tagged-union 语义)。
// REnum(t.REnum)的字段定义在嵌套类变体(如 class LLVMType 内的
// class Ptr: Pointee)中,常规类成员查找找不到,需遍历所有
// 嵌套类变体的字段表。放在 getTypeOfBoundMember 之前,避免其
// 先产生 "Attribute is unknown" 诊断。
if (
IsViperDialect(fileInfo.executionEnvironment.dialect) &&
isClassInstance(baseType) &&
isViperREnumClass(baseType)
) {
const variantFieldType = getViperREnumVariantFieldType(baseType, memberName);
if (variantFieldType) {
typeResult = { type: variantFieldType };
}
}
}
if (!typeResult) {
typeResult = getTypeOfBoundMember(
node.d.member,
@@ -7080,6 +7098,17 @@ export function createTypeEvaluator(
if (!isFunctionOrOverloaded(methodType)) {
if (isAnyOrUnknown(methodType)) {
// Viper 扩展:描述符协议(__get__/__set__/__delete__)是 Python 概念,
// Viper 的 C 风格结构体字段不适用。当 `__get__` 查找返回 Unknown/Any
// (而非 undefined,如 CPtr 等 C 类型类上的查找)时,若直接返回该
// Unknown 会污染结构体字段类型(如 `Value.Ty` → Unknown,进而导致
// `elem_ptr.Ty.Pointee` 无法解析)。此时应保留成员原始类型 memberType。
if (
errorNode &&
IsViperDialect(AnalyzerNodeInfo.getFileInfo(errorNode).executionEnvironment.dialect)
) {
return { type: memberType };
}
return { type: methodType };
}
@@ -8551,6 +8580,49 @@ export function createTypeEvaluator(
return grandparentNode?.nodeType === ParseNodeType.Class;
}
// Viper 扩展:判断类类型是否继承自 t.REnum(REnum tagged-union 根类)。
function isViperREnumClass(classType: ClassType): boolean {
return classType.shared.mro.some(
(baseClass) => isClass(baseClass) && baseClass.shared.fullName?.endsWith('.REnum')
);
}
// Viper 扩展:在 REnum 类的所有嵌套类变体中查找字段。
// REnum 字段定义在嵌套类变体(如 class LLVMType 内的 class Ptr: Pointee)中,
// 访问 REnum 实例的成员时按 tagged-union 语义返回匹配变体的字段符号与类型。
function getViperREnumVariantFieldInfo(
renumType: ClassType,
memberName: string
): { symbol: Symbol; type: Type } | undefined {
const symbolTable = ClassType.getSymbolTable(renumType);
for (const symbol of symbolTable.values()) {
const symType = getEffectiveTypeOfSymbolForUsage(
symbol,
/* usageNode */ undefined,
/* useLastDecl */ true
).type;
if (!isClass(symType) || !isViperREnumVariantType(symType)) {
continue;
}
const variantInstance = TypeBase.isInstance(symType) ? symType : ClassType.cloneAsInstance(symType);
const fieldSymbol = ClassType.getSymbolTable(variantInstance).get(memberName);
if (fieldSymbol) {
const fieldType = getEffectiveTypeOfSymbolForUsage(
fieldSymbol,
/* usageNode */ undefined,
/* useLastDecl */ true
).type;
return { symbol: fieldSymbol, type: convertToInstance(fieldType) };
}
}
return undefined;
}
// Viper 扩展:REnum 变体字段类型(仅取类型,见 getViperREnumVariantFieldInfo)。
function getViperREnumVariantFieldType(renumType: ClassType, memberName: string): Type | undefined {
return getViperREnumVariantFieldInfo(renumType, memberName)?.type;
}
// Viper 扩展:构造带 t.CChar 类型别名信息的 int 类型(表示 C 的 char 类型)。
// Viper 中 str/bytes 是 i8* 指针,下标访问/迭代/字符运算返回 t.CChar(int 别名)。
// 优先从 t 模块查找 CChar 类型别名以保留显示信息;找不到时回退为
@@ -23595,6 +23667,17 @@ export function createTypeEvaluator(
}
if (member) {
symbol = member.symbol;
} else if (
IsViperDialect(AnalyzerNodeInfo.getFileInfo(node)?.executionEnvironment.dialect) &&
isViperREnumClass(subtypeForLookup)
) {
// Viper 扩展:REnum 变体字段(如 x.Pointee,字段定义在
// 嵌套类变体 class Ptr 内)常规 lookUpObjectMember 找不到,
// 按 tagged-union 语义在所有嵌套类变体中查找字段符号。
const variantFieldInfo = getViperREnumVariantFieldInfo(subtypeForLookup, memberName);
if (variantFieldInfo) {
symbol = variantFieldInfo.symbol;
}
}
} else if (isModule(subtype)) {
symbol = ModuleType.getField(subtype, memberName);
@@ -609,8 +609,24 @@ class SemanticTokenWalker extends ParseTreeWalker {
tokenType = SemanticTokenTypes.function;
tokenModifiers = 0;
} else if (!declInfo || !declInfo.decls || declInfo.decls.length === 0) {
// 未定义符号 → 白色(默认前景)
tokenType = SemanticTokenTypes.undefined;
// Viper 扩展:REnum 变体字段(如 x.Pointee,字段定义在嵌套类变体
// class Ptr 内)常规声明查找找不到,且 getType 对成员裸名称返回 Unknown;
// 改用成员访问表达式求值获取类型,可求值时显示为 property 而非未定义白色。
if (this._isViperMemberAccess(node)) {
const memberAccessType = this._evaluator.getTypeOfExpression(node.parent as MemberAccessNode).type;
if (
memberAccessType !== undefined &&
memberAccessType.category !== TypeCategory.Unknown &&
memberAccessType.category !== TypeCategory.Unbound
) {
tokenType = SemanticTokenTypes.property;
} else {
tokenType = SemanticTokenTypes.undefined;
}
} else {
// 未定义符号 → 白色(默认前景)
tokenType = SemanticTokenTypes.undefined;
}
} else {
const decl: Declaration | undefined = declInfo.decls[0];
const declType = decl?.type;