✨ feat(vscode): 代码阅读预览里工作区外的库文件也能问 AI,问答记进第一个工作区文件夹,重写注释不对库文件开放

This commit is contained in:
cruldra committed 2026-10-13 21:50:54 +11:00
1 parent cecae0e244
commit 39dfd9b084
24 files changed
+463 -79

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
import type { WorkspaceFolder } from 'vscode'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { keyUri, locateQa } from './folderStore'
const fake = vi.hoisted(() => {
/** 够用的 Uri:协议、主机、路径;测试里都是 POSIX 路径,fsPath 同 path */
class FakeUri {
constructor(readonly scheme: string, readonly authority: string, readonly path: string) {}
get fsPath(): string {
return this.path
}
with(change: { path?: string }): FakeUri {
return new FakeUri(this.scheme, this.authority, change.path ?? this.path)
}
toString(): string {
return `${this.scheme}://${this.authority}${this.path}`
}
static file(fsPath: string): FakeUri {
return new FakeUri('file', '', fsPath)
}
static joinPath(base: FakeUri, ...parts: string[]): FakeUri {
return base.with({ path: [base.path, ...parts].join('/') })
}
}
/** 眼下打开的工作区文件夹,按顺序 */
const folders: WorkspaceFolder[] = []
const workspace = {
get workspaceFolders(): WorkspaceFolder[] | undefined {
return folders.length > 0 ? folders : undefined
},
getWorkspaceFolder: (uri: FakeUri) => folders.find(folder => uri.path === folder.uri.path || uri.path.startsWith(`${folder.uri.path}/`)),
}
return { FakeUri, folders, workspace }
})
vi.mock('vscode', () => ({ Uri: fake.FakeUri, workspace: fake.workspace, Disposable: {}, EventEmitter: class {}, RelativePattern: class {}, window: {} }))
vi.mock('node:os', () => ({ homedir: () => '/Users/me' }))
const { FakeUri } = fake
const folder = (path: string, index: number): WorkspaceFolder => ({ uri: FakeUri.file(path) as never, name: path.split('/').at(-1)!, index })
const APP = folder('/Users/me/work/app', 0)
const API = folder('/Users/me/work/api', 1)
/** uv 装的 Python 标准库,⌘ 点 rglob 进去的那份 */
const LIBRARY_DIR = '/Users/me/.local/share/uv/python/cpython-3.12.4-macos-aarch64-none/lib/python3.12'
const PATHLIB = FakeUri.file(`${LIBRARY_DIR}/pathlib.py`) as never
beforeEach(() => {
fake.folders.splice(0, fake.folders.length, APP, API)
})
describe('这份文件的问答记在哪', () => {
it('工作区里的文件:记在所在的工作区文件夹,键是相对路径;发给模型也写相对路径,不用另外放行目录', () => {
expect(locateQa(FakeUri.file('/Users/me/work/api/src/main.py') as never)).toEqual({ folder: API, key: 'src/main.py', promptPath: 'src/main.py' })
})
it('家目录下的工作区外文件(库源码):记在第一个工作区文件夹,键把家目录写成 ~;发给模型写绝对路径,放行它所在的目录', () => {
expect(locateQa(PATHLIB)).toEqual({
folder: APP,
key: '~/.local/share/uv/python/cpython-3.12.4-macos-aarch64-none/lib/python3.12/pathlib.py',
promptPath: `${LIBRARY_DIR}/pathlib.py`,
outsideDir: LIBRARY_DIR,
})
})
it('家目录外的工作区外文件:键是绝对路径', () => {
const requests = FakeUri.file('/opt/homebrew/lib/python3.12/site-packages/requests/api.py') as never
expect(locateQa(requests)).toMatchObject({ folder: APP, key: '/opt/homebrew/lib/python3.12/site-packages/requests/api.py', outsideDir: '/opt/homebrew/lib/python3.12/site-packages/requests' })
})
it('没打开工作区文件夹时没有;工作区文件夹本身、不是磁盘上的文件(别的协议)也没有', () => {
expect(locateQa(APP.uri)).toBeUndefined()
expect(locateQa(new FakeUri('git', '', `${LIBRARY_DIR}/pathlib.py`) as never)).toBeUndefined()
fake.folders.splice(0)
expect(locateQa(PATHLIB)).toBeUndefined()
})
})
describe('表里的键对应哪个文件', () => {
it('工作区里的在工作区文件夹下面;工作区外的还原成磁盘上的位置,和打开的那份文件是同一个 Uri', () => {
expect(keyUri(API, 'src/main.py').toString()).toBe('file:///Users/me/work/api/src/main.py')
expect(keyUri(APP, locateQa(PATHLIB)!.key).toString()).toBe(String(PATHLIB))
expect(keyUri(APP, '/opt/homebrew/a.py').toString()).toBe('file:///opt/homebrew/a.py')
})
})