⚡ perf(vscode): 代码阅读预览发给页面的块只记相对位置:块在源码里占的地方记成离前一块多远、自己多长,块里名字的下标从块的开头算,页面从文件开头累加回文件里的位置、和扩展端打交道的地方都在一处换算;靠前改了代码,后面内容没变的块发过去一模一样,扩展端自己的块和发给页面的块分成两种类型
This commit is contained in:
1 parent
3a2815c19c
commit
ad5f559e92
43 files changed
+980
-424
No files matched your search
@@ -1,12 +1,15 @@
|
||||
import type { FileAttribute } from '../attributes'
|
||||
import type { BlockView } from '../blockView'
|
||||
import type { PageCard } from '../editor/messages'
|
||||
import type { ChangedBlock, DiffStats, RemovedBlock } from './blockDiff'
|
||||
import type { DiffBase } from './diffBase'
|
||||
import { pageCard, pageMarks, sourceLines } from '../editor/pageBlocks'
|
||||
import { splitLines } from '../editText'
|
||||
import { diffBlockTrees } from './blockDiff'
|
||||
|
||||
/** 删掉的一块(见 RemovedBlock),带上种类的名字:旧版本里才有的种类,新文件的筛选属性里查不到它叫什么。 */
|
||||
export interface RemovedView extends RemovedBlock {
|
||||
/** 删掉的一块(见 RemovedBlock)发给页面的样子:旧版本里它自己的内容(见 pageCard),带上种类的名字(旧版本里才有的种类,新文件的筛选属性里查不到它叫什么)。 */
|
||||
export interface RemovedView extends Omit<RemovedBlock, 'block'> {
|
||||
block: PageCard
|
||||
kindName: string
|
||||
}
|
||||
|
||||
@@ -49,6 +52,20 @@ function kindNames(attributes: readonly FileAttribute[]): Map<string, string> {
|
||||
return new Map(attributes.find(attribute => attribute.id === 'kind')?.values.map(value => [value.id, value.name]))
|
||||
}
|
||||
|
||||
/** 各块的开头(第一行的行首)在文件里的下标,按块的记号:卡片里要标的改动发给页面时从块的开头算(见 pageMarks) */
|
||||
function blockStarts({ blocks, source }: SentDocument): Map<string, number> {
|
||||
const lines = sourceLines(source)
|
||||
const starts = new Map<string, number>()
|
||||
const visit = (list: readonly BlockView[]): void => {
|
||||
for (const block of list) {
|
||||
starts.set(block.anchor, lines.start(block.startLine))
|
||||
visit(block.children)
|
||||
}
|
||||
}
|
||||
visit(blocks)
|
||||
return starts
|
||||
}
|
||||
|
||||
/** 按基准比出来的差异:基准里没有这个文件时整份是新文件,否则两棵块树比(见 diffBlockTrees)。 */
|
||||
export function documentDiff(base: DiffBase, sent: SentDocument, old: { source: string, document: OldDocument } | null): DocumentDiff {
|
||||
const common = { base: base.label, version: sent.version, lineCount: splitLines(sent.source).length }
|
||||
@@ -56,7 +73,13 @@ export function documentDiff(base: DiffBase, sent: SentDocument, old: { source:
|
||||
return { ...common, newFile: base.missing, blocks: {}, removed: [], stats: NO_CHANGES }
|
||||
const { blocks, removed, stats } = diffBlockTrees({ blocks: old.document.blocks, source: old.source }, sent)
|
||||
const kinds = kindNames(old.document.attributes)
|
||||
return { ...common, blocks, removed: removed.map(item => ({ ...item, kindName: kinds.get(item.block.kind) ?? item.block.kind })), stats }
|
||||
const starts = blockStarts(sent)
|
||||
return {
|
||||
...common,
|
||||
blocks: Object.fromEntries(Object.entries(blocks).map(([anchor, changed]) => [anchor, changed.marks ? { ...changed, marks: pageMarks(changed.marks, starts.get(anchor) ?? 0) } : changed])),
|
||||
removed: removed.map(item => ({ ...item, block: pageCard(item.block, 0), kindName: kinds.get(item.block.kind) ?? item.block.kind })),
|
||||
stats,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { BlockView } from '../blockView'
|
||||
import type { DisplayName } from '../contract'
|
||||
import type { ShownName } from '../nameResolution'
|
||||
import type { PageBlock } from './messages'
|
||||
import { renderedNames } from '../nameResolution'
|
||||
import { pageBlocks } from './pageBlocks'
|
||||
|
||||
function covers(block: BlockView, offset: number): boolean {
|
||||
return block.defines !== undefined && block.defines.startIndex <= offset && offset < block.defines.endIndex
|
||||
@@ -38,6 +40,11 @@ export function peekBlock(blocks: readonly BlockView[], offset: number, line: nu
|
||||
return card
|
||||
}
|
||||
|
||||
/** 浮窗里那块发给页面的样子(见 pageBlocks):当那个文件的顶层第一块,span 从文件开头算,页面按它把卡片里的下标换回那个文件里的。 */
|
||||
export function pagePeekBlock(block: BlockView, source: string): PageBlock {
|
||||
return pageBlocks([block], source)[0]
|
||||
}
|
||||
|
||||
/** 卡片上画出来的名字(照抄自源码,下标和长度都对得上)显示成什么中文名;别的不带过去。 */
|
||||
export function namesOnCard(block: BlockView, names: readonly ShownName[]): ShownName[] {
|
||||
const rendered = renderedNames([block])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { NamedKind } from '../blockView'
|
||||
import type { BlockView, NamedKind } from '../blockView'
|
||||
import type { DisplayName, LocalSymbol, NameBinding, RuleContext, SourceDocument } from '../contract'
|
||||
import type { CodeReaderRegistry } from '../registry'
|
||||
import type { TreeSitterRuntime } from '../runtime'
|
||||
@@ -9,6 +9,7 @@ import { readBlockViews } from '../blockView'
|
||||
import { commandRuleLookup } from '../commandRules'
|
||||
import { markEntryBlocks } from '../entries/entryMarks'
|
||||
import { ruleAttributeNames } from '../libraryRules'
|
||||
import { pageBlocks } from './pageBlocks'
|
||||
|
||||
/** 生成预览数据要读的那点文档信息(TextDocument 的子集)。 */
|
||||
export interface DocumentSnapshot {
|
||||
@@ -21,13 +22,21 @@ export interface DocumentSnapshot {
|
||||
entryNames?: readonly string[]
|
||||
}
|
||||
|
||||
/** 扩展端这边的一份文档:同发给预览的 document 消息,块是扩展端的 BlockView(位置都是文件里的);发出去前换成页面收的样子(pageDocument)。 */
|
||||
export type DocumentView = Omit<DocumentMessage, 'blocks'> & { blocks: BlockView[] }
|
||||
|
||||
/** 发给预览的 document 消息:块换成页面收的样子(见 pageBlocks)。 */
|
||||
export function pageDocument({ blocks, ...rest }: DocumentView): DocumentMessage {
|
||||
return { ...rest, blocks: pageBlocks(blocks, rest.source) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 发给预览的文档,和这份源码里起了中文名的定义(扩展端接着找用到它们的各处)、语言插件自己认得出的名字(LocalSymbol)、
|
||||
* 读出来的文档,和这份源码里起了中文名的定义(扩展端接着找用到它们的各处)、语言插件自己认得出的名字(LocalSymbol)、
|
||||
* 各条导入引进来的名字(注释里不带路径的引用按它找导入的定义)、各块自己的名字和种类(调用的定义就在这份文档里时认种类用,见 NamedKind)、
|
||||
* 各个名字的绑定(找中文名时同一个绑定问一处,见 NameBinding)。
|
||||
*/
|
||||
export interface DocumentRead {
|
||||
message: DocumentMessage
|
||||
message: DocumentView
|
||||
displayNames: DisplayName[]
|
||||
symbols: LocalSymbol[]
|
||||
imports: ImportedName[]
|
||||
@@ -36,7 +45,7 @@ export interface DocumentRead {
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前文档 → 发给预览的 document 消息;语言不支持或解析失败时带 error,blocks 为空。库规则出错不算失败,交给 report 记下;
|
||||
* 当前文档 → 扩展端这边的一份文档(DocumentView,发出去前见 pageDocument);语言不支持或解析失败时带 error,blocks 为空。库规则出错不算失败,交给 report 记下;
|
||||
* 规则查名字的定义时问 lookup(RuleContext.lookup),翻译插件问调用的名字定义成哪种块时问 calleeKind(SourceDocument.calleeKind)。
|
||||
* 筛选属性和值的名字先取翻译插件的,没给的再取库规则的(LibraryRule.attributeNames)。
|
||||
* 入口文件里名字对上的块,概念列表的第一个换成入口(markEntryBlocks)。
|
||||
@@ -52,7 +61,7 @@ export async function documentMessage(
|
||||
const { languageId, version } = document
|
||||
const source = document.getText()
|
||||
const translator = registry.selectedTranslator(languageId)
|
||||
const message: DocumentMessage = {
|
||||
const message: DocumentView = {
|
||||
type: 'document',
|
||||
version,
|
||||
languageId,
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
import type { ClaudeImage } from '../../cc/spawnClaude'
|
||||
import type { FileAttribute } from '../attributes'
|
||||
import type { BlockView, SourceColors } from '../blockView'
|
||||
import type { BlockSlot, CallTreeTarget, CommentTarget, SourceColors } from '../blockView'
|
||||
import type { ContractMiss } from '../callTree/endpoint'
|
||||
import type { CallTree } from '../callTree/model'
|
||||
import type { BlockAttributes, BlockConcept, KindBadge, Markdown, PreviewTable, PreviewText, PropertyItem, PropertyRow, SourceRange } from '../contract'
|
||||
import type { OpenedFrom } from '../diff/diffBase'
|
||||
import type { DocumentDiff } from '../diff/previewDiff'
|
||||
import type { ShownName } from '../nameResolution'
|
||||
@@ -48,14 +49,52 @@ export interface Occurrence {
|
||||
kind: 'text' | 'read' | 'write'
|
||||
}
|
||||
|
||||
/**
|
||||
* 块在源码里占的地方,按相对的量记,前面的块变长变短、挪了位置它都不跟着变:
|
||||
* 离前一个兄弟块的结尾(第一个子块从父块的开头算,顶层第一块从文件开头算)隔几行(lineGap)、几个字符(gap),
|
||||
* 自己占几行(lines,首尾两行的行号差)、几个字符(length,第一行行首到最后一行行尾)。块的开头是它第一行的行首。
|
||||
*/
|
||||
export interface BlockSpan {
|
||||
lineGap: number
|
||||
gap: number
|
||||
lines: number
|
||||
length: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面上一张卡片画的内容(发给页面的样子,见 pageCard):同 BlockView 的这几样,块里的下标(名字的 offset、refers、defines)
|
||||
* 都从块的开头算;不带行号、头部的最后一行(扩展端自己用),「重写注释」只带是换掉还是新写。
|
||||
*/
|
||||
interface PageCardBase {
|
||||
id: string
|
||||
anchor: string
|
||||
kind: string
|
||||
defines?: SourceRange
|
||||
attributes: BlockAttributes
|
||||
concepts: BlockConcept[]
|
||||
commentTarget?: CommentTarget['kind']
|
||||
badge?: KindBadge
|
||||
slot?: BlockSlot
|
||||
callTree?: CallTreeTarget
|
||||
}
|
||||
|
||||
export type PageCard = PageCardBase & ({ translation: PreviewText, items?: PropertyItem[], table?: PreviewTable, doc?: Markdown, rows?: PropertyRow[] } | { properties: PropertyRow[] })
|
||||
|
||||
/** 发给页面的一块(见 pageBlocks):卡片的内容,在源码里占的地方(相对的,见 BlockSpan),子块。内容没变、只是挪了位置的块,发出去一模一样。 */
|
||||
export type PageBlock = PageCard & {
|
||||
span: BlockSpan
|
||||
children: PageBlock[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 悬停名字、注释里的链接时浮窗里的定义卡片:定义所在的文件(从工作区文件夹算起的相对路径,同挑选框)、定义处那一行(0 起),
|
||||
* 盖住定义处的那块(连同子块,和那个文件的预览画的是同一张卡片),显示成中文名的名字(下标是那个文件里的)。
|
||||
* 盖住定义处的那块(连同子块,和那个文件的预览画的是同一张卡片;它自己当那个文件的顶层第一块,span 从文件开头算),
|
||||
* 显示成中文名的名字(下标是那个文件里的)。
|
||||
*/
|
||||
export interface DefinitionPeek {
|
||||
path: string
|
||||
line: number
|
||||
block: BlockView
|
||||
block: PageBlock
|
||||
names: ShownName[]
|
||||
}
|
||||
|
||||
@@ -64,7 +103,7 @@ export interface DocumentMessage {
|
||||
/** TextDocument.version:webview 靠它判断是不是新一份文档 */
|
||||
version: number
|
||||
languageId: string
|
||||
blocks: BlockView[]
|
||||
blocks: PageBlock[]
|
||||
/** 整份源码和它的着色,只这一份:编辑框里一块的源码、着色按它的编辑范围取;解析失败、语言不支持时是空的(没有块) */
|
||||
source: string
|
||||
colors: SourceColors
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
import type { BlockView } from '../blockView'
|
||||
import type { Inline, PreviewTable, PreviewText, PropertyItem, PropertyRow, Segment, SourceRange } from '../contract'
|
||||
import type { BlockMarks, ItemDiff, ItemsDiff, RowDiff, RowsDiff, TextDiff } from '../diff/viewDiff'
|
||||
import type { BlockSpan, PageBlock, PageCard } from './messages'
|
||||
|
||||
/**
|
||||
* 扩展端的块(位置都是文件里的)→ 发给页面的块(见 PageBlock):块在源码里占的地方按相对的量记(BlockSpan),
|
||||
* 块里的下标从块的开头(第一行的行首)算。内容没变、只是前面的代码变长变短挪了位置的块,发出去一模一样,页面认得出它没变。
|
||||
* 页面那边从文件开头把各块的 span 累加回文件里的位置(webview-ui 的 placement.ts),两边的算法互逆。
|
||||
*/
|
||||
|
||||
/** 一份源码各行行首、行尾(不含换行符)的下标 */
|
||||
export interface SourceLines {
|
||||
start: (line: number) => number
|
||||
end: (line: number) => number
|
||||
}
|
||||
|
||||
export function sourceLines(source: string): SourceLines {
|
||||
const starts = [0]
|
||||
for (let at = source.indexOf('\n'); at >= 0; at = source.indexOf('\n', at + 1))
|
||||
starts.push(at + 1)
|
||||
const start = (line: number): number => starts[Math.min(Math.max(line, 0), starts.length - 1)]
|
||||
const end = (line: number): number => {
|
||||
const next = line + 1 < starts.length ? starts[line + 1] - 1 : source.length
|
||||
return next > start(line) && source[next - 1] === '\r' ? next - 1 : next
|
||||
}
|
||||
return { start, end }
|
||||
}
|
||||
|
||||
function shiftRange(range: SourceRange, base: number): SourceRange {
|
||||
return { startIndex: range.startIndex - base, endIndex: range.endIndex - base }
|
||||
}
|
||||
|
||||
function shiftSegment(segment: Segment, base: number): Segment {
|
||||
if (segment.offset === undefined && !segment.refers)
|
||||
return segment
|
||||
return {
|
||||
...segment,
|
||||
...(segment.offset !== undefined && { offset: segment.offset - base }),
|
||||
...(segment.refers && { refers: shiftRange(segment.refers, base) }),
|
||||
}
|
||||
}
|
||||
|
||||
function shiftInline(pieces: readonly Inline[], base: number): Inline[] {
|
||||
return pieces.map(piece => 'role' in piece ? shiftSegment(piece, base) : { ...piece, segments: shiftInline(piece.segments, base) })
|
||||
}
|
||||
|
||||
function shiftText(text: PreviewText, base: number): PreviewText {
|
||||
return 'markdown' in text ? text : shiftInline(text, base)
|
||||
}
|
||||
|
||||
function shiftItem(item: PropertyItem, base: number): PropertyItem {
|
||||
return {
|
||||
...item,
|
||||
cells: item.cells.map(cell => shiftText(cell, base)),
|
||||
...(item.defines && { defines: shiftRange(item.defines, base) }),
|
||||
...(item.items && { items: item.items.map(inner => shiftItem(inner, base)) }),
|
||||
...(item.table && { table: shiftTable(item.table, base) }),
|
||||
}
|
||||
}
|
||||
|
||||
function shiftTable(table: PreviewTable, base: number): PreviewTable {
|
||||
return { ...table, items: table.items.map(item => shiftItem(item, base)) }
|
||||
}
|
||||
|
||||
function shiftRow(row: PropertyRow, base: number): PropertyRow {
|
||||
return {
|
||||
...row,
|
||||
value: shiftText(row.value, base),
|
||||
...(row.defines && { defines: shiftRange(row.defines, base) }),
|
||||
...(row.items && { items: row.items.map(item => shiftItem(item, base)) }),
|
||||
}
|
||||
}
|
||||
|
||||
/** 一块卡片画的内容(见 PageCard):下标从 base(块第一行的行首在文件里的下标)算,不带行号、子块。 */
|
||||
export function pageCard(block: BlockView, base: number): PageCard {
|
||||
const card = {
|
||||
id: block.id,
|
||||
anchor: block.anchor,
|
||||
kind: block.kind,
|
||||
...(block.defines && { defines: shiftRange(block.defines, base) }),
|
||||
attributes: block.attributes,
|
||||
concepts: block.concepts,
|
||||
...(block.commentTarget && { commentTarget: block.commentTarget.kind }),
|
||||
...(block.badge && { badge: block.badge }),
|
||||
...(block.slot && { slot: block.slot }),
|
||||
...(block.callTree && { callTree: block.callTree }),
|
||||
}
|
||||
if ('properties' in block)
|
||||
return { ...card, properties: block.properties.map(row => shiftRow(row, base)) }
|
||||
return {
|
||||
...card,
|
||||
translation: shiftText(block.translation, base),
|
||||
...(block.items && { items: block.items.map(item => shiftItem(item, base)) }),
|
||||
...(block.table && { table: shiftTable(block.table, base) }),
|
||||
...(block.doc && { doc: block.doc }),
|
||||
...(block.rows && { rows: block.rows.map(row => shiftRow(row, base)) }),
|
||||
}
|
||||
}
|
||||
|
||||
/** 文件里的一处:行号、下标 */
|
||||
interface Point { line: number, offset: number }
|
||||
|
||||
/**
|
||||
* 一串兄弟块发给页面的样子:每块的开头是它第一行的行首、结尾是最后一行的行尾,离前一块的结尾(第一块从 from 算)隔多远、自己多长记成 span,
|
||||
* 子块从这块的开头算起。
|
||||
*/
|
||||
function pageList(blocks: readonly BlockView[], lines: SourceLines, from: Point): PageBlock[] {
|
||||
let cursor = from
|
||||
return blocks.map((block) => {
|
||||
const start = { line: block.startLine, offset: lines.start(block.startLine) }
|
||||
const end = { line: block.endLine, offset: lines.end(block.endLine) }
|
||||
const span: BlockSpan = { lineGap: start.line - cursor.line, gap: start.offset - cursor.offset, lines: end.line - start.line, length: end.offset - start.offset }
|
||||
cursor = end
|
||||
return { ...pageCard(block, start.offset), span, children: pageList(block.children, lines, start) }
|
||||
})
|
||||
}
|
||||
|
||||
/** 一份源码的块树发给页面的样子(见 PageBlock):顶层第一块从文件开头算。 */
|
||||
export function pageBlocks(blocks: readonly BlockView[], source: string): PageBlock[] {
|
||||
return pageList(blocks, sourceLines(source), { line: 0, offset: 0 })
|
||||
}
|
||||
|
||||
function shiftTextDiff(diff: TextDiff, base: number): TextDiff {
|
||||
return 'markdown' in diff ? diff : { inline: diff.inline.map(part => ({ ...part, segments: shiftInline(part.segments, base) })) }
|
||||
}
|
||||
|
||||
function shiftCells(cells: Record<number, TextDiff>, base: number): Record<number, TextDiff> {
|
||||
return Object.fromEntries(Object.entries(cells).map(([column, cell]) => [column, shiftTextDiff(cell, base)]))
|
||||
}
|
||||
|
||||
function shiftItemDiff(diff: ItemDiff, base: number): ItemDiff {
|
||||
return {
|
||||
...diff,
|
||||
...(diff.cells && { cells: shiftCells(diff.cells, base) }),
|
||||
...(diff.items && { items: shiftItemsDiff(diff.items, base) }),
|
||||
...(diff.table && { table: shiftItemsDiff(diff.table, base) }),
|
||||
}
|
||||
}
|
||||
|
||||
function shiftItemsDiff(diff: ItemsDiff, base: number): ItemsDiff {
|
||||
return { ...diff, changed: Object.fromEntries(Object.entries(diff.changed).map(([index, item]) => [index, shiftItemDiff(item, base)])) }
|
||||
}
|
||||
|
||||
function shiftRowDiff(diff: RowDiff, base: number): RowDiff {
|
||||
return {
|
||||
...diff,
|
||||
...(diff.value && { value: shiftTextDiff(diff.value, base) }),
|
||||
...(diff.note && { note: shiftTextDiff(diff.note, base) }),
|
||||
...(diff.items && { items: shiftItemsDiff(diff.items, base) }),
|
||||
}
|
||||
}
|
||||
|
||||
function shiftRowsDiff(diff: RowsDiff, base: number): RowsDiff {
|
||||
return { ...diff, changed: Object.fromEntries(Object.entries(diff.changed).map(([index, row]) => [index, shiftRowDiff(row, base)])) }
|
||||
}
|
||||
|
||||
/** 卡片里要标的改动(BlockMarks)发给页面的样子:新加、没变的词带的下标同卡片的内容,从块的开头(base)算;删掉的词本来就不带下标。 */
|
||||
export function pageMarks(marks: BlockMarks, base: number): BlockMarks {
|
||||
return {
|
||||
...(marks.rows && { rows: shiftRowsDiff(marks.rows, base) }),
|
||||
...(marks.translation && { translation: shiftTextDiff(marks.translation, base) }),
|
||||
...(marks.items && { items: shiftItemsDiff(marks.items, base) }),
|
||||
...(marks.table && { table: shiftItemsDiff(marks.table, base) }),
|
||||
...(marks.doc && { doc: shiftTextDiff(marks.doc, base) }),
|
||||
}
|
||||
}
|
||||
@@ -38,9 +38,10 @@ vi.mock('../folderStore', () => ({ locate: () => ({ folder: { uri: { fsPath: '/w
|
||||
vi.mock('./pathPreview', () => ({ PATH_PREVIEW_SCHEME: 'code-reader-path', topSubjectOf: (uri: unknown) => ({ uri, kind: 'file' }) }))
|
||||
vi.mock('./occurrences', () => ({ occurrencesOf: vi.fn() }))
|
||||
/** 排视图数据不真的解析:一份没有块的文档 */
|
||||
vi.mock('./documentMessage', () => ({
|
||||
vi.mock('./documentMessage', async importOriginal => ({
|
||||
...await importOriginal<typeof import('./documentMessage')>(),
|
||||
documentMessage: vi.fn(async (input: { languageId: string, version: number }) => ({
|
||||
message: { type: 'document', version: input.version, languageId: input.languageId, blocks: [], attributes: [], translators: [], translatorId: '', names: [] },
|
||||
message: { type: 'document', version: input.version, languageId: input.languageId, blocks: [], source: '', colors: { roles: [], runs: [] }, attributes: [], translators: [], translatorId: '', names: [] },
|
||||
displayNames: [],
|
||||
symbols: [],
|
||||
imports: [],
|
||||
@@ -539,7 +540,7 @@ describe('注释里不带路径的引用按它写在哪块的注释里找', () =
|
||||
it('同一个名字:方法说明里的找得到同类的另一个方法,顶层函数说明里的找不到;标坏链接、点了打开都按各自那块找', async () => {
|
||||
const blocks = [declared('class AgentService', 100, [declared(METHOD, 400)]), declared(HELPER, 950)]
|
||||
vi.mocked(documentMessage).mockImplementationOnce(async input => ({
|
||||
message: { type: 'document', version: input.version, languageId: input.languageId, blocks, attributes: [], translators: [], translatorId: '', names: [] },
|
||||
message: { type: 'document', version: input.version, languageId: input.languageId, blocks, source: '', colors: { roles: [], runs: [] }, attributes: [], translators: [], translatorId: '', names: [] },
|
||||
displayNames: [],
|
||||
symbols: [],
|
||||
imports: [],
|
||||
|
||||
@@ -38,10 +38,10 @@ import { askPrompt, followUpPrompt } from '../qa/prompt'
|
||||
import { DocumentLookups } from '../ruleLookups'
|
||||
import { referenceScope, resolveReference } from '../symbolLinks'
|
||||
import { definitionAction } from './definitionAction'
|
||||
import { definitionSiteNames, namesOnCard, peekBlock } from './definitionPeek'
|
||||
import { definitionSiteNames, namesOnCard, pagePeekBlock, peekBlock } from './definitionPeek'
|
||||
import { definitionKind, findDefinitions, languageDefinitions, pickDefinition, ruleDefinitions } from './definitions'
|
||||
import { DefinitionSources } from './definitionSources'
|
||||
import { documentMessage } from './documentMessage'
|
||||
import { documentMessage, pageDocument } from './documentMessage'
|
||||
import { documentSymbolNodes } from './documentSymbols'
|
||||
import { NavigationContext, OCCURRENCES_CONTEXT } from './occurrenceNavigation'
|
||||
import { occurrencesOf } from './occurrences'
|
||||
@@ -431,7 +431,7 @@ class Preview {
|
||||
const reveal = this.pendingReveal
|
||||
this.pendingReveal = undefined
|
||||
this.shown = version
|
||||
this.post({ ...message, names: this.names.known(version), ...(reveal && { reveal }) })
|
||||
this.post({ ...pageDocument(message), names: this.names.known(version), ...(reveal && { reveal }) })
|
||||
if (this.sent)
|
||||
void this.diff.update(this.sent)
|
||||
// 文档在解析期间又改了的,等下一次发文档再查
|
||||
@@ -847,8 +847,10 @@ class Preview {
|
||||
const path = workspace.asRelativePath(uri)
|
||||
if (uri.toString() === this.document.uri.toString()) {
|
||||
const { sent } = this
|
||||
const block = sent?.version === target.version ? peekBlock(sent.blocks, offset, line) : undefined
|
||||
return block && { path, line, block, names: namesOnCard(block, this.names.known(target.version)) }
|
||||
if (sent?.version !== target.version)
|
||||
return undefined
|
||||
const block = peekBlock(sent.blocks, offset, line)
|
||||
return block && { path, line, block: pagePeekBlock(block, sent.source), names: namesOnCard(block, this.names.known(target.version)) }
|
||||
}
|
||||
const { message, displayNames } = await documentMessage(
|
||||
{ languageId: target.languageId, version: target.version, getText: () => target.getText(), fileName: target.fileName, entryNames: this.owner.entries.namesOf(uri) },
|
||||
@@ -858,7 +860,7 @@ class Preview {
|
||||
() => {},
|
||||
)
|
||||
const block = message.error === undefined ? peekBlock(message.blocks, offset, line) : undefined
|
||||
return block && { path, line, block, names: namesOnCard(block, definitionSiteNames(displayNames)) }
|
||||
return block && { path, line, block: pagePeekBlock(block, message.source), names: namesOnCard(block, definitionSiteNames(displayNames)) }
|
||||
}
|
||||
catch (err) {
|
||||
logger.add({ level: 'warn', source: 'codeReader', message: `没能读出 ${uri.toString()} 里定义的那块:${err instanceof Error ? err.message : String(err)}` })
|
||||
|
||||
Reference in new issue
Block a user