⚡ perf(vscode): 查到的定义落到名字上时只读定义那一段,不把目标文件整份取出来

This commit is contained in:
cruldra committed 2026-10-13 14:40:07 +11:00
1 parent 0070933599
commit 6e2c541558
2 files changed
+51 -6

No files matched your search

@@ -1,10 +1,13 @@
import { describe, expect, it, vi } from 'vitest'
import { definitionOffset } from './definitions'
import { commands, workspace } from 'vscode'
import { definitionOffset, languageDefinitions } from './definitions'
vi.mock('vscode', () => ({
commands: { executeCommand: vi.fn() },
EventEmitter: class EventEmitter { event = vi.fn(); fire = vi.fn() },
Range: class Range {},
Range: class Range {
constructor(readonly start: { offset: number }, readonly end: { offset: number }) {}
},
Uri: { parse: vi.fn() },
window: { createOutputChannel: vi.fn(() => ({ appendLine: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() })) },
workspace: { openTextDocument: vi.fn(), asRelativePath: vi.fn() },
@@ -40,3 +43,39 @@ describe('定义范围的起点不在名字上时,用范围里那个名字', (
expect(definitionOffset(text, { start: 0, end: text.length }, undefined, 'fetchAppDeployments')).toBe(text.lastIndexOf('fetchAppDeployments'))
})
})
/** 假的文档:位置就是下标;记下 getText 每次取了多长。 */
function fakeDocument(uri: string, text: string): { reads: number[] } {
const reads: number[] = []
const at = (offset: number) => ({ offset })
const document = {
uri: { toString: () => uri },
offsetAt: (position: { offset: number }) => position.offset,
positionAt: (offset: number) => at(Math.max(0, Math.min(offset, text.length))),
getText: (range?: { start: { offset: number }, end: { offset: number } }) => {
const read = range ? text.slice(range.start.offset, range.end.offset) : text
reads.push(read.length)
return read
},
getWordRangeAtPosition: (position: { offset: number }) => {
const start = text.slice(0, position.offset).search(/\w+$/)
const end = position.offset + (/^\w*/.exec(text.slice(position.offset))?.[0].length ?? 0)
return { start: at(start < 0 ? position.offset : start), end: at(end) }
},
}
vi.mocked(workspace.openTextDocument).mockImplementation((async (target: { toString: () => string }) => target.toString() === uri ? document : undefined) as never)
return { reads }
}
describe('查到的定义落到名字上', () => {
it('只读定义那一段(前后各多一个字认名字的边界),不把目标文件整份取出来', async () => {
const text = `${'# 很长的文件\n'.repeat(2000)}def fetch_app(x):\n return fetch_app(x)\n`
const { reads } = fakeDocument('file:///w/a.py', text)
const call = text.lastIndexOf('fetch_app')
const declaration = text.indexOf('def fetch_app')
vi.mocked(commands.executeCommand).mockResolvedValue([{ uri: { toString: () => 'file:///w/a.py' }, range: { start: { offset: declaration }, end: { offset: text.indexOf(':', declaration) } } }] as never)
const [found] = await languageDefinitions({ toString: () => 'file:///w/a.py' } as never, { offset: call } as never)
expect((found.range.start as unknown as { offset: number }).offset).toBe(text.indexOf('fetch_app', declaration))
expect(Math.max(...reads)).toBeLessThan(40)
})
})
+10 -4
View File
@@ -108,16 +108,22 @@ async function rangeOnName(uri: Uri, range: Range, selection: Range | undefined,
return fallback
try {
const document = await workspace.openTextDocument(uri)
const text = document.getText()
const start = document.offsetAt(range.start)
const end = document.offsetAt(range.end)
const selected = selection && { start: document.offsetAt(selection.start), end: document.offsetAt(selection.end) }
// 只取定义这一段,前后各多一个字(认名字的边界):目标文件可能很大,每处定义都整份取一遍太费
const from = Math.max(0, Math.min(start, selected?.start ?? start) - 1)
const to = Math.max(end, (selected?.start ?? start) + name.length) + 1
const text = document.getText(new Range(document.positionAt(from), document.positionAt(to)))
const offset = definitionOffset(
text,
{ start: document.offsetAt(range.start), end: document.offsetAt(range.end) },
selection ? { start: document.offsetAt(selection.start), end: document.offsetAt(selection.end) } : undefined,
{ start: start - from, end: end - from },
selected && { start: selected.start - from, end: selected.end - from },
name,
)
if (!onName(text, offset, name))
return fallback
return new Range(document.positionAt(offset), document.positionAt(offset + name.length))
return new Range(document.positionAt(from + offset), document.positionAt(from + offset + name.length))
}
catch (err) {
logger.add({ level: 'warn', source: 'codeReader', message: `读不到定义所在的 ${uri.toString()}:${err instanceof Error ? err.message : String(err)}` })