✨ feat(vscode): 代码阅读函数块默认折叠,函数说明进属性表「说明」行

This commit is contained in:
cruldra committed 2026-09-25 13:09:53 +08:00
1 parent 62f48fe67c
commit 9b32d4b5a8
17 files changed
+489 -100

No files matched your search

+45 -8
View File
@@ -64,14 +64,50 @@ describe('blockView', () => {
}
})
it.each(SAMPLES)('%#: 各块头部的行互不重叠,每行源码最多归一块编辑', async (adapter, languageId, translator, fixture) => {
const owner = new Map<number, string>()
for (const view of flatten(await views(adapter, languageId, translator, readFixture(fixture)))) {
for (let line = view.startLine; line <= view.endLine; line++) {
expect(owner.get(line), `第 ${line} 行又归 ${view.id}`).toBeUndefined()
owner.set(line, view.id)
}
}
})
it('函数的说明算在函数块的头部里:编辑时和签名一起显示、一起改', async () => {
const env = await views(ts, 'typescript', typescriptZhTranslator, readFixture('envLock.ts.txt'))
expect(byId(env, '5')).toMatchObject({ kind: 'function', startLine: 17, endLine: 22 })
expect(byId(env, '5').code.split('\n')).toEqual([
'/**',
' * Scan the workspace folder rooted at `workspaceRoot` for all `.env*`',
' * files, skipping `node_modules`, `.git`, and `.claude`. Returns absolute',
' * fs paths. Empty array if the workspace folder isn\'t currently open.',
' */',
'export async function findEnvFiles(workspaceRoot: string): Promise<string[]> {',
])
expect(byId(env, '4')).toMatchObject({ kind: 'const', startLine: 15, endLine: 15 })
const routes = await views(py, 'python', pythonZhTranslator, readFixture('routes.py'))
const getUser = flatten(routes).find(view => view.kind === 'function' && view.startLine === 28)
expect(getUser).toMatchObject({ startLine: 28, endLine: 37 })
expect(getUser?.code.split('\n').slice(-5)).toEqual([
') -> UserDetailResponse:',
' """获取用户详情。',
'',
' 管理员可查看任意用户,普通用户只能查看自己。',
' """',
])
expect(getUser?.children[0]).toMatchObject({ kind: 'comment', startLine: 38, endLine: 38 })
})
it('id 是块在树里的位置,行号 0 起,多行块去掉共同缩进', async () => {
const env = await views(ts, 'typescript', typescriptZhTranslator, readFixture('envLock.ts.txt'))
expect(byId(env, '6.1.0')).toMatchObject({ kind: 'return', startLine: 25, endLine: 25, code: 'return []' })
expect(byId(env, '6.1')).toMatchObject({ kind: 'if', startLine: 24, code: 'if (!folder)' })
expect(byId(env, '8.2.1')).toMatchObject({ kind: 'catch', startLine: 45, code: 'catch (err) {' })
expect(byId(env, '5.1.0')).toMatchObject({ kind: 'return', startLine: 25, endLine: 25, code: 'return []' })
expect(byId(env, '5.1')).toMatchObject({ kind: 'if', startLine: 24, code: 'if (!folder)' })
expect(byId(env, '7.2.1')).toMatchObject({ kind: 'catch', startLine: 45, code: 'catch (err) {' })
const issue = await views(ts, 'typescript', typescriptZhTranslator, readFixture('issueLock.ts.txt'))
expect(byId(issue, '3.4')).toMatchObject({
expect(byId(issue, '2.4')).toMatchObject({
kind: 'return',
startLine: 19,
endLine: 23,
@@ -81,8 +117,8 @@ describe('blockView', () => {
it('源码着色来自语法树:每个叶子一段,空白和标点归 plain', async () => {
const env = await views(ts, 'typescript', typescriptZhTranslator, readFixture('envLock.ts.txt'))
const tokens = byId(env, '6.3').codeTokens
expect(byId(env, '6.3').code).toBe('const uris = await workspace.findFiles(include, EXCLUDE_PATTERN)')
const tokens = byId(env, '5.3').codeTokens
expect(byId(env, '5.3').code).toBe('const uris = await workspace.findFiles(include, EXCLUDE_PATTERN)')
expect(tokens.slice(0, 7)).toEqual([
{ text: 'const', role: 'storage' },
{ text: ' ', role: 'plain' },
@@ -97,14 +133,15 @@ describe('blockView', () => {
// 中文注释之后的行:语法树下标按字符串下标算,不按 UTF-8 字节
const issue = await views(ts, 'typescript', typescriptZhTranslator, readFixture('issueLock.ts.txt'))
expect(byId(issue, '3').codeTokens.slice(0, 5)).toEqual([
expect(byId(issue, '2').codeTokens.slice(0, 7)).toEqual([
{ text: '/**\n * 纯判定:工单被未完成的前置挡住才算锁定。快照里找不到工单或前置一律放行,\n * 与 webview 的 `isIssueLocked` 保持同一语义。\n */', role: 'comment' },
{ text: '\n', role: 'plain' },
{ text: 'export', role: 'keyword' },
{ text: ' ', role: 'plain' },
{ text: 'function', role: 'storage' },
{ text: ' ', role: 'plain' },
{ text: 'evaluateLockedReason', role: 'function' },
])
expect(byId(issue, '2').codeTokens).toEqual([{ text: byId(issue, '2').code, role: 'comment' }])
const sample = await views(py, 'python', pythonZhTranslator, readFixture('sample.py'))
const signature = byId(sample, '5').codeTokens