✨ feat(vscode): 代码阅读的调用与构造:跨多行写的调用排成「新建 / 调用 名字 · N 个参数」一行,实参摊成参数 / 值表;Python 查被调用名字的定义分新建和调用,查到后刷新

This commit is contained in:
cruldra committed 2026-09-27 22:08:16 +08:00
1 parent ebf228cdc7
commit ecc415d763
30 files changed
+1033 -157

No files matched your search

+47 -9
View File
@@ -1,4 +1,4 @@
import type { BlockAttributes, CodeBlock, DisplayName, KindBadge, LanguageAdapter, LibraryRule, Markdown, Node, PreviewText, PropertyRow, RuleContext, Segment, SourceDocument, SourceRange, TextBlock, TokenRole, Translator } from './contract'
import type { BlockAttributes, BlockKind, CodeBlock, DisplayName, KindBadge, LanguageAdapter, LibraryRule, Markdown, Node, PreviewTable, PreviewText, PropertyRow, RuleContext, Segment, SourceDocument, SourceRange, TextBlock, TokenRole, Translator } from './contract'
import type { TreeSitterRuntime } from './runtime'
import { blockAttributes } from './attributes'
import { commonIndent, splitLines } from './editText'
@@ -33,9 +33,9 @@ interface BlockViewBase {
/**
* 发给 webview 的一块(可序列化):函数、类、枚举、异常、导入、常量、变量块和库规则的卡片预览时是属性表,注释块是 Markdown 说明,其余是一行译文。
* 一行译文的块带说明(TextBlock.doc)时 doc 是翻译插件给的 Markdown 原文,预览排在译文下面。
* 一行译文下面依次是:跨几行写的调用摊开各个实参的表(TextTranslation.table),块的说明(TextBlock.doc,翻译插件给的 Markdown 原文)。
*/
export type BlockView = BlockViewBase & ({ translation: PreviewText, doc?: Markdown } | { properties: PropertyRow[] })
export type BlockView = BlockViewBase & ({ translation: PreviewText, table?: PreviewTable, doc?: Markdown } | { properties: PropertyRow[] })
interface Line { start: number, end: number }
@@ -159,10 +159,13 @@ export function toBlockViews(blocks: CodeBlock[], document: SourceDocument, tran
codeTokens: colorLines(root, source, lines, startRow, endRow, indent, adapter.tokenRole),
}
}
/** 一行译文,带说明的块连着说明。 */
const textView = (block: TextBlock): { translation: PreviewText, doc?: Markdown } => {
const doc = block.doc && translator?.doc(block.doc, document)
return { translation: translator ? translator.translate(block, document) : [], ...(doc && { doc }) }
/** 一行译文,连着摊开实参的表、块的说明(有才有)。 */
const textView = (block: TextBlock): { translation: PreviewText, table?: PreviewTable, doc?: Markdown } => {
if (!translator)
return { translation: [] }
const { text, table } = translator.translate(block, document)
const doc = block.doc && translator.doc(block.doc, document)
return { translation: text, ...(table && { table }), ...(doc && { doc }) }
}
/** 按源码先后逐块给位置记号:先序遍历,块的记号在它的子块之前要 */
const anchors = new BlockAnchors()
@@ -215,7 +218,10 @@ export interface DocumentViews {
displayNames: DisplayName[]
}
/** 解析一份源码并转成视图数据(中文名记号交给翻译插件去掉);语法树用完即释放。 */
/**
* 解析一份源码并转成视图数据(中文名记号交给翻译插件去掉);语法树用完即释放。
* calleeKind 交出调用的名字的定义眼下查到是哪种块(SourceDocument.calleeKind)。
*/
export async function readBlockViews(
runtime: Pick<TreeSitterRuntime, 'parse'>,
adapter: LanguageAdapter,
@@ -223,14 +229,46 @@ export async function readBlockViews(
languageId: string,
source: string,
rules: RuleRun = NO_RULES,
calleeKind?: SourceDocument['calleeKind'],
): Promise<DocumentViews> {
const tree = await runtime.parse(adapter, languageId, source)
try {
const { names, markers } = adapter.displayNames?.find(tree.rootNode, source, languageId) ?? { names: [], markers: [] }
const blocks = toBlockViews(adapter.toBlocks(tree.rootNode, source, languageId), { source, language: adapter, markers }, translator, rules)
const document: SourceDocument = { source, language: adapter, markers, ...(calleeKind && { calleeKind }) }
const blocks = toBlockViews(adapter.toBlocks(tree.rootNode, source, languageId), document, translator, rules)
return { blocks, displayNames: names }
}
finally {
tree.delete()
}
}
/** 块树里自己的名字(见 ownName)盖住 offset 的最里层那块的种类;offset 不在哪块的名字上时没有。 */
export function blockKindAt(blocks: readonly CodeBlock[], offset: number): BlockKind | undefined {
for (const block of blocks) {
const inner = blockKindAt(block.children, offset)
if (inner)
return inner
const name = ownName(block)
if (name && name.startIndex <= offset && offset < name.endIndex)
return block.kind
}
return undefined
}
/** 解析一份源码,offset 处的名字定义的是哪种块(见 blockKindAt);语法树用完即释放。 */
export async function readDefinitionKind(
runtime: Pick<TreeSitterRuntime, 'parse'>,
adapter: LanguageAdapter,
languageId: string,
source: string,
offset: number,
): Promise<BlockKind | undefined> {
const tree = await runtime.parse(adapter, languageId, source)
try {
return blockKindAt(adapter.toBlocks(tree.rootNode, source, languageId), offset)
}
finally {
tree.delete()
}
}