feat(vipeye-internal): __attribute__ 补全/hover 列出未声明的属性名
属性名是编译器级开放集合,补全/hover 原先只枚举 `t.attr`,故 codegen 支持 但未声明的名字(唯一已知例子 stackrealign)看不到。 - viperAttributeUtils:新增 VIPER_UNDECLARED_ATTRIBUTE_NAMES(来源 TransPyV FuncGenBase.vp 的 stackrealign 映射、ViperOS main.vp 实际使用), 以及 getViperAttributeNames(全集,供 hover)与 getViperUndeclaredAttributeNames(仅未声明,供补全注入)——两处共用同一来源, 不会与 t.attr 符号表漂移 - hoverProvider:属性清单改用 getViperAttributeNames - completionProvider:符号表循环后注入未声明属性名(43 项) - 不改存根 t.vpi(沿用既有决定) - viperAttribute.test.ts:既有补全/hover 两用例各加 stackrealign 断言 - CHANGELOG:1.1.426 追加 1 条
This commit is contained in:
1 parent
71cb333549
commit
c7878ab9d7
5 files changed
+54
-7
No files matched your search
@@ -138,7 +138,11 @@ import {
|
||||
import { DocumentSymbolCollector } from './documentSymbolCollector';
|
||||
import { getImportFromTarget, getModuleNameCompletionSuggestions } from './importStatementCandidates';
|
||||
import { getAutoImportText, getDocumentationPartsForTypeAndDecl } from './tooltipUtils';
|
||||
import { findViperAttributeContext, getViperAttributeSymbols } from './viperAttributeUtils';
|
||||
import {
|
||||
findViperAttributeContext,
|
||||
getViperAttributeSymbols,
|
||||
getViperUndeclaredAttributeNames,
|
||||
} from './viperAttributeUtils';
|
||||
|
||||
namespace Keywords {
|
||||
const base: string[] = [
|
||||
@@ -3558,6 +3562,16 @@ export class CompletionProvider {
|
||||
});
|
||||
});
|
||||
|
||||
// 属性名是编译器级开放集合:`t.attr` 未声明、但 codegen 支持的名字
|
||||
// (如 stackrealign)也要列出(见 viperAttributeUtils)。
|
||||
getViperUndeclaredAttributeNames(attributeInfo).forEach((name) => {
|
||||
this.addNameToCompletions(name, CompletionItemKind.Function, priorWord, completionMap, {
|
||||
funcParensDisabled: false,
|
||||
extraCommitChars: !!priorWord,
|
||||
itemDetail: '__attribute__ 属性名(编译器 codegen 支持)',
|
||||
});
|
||||
});
|
||||
|
||||
return completionMap;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ import {
|
||||
getTypeForToolTip,
|
||||
getWrappedFunctionType,
|
||||
} from './tooltipUtils';
|
||||
import { findViperAttributeContext, getViperAttributeSymbols } from './viperAttributeUtils';
|
||||
import { findViperAttributeContext, getViperAttributeNames, getViperAttributeSymbols } from './viperAttributeUtils';
|
||||
|
||||
export interface HoverTextPart {
|
||||
// 该部分按代码块渲染(markdown 下加代码围栏,见 convertHoverResults)。
|
||||
@@ -459,7 +459,7 @@ export class HoverProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
const names = Array.from(attributeInfo.symbolTable.keys()).sort();
|
||||
const names = getViperAttributeNames(attributeInfo);
|
||||
|
||||
return {
|
||||
parts: [
|
||||
@@ -469,7 +469,7 @@ export class HoverProvider {
|
||||
text:
|
||||
'\n\n带参数者写成调用,如 `section(".text.wo")` / `aligned(16)` / ' +
|
||||
'`format(printf, 1, 2)`;无参数者可直接写属性名(`packed`)或写调用(`packed()`)。' +
|
||||
'\n\n属性清单来自 `t.attr`(TransPyC 的 `lib/includes/t.py`)。',
|
||||
'\n\n属性清单来自 `t.attr`(TransPyC 的 `lib/includes/t.py`)与编译器 codegen 支持的属性名。',
|
||||
},
|
||||
],
|
||||
range: {
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
* 由 completionProvider(括号内属性名补全)与 hoverProvider(括号内属性名提示)共用,
|
||||
* 避免两处各写一份 `t.attr` 查找逻辑导致口径漂移。
|
||||
*
|
||||
* 属性名是编译器级的**开放集合**,故清单 = `t.attr` 已声明的名字 ∪ 编译器 codegen
|
||||
* 支持但未声明的名字(见 VIPER_UNDECLARED_ATTRIBUTE_NAMES),不能只依赖存根声明。
|
||||
*
|
||||
* 为什么用文本扫描定位上下文:`__attribute__(...)` 在 parser 里会被脱糖
|
||||
* (装饰器 → `@c.Attribute(t.attr.X, ...)`;注解修饰器 → `t.attr.X | 内层类型`),
|
||||
* 原始调用节点不保留在 parse 树中,光标位置(尤其实参为空或拼写未完成时)
|
||||
@@ -25,6 +28,32 @@ export interface ViperAttributeContext {
|
||||
openParen: number;
|
||||
}
|
||||
|
||||
// 编译器(TransPyV)codegen 支持、但 `class attr` 里**未声明**的属性名。
|
||||
//
|
||||
// 属性名是编译器级的**开放集合**:TransPyV 的 codegen 映射里支持的名字不一定都
|
||||
// 声明在 `t.attr`(TransPyC 的 `lib/includes/t.py` / LSP 存根 `t.vpi` 的
|
||||
// `class attr` 两边一致,都没有 `stackrealign`)。补全/悬停若只枚举 `t.attr`,
|
||||
// 这类名字就看不到,故在此显式补齐。
|
||||
// 来源:TransPyC/TransPyV/App/lib/core/Gen/Func/FuncGenBase.vp(`attr_name ==
|
||||
// "stackrealign"` → LLVM `"stackrealign"` 属性);
|
||||
// 真实用例:ViperOS `VKernel/Kernel/main.vp`
|
||||
// `@__attribute__(section(".text.startup"), aligned(16), stackrealign)`。
|
||||
export const VIPER_UNDECLARED_ATTRIBUTE_NAMES: readonly string[] = ['stackrealign'];
|
||||
|
||||
// 补全/悬停用的**属性名全集**:`t.attr` 已声明的名字 ∪ 上面补齐的未声明名字,
|
||||
// 排序去重。属性名是开放集合,不能只依赖 `t.attr` 的声明。
|
||||
export function getViperAttributeNames(attributeInfo: { symbolTable: SymbolTable }): string[] {
|
||||
const names = new Set<string>(attributeInfo.symbolTable.keys());
|
||||
VIPER_UNDECLARED_ATTRIBUTE_NAMES.forEach((name) => names.add(name));
|
||||
return Array.from(names).sort();
|
||||
}
|
||||
|
||||
// `t.attr` 里**未声明**、只在编译器 codegen 里支持的属性名(补全时单独注入,
|
||||
// 已声明的走符号表,避免重复)。
|
||||
export function getViperUndeclaredAttributeNames(attributeInfo: { symbolTable: SymbolTable }): string[] {
|
||||
return VIPER_UNDECLARED_ATTRIBUTE_NAMES.filter((name) => !attributeInfo.symbolTable.has(name));
|
||||
}
|
||||
|
||||
// 判断 `offset` 是否位于 `__attribute__(...)` 的实参括号内,是则返回上下文。
|
||||
// 扫描方式:从光标向前找最近的未闭合 `(`(跳过已输入的属性名/实参),
|
||||
// 该 `(` 左侧(允许空白分隔)的标识符必须是 `__attribute__`。
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
* ③ 注解联合里的属性标记 `T | t.attr.<name>` / `T | t.attr.llvm.<name>`
|
||||
* 求值为 t.CAttr(修饰符),不参与类型检查、展示不泄漏
|
||||
* ④ 值位置 `volatile f()` / `volatile 结构体()`(标记调用为 volatile)
|
||||
* ⑤ `__attribute__(` 括号内的属性名补全
|
||||
* ⑤ `__attribute__(` 括号内的属性名补全/悬停(含 `t.attr` 未声明、但编译器 codegen
|
||||
* 支持的 `stackrealign`)
|
||||
* ⑥ 属性名是编译器级开放集合:未声明在 `t.attr` 的名字(如 `stackrealign`)
|
||||
* 也按 function 高亮,且不报「无法访问属性」
|
||||
* 负例:`volatile = 2` / `const = 1` / `volatile 1`(非调用)仍须报错。
|
||||
@@ -309,7 +310,8 @@ Attr: __attribute__() int = 1
|
||||
const labels: string[] = completions.items.map((item) => item.label);
|
||||
console.log(`=== __attribute__ 补全项 ${labels.length} 项:${labels.slice(0, 20).join(', ')} ===`);
|
||||
|
||||
for (const name of ['section', 'always_inline', 'aligned', 'packed', 'weak', 'noinline']) {
|
||||
// 已声明的属性名 + 编译器 codegen 支持但 `t.attr` 未声明的 stackrealign
|
||||
for (const name of ['section', 'always_inline', 'aligned', 'packed', 'weak', 'noinline', 'stackrealign']) {
|
||||
assert(labels.indexOf(name) >= 0, `__attribute__ 补全缺少属性 ${name}:${JSON.stringify(labels)}`);
|
||||
}
|
||||
// llvm 描述符类不是 __attribute__ 的属性名(属注解联合用法),不应出现在此处
|
||||
@@ -431,7 +433,8 @@ Attr: __attribute__(section(".x")) const int = 1
|
||||
const text = typeof hover.contents === 'string' ? hover.contents : (hover.contents as any).value;
|
||||
console.log(`=== hover 内容(前 200 字)===\n${text.slice(0, 200)}`);
|
||||
|
||||
for (const name of ['section', 'always_inline', 'aligned', 'packed', 'weak']) {
|
||||
// 已声明的属性名 + 编译器 codegen 支持但 `t.attr` 未声明的 stackrealign
|
||||
for (const name of ['section', 'always_inline', 'aligned', 'packed', 'weak', 'stackrealign']) {
|
||||
assert(text.includes(name), `hover 应列出属性 ${name}:${text.slice(0, 300)}`);
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
- **`export` / `extern` on variable declarations** are now supported: `export gdt: [7]gdt_entry = []`, `export tss_buf: [104]uint8` and `extern ext_flag: int`. The variable form is told apart from the function form (`export def f()` / `export f(...)`) by the third token — `:` is a variable (type annotation), `(` / `[` is a function, the same criterion as TransPyC's `_is_export_extern_var`). They desugar exactly like TransPyC's `_parse_export_extern_var`: `export NAME: T [= v]` becomes `T | t.CExport` (bare-named definition, **no module SHA1 header**), `extern NAME: T` becomes `T | t.State` (= `CExtern | CExport`, declaration only). An **initializer is allowed for `export` but rejected for `extern`** — `extern a: int = 1` reports "extern 变量声明不能带初始值(符号定义在外部)", matching the compiler's fail-fast. Storage-class markers render as a prefix qualifier (`export CArray[gdt_entry, 7]`, `extern int`), and the marker is treated as a modifier everywhere else: in the `Struct | CPtr` fold (so `extern p: t.CPtr` stays a pointer instead of degrading to `CPtr[State]`), in the union index access, and as a CArray element access (so `gdt[i].access` still resolves to `uint8` and the zero-initializer `= []` is accepted)
|
||||
- `[SIZE]T` array annotations no longer require the file to `import t`. The parser desugars `coroutines: [8]Coroutine` into a synthetic `t.CArray[Coroutine, 8]` member access; when that synthetic `t` could not be resolved through the lexical scope it silently degraded to `Unknown`, so the whole array annotation collapsed and `m.coroutines[i].rsp` reported "无法解析类型上的成员“rsp”访问" with `rsp` getting no semantic token at all (rendered unhighlighted, no jump-to-definition). The synthetic `t` now falls back to the `t` module bound in the built-in `builtins.vpi` scope — the same mechanism `T*` uses for `rawptr` and `__attribute__(...)` uses for its implicit module roots — so a file without `import t` still gets the real `CArray[Coroutine, Literal[8]]` and the element's member resolves
|
||||
- Attribute names inside `__attribute__(...)` are highlighted **structurally**, so a name that the compiler supports but that isn't declared in the `attr` class still colours like the declared ones. `stackrealign` (supported by TransPyV's code generator — `FuncGenBase.vp` maps it to the LLVM `"stackrealign"` attribute — and used by ViperOS `VKernel/Kernel/main.vp`) is declared in neither `t.py` nor the `t.vpi` stub, so `t.attr.stackrealign` used to be unresolvable: the name got no semantic token (rendered unhighlighted) and the file was additionally flagged with "无法访问类"type[attr]"的属性"stackrealign"". The parser now marks the synthesized attribute-name node, the semantic token provider colours it as `function` (exactly like a declared attribute such as `section` / `aligned` / `naked`), and the member-access diagnostic is suppressed for these names — the compiler silently drops unknown attributes rather than rejecting them, so reporting them was a false positive. Declared names keep resolving through `t.attr` as before, so hover and jump-to-definition still work for them
|
||||
- `__attribute__(...)` **completion and hover** now list attribute names that the compiler supports but that the `attr` class doesn't declare, instead of only mirroring `t.attr`. `stackrealign` is offered by typing inside the parentheses and appears in the hover list of available names; the list is a single shared union (`viperAttributeUtils.getViperAttributeNames`) of `t.attr`'s declared names plus these extra names, so completion and hover cannot drift apart. Declared names keep coming from the stub symbol table (so they still show their signature and support jump-to-definition)
|
||||
|
||||
## 1.1.425
|
||||
|
||||
|
||||
Reference in new issue
Block a user