⚡ perf(vscode): 认调用分新建还是调用时,定义所在的文件按版本记着解析结果,同一版不再整份重解析;定义就在本文件时用发文档时读出的
This commit is contained in:
1 parent
80d9962856
commit
e9c1c67d6f
8 files changed
+194
-45
No files matched your search
@@ -1,10 +1,9 @@
|
||||
import type { Location, LocationLink, Position } from 'vscode'
|
||||
import type { BlockKind, LanguageAdapter, RuleLocation } from '../contract'
|
||||
import type { TreeSitterRuntime } from '../runtime'
|
||||
import type { BlockKind, RuleLocation } from '../contract'
|
||||
import type { DefinitionKinds } from '../definitionKinds'
|
||||
import type { DefinitionTarget } from './definitionAction'
|
||||
import { commands, Range, Uri, window, workspace } from 'vscode'
|
||||
import { logger } from '../../logging/logger'
|
||||
import { readDefinitionKind } from '../blockView'
|
||||
|
||||
/** 查到的一处定义:文件和定义处那个名字的范围。 */
|
||||
export interface FoundLocation { uri: Uri, range: Range }
|
||||
@@ -131,16 +130,12 @@ export function ruleDefinitions(locations: readonly RuleLocation[]): FoundLocati
|
||||
return locations.map(({ uri, start, end }) => ({ uri: Uri.parse(uri), range: new Range(start.line, start.character, end.line, end.character) }))
|
||||
}
|
||||
|
||||
/** 定义处那个名字定义的是哪种块:打开目标文件,用它那种语言的语言插件分块认;目标打不开、语言不支持、不在哪块的名字上时没有。 */
|
||||
export async function definitionKind(
|
||||
location: FoundLocation,
|
||||
languageFor: (languageId: string) => LanguageAdapter | undefined,
|
||||
runtime: Pick<TreeSitterRuntime, 'parse'>,
|
||||
): Promise<BlockKind | undefined> {
|
||||
/** 定义处那个名字定义的是哪种块:打开目标文件,按它这一版各块的名字认(见 DefinitionKinds);目标打不开、语言不支持、不在哪块的名字上时没有。 */
|
||||
export async function definitionKind(location: FoundLocation, kinds: DefinitionKinds): Promise<BlockKind | undefined> {
|
||||
try {
|
||||
const document = await workspace.openTextDocument(location.uri)
|
||||
const adapter = languageFor(document.languageId)
|
||||
return adapter && await readDefinitionKind(runtime, adapter, document.languageId, document.getText(), document.offsetAt(location.range.start))
|
||||
const file = { uri: document.uri.toString(), version: document.version, languageId: document.languageId, getText: () => document.getText() }
|
||||
return await kinds.kindAt(file, document.offsetAt(location.range.start))
|
||||
}
|
||||
catch (err) {
|
||||
logger.add({ level: 'warn', source: 'codeReader', message: `认不出 ${location.uri.toString()} 里定义的是哪种块:${err instanceof Error ? err.message : String(err)}` })
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { NamedKind } from '../blockView'
|
||||
import type { DisplayName, LocalSymbol, RuleContext, SourceDocument } from '../contract'
|
||||
import type { CodeReaderRegistry } from '../registry'
|
||||
import type { TreeSitterRuntime } from '../runtime'
|
||||
@@ -22,13 +23,14 @@ export interface DocumentSnapshot {
|
||||
|
||||
/**
|
||||
* 发给预览的文档,和这份源码里起了中文名的定义(扩展端接着找用到它们的各处)、语言插件自己认得出的名字(LocalSymbol)、
|
||||
* 各条导入引进来的名字(注释里不带路径的引用按它找导入的定义)。
|
||||
* 各条导入引进来的名字(注释里不带路径的引用按它找导入的定义)、各块自己的名字和种类(调用的定义就在这份文档里时认种类用,见 NamedKind)。
|
||||
*/
|
||||
export interface DocumentRead {
|
||||
message: DocumentMessage
|
||||
displayNames: DisplayName[]
|
||||
symbols: LocalSymbol[]
|
||||
imports: ImportedName[]
|
||||
kinds: NamedKind[]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,10 +62,10 @@ export async function documentMessage(
|
||||
}
|
||||
const adapter = registry.languageFor(languageId)
|
||||
if (!adapter)
|
||||
return { message: { ...message, error: `代码阅读还不支持「${languageId}」这种语言` }, displayNames: [], symbols: [], imports: [] }
|
||||
return { message: { ...message, error: `代码阅读还不支持「${languageId}」这种语言` }, displayNames: [], symbols: [], imports: [], kinds: [] }
|
||||
try {
|
||||
const rules = registry.rulesFor(languageId)
|
||||
const { blocks, displayNames, symbols, imports } = await readBlockViews(runtime, adapter, translator, languageId, source, {
|
||||
const { blocks, displayNames, symbols, imports, kinds } = await readBlockViews(runtime, adapter, translator, languageId, source, {
|
||||
...(document.fileName && { fileName: document.fileName }),
|
||||
rules: { rules, report, lookup },
|
||||
calleeKind,
|
||||
@@ -78,9 +80,9 @@ export async function documentMessage(
|
||||
},
|
||||
})
|
||||
const names = mergeAttributeNames([translator?.attributeNames, ...ruleAttributeNames(rules, translator?.displayLanguage, report)])
|
||||
return { message: { ...message, blocks: markEntryBlocks(blocks, source, document.entryNames ?? []), attributes: fileAttributes(blocks, names) }, displayNames, symbols, imports }
|
||||
return { message: { ...message, blocks: markEntryBlocks(blocks, source, document.entryNames ?? []), attributes: fileAttributes(blocks, names) }, displayNames, symbols, imports, kinds }
|
||||
}
|
||||
catch (err) {
|
||||
return { message: { ...message, error: err instanceof Error ? err.message : String(err) }, displayNames: [], symbols: [], imports: [] }
|
||||
return { message: { ...message, error: err instanceof Error ? err.message : String(err) }, displayNames: [], symbols: [], imports: [], kinds: [] }
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ vi.mock('./documentMessage', () => ({
|
||||
displayNames: [],
|
||||
symbols: [],
|
||||
imports: [],
|
||||
kinds: [],
|
||||
})),
|
||||
}))
|
||||
/** 文档符号由各个测试给 */
|
||||
|
||||
@@ -26,6 +26,7 @@ import { DocumentCallees } from '../calleeKinds'
|
||||
import { loadBlockCalls } from '../callTree/query'
|
||||
import { CallTreeSession } from '../callTree/session'
|
||||
import { commentFollowUp, commentJob, commentRewritePrompt, findBlock, writeCommentBody } from '../commentRewrite'
|
||||
import { DefinitionKinds } from '../definitionKinds'
|
||||
import { PreviewDiff } from '../diff/previewDiff'
|
||||
import { blockReplacement } from '../editText'
|
||||
import { locate } from '../folderStore'
|
||||
@@ -77,6 +78,8 @@ export class PreviewEditorProvider implements CustomTextEditorProvider {
|
||||
private readonly requests = new Map<string, OpenRequest>()
|
||||
/** 哪个预览眼下能用键盘在高亮的各处出现之间跳,跟着它设快捷键 when 子句用的上下文键 */
|
||||
readonly navigation = new NavigationContext<Preview>(value => void commands.executeCommand('setContext', OCCURRENCES_CONTEXT, value))
|
||||
/** 调用的名字的定义是哪种块:各预览共用,定义所在的文件同一版只解析一次 */
|
||||
readonly definitionKinds: DefinitionKinds
|
||||
|
||||
constructor(
|
||||
private readonly extensionUri: Uri,
|
||||
@@ -101,7 +104,9 @@ export class PreviewEditorProvider implements CustomTextEditorProvider {
|
||||
readonly revealInTree: (uri: Uri) => Promise<boolean>,
|
||||
/** 「了解一块代码」的对话页里接着说(subject 是那个功能,见 featureSubjectUri);说不了时返回给人看的原因 */
|
||||
readonly askFeature: (subject: Uri, request: TopRequest) => Promise<string | undefined>,
|
||||
) {}
|
||||
) {
|
||||
this.definitionKinds = new DefinitionKinds(languageId => registry.languageFor(languageId), runtime)
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册成预览编辑器。标签页切走时页面留着(`retainContextWhenHidden`):切回来不用重新生成、重发文档(切走期间改过的才补一次),页面也不用整份重画,
|
||||
@@ -404,12 +409,14 @@ class Preview {
|
||||
const source = this.document.getText()
|
||||
const session = this.lookups.session()
|
||||
const callees = this.callees.session()
|
||||
const { message, displayNames, symbols, imports } = await documentMessage({ languageId, version, getText: () => source, fileName: this.document.fileName, entryNames: this.owner.entries.namesOf(this.document.uri) }, this.registry, this.runtime, (text) => {
|
||||
const { message, displayNames, symbols, imports, kinds } = await documentMessage({ languageId, version, getText: () => source, fileName: this.document.fileName, entryNames: this.owner.entries.namesOf(this.document.uri) }, this.registry, this.runtime, (text) => {
|
||||
logger.add({ level: 'warn', source: 'codeReader', message: `${this.document.uri.fsPath}:${text}` })
|
||||
}, session.lookup, callees.calleeKind)
|
||||
if (request !== this.latest)
|
||||
return
|
||||
this.definitions.remember(message.version, message.blocks)
|
||||
// 调用的定义就在这份文档里时,认种类直接用这一遍读出的,不再解析一遍
|
||||
this.owner.definitionKinds.remember(this.document.uri.toString(), version, kinds)
|
||||
// 解析失败的文档没有块:问 AI 找不到块,也不拿它比差异
|
||||
this.sent = message.error === undefined ? { version: message.version, blocks: message.blocks, source } : undefined
|
||||
this.symbols = { version, list: symbols }
|
||||
@@ -452,7 +459,7 @@ class Preview {
|
||||
if (found.length === 0)
|
||||
return undefined
|
||||
for (const location of found) {
|
||||
const kind = await definitionKind(location, languageId => this.registry.languageFor(languageId), this.runtime)
|
||||
const kind = await definitionKind(location, this.owner.definitionKinds)
|
||||
if (kind)
|
||||
return kind
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user