From 2b752a7aec0db1c04ebdec07e72fe125c30fcde2 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 8 Aug 2026 11:07:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(vipeye):=20=E4=BF=AE=E5=A4=8D=20REnum=20?= =?UTF-8?q?=E5=8F=98=E4=BD=93=E5=AD=97=E6=AE=B5=E8=AF=AD=E4=B9=89=E9=AB=98?= =?UTF-8?q?=E4=BA=AE=E4=B8=BA=20property?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../src/analyzer/typeEvaluator.ts | 83 +++++++++++++++++++ .../languageService/semanticTokenProvider.ts | 20 ++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/packages/vipeye-internal/src/analyzer/typeEvaluator.ts b/packages/vipeye-internal/src/analyzer/typeEvaluator.ts index 2965ca23..dfa991bb 100644 --- a/packages/vipeye-internal/src/analyzer/typeEvaluator.ts +++ b/packages/vipeye-internal/src/analyzer/typeEvaluator.ts @@ -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); diff --git a/packages/vipeye-internal/src/languageService/semanticTokenProvider.ts b/packages/vipeye-internal/src/languageService/semanticTokenProvider.ts index 326dfaaa..7e5d9189 100644 --- a/packages/vipeye-internal/src/languageService/semanticTokenProvider.ts +++ b/packages/vipeye-internal/src/languageService/semanticTokenProvider.ts @@ -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;