✨ 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

+38 -1
View File
@@ -1,4 +1,4 @@
import type { Access, BlockShape, ClassFacts, CodeBlock, EntryFacts, FunctionFacts, ImportFacts, ImportItem, IterationClause, IterationFacts, IterationResult, LanguageAdapter, Node, ParameterFacts, TextKind, TokenRole } from '../contract'
import type { Access, BlockShape, CallArgument, CallFacts, ClassFacts, CodeBlock, EntryFacts, FunctionFacts, ImportFacts, ImportItem, IterationClause, IterationFacts, IterationResult, LanguageAdapter, Node, ParameterFacts, TextKind, TokenRole } from '../contract'
import type { CommentRules, ExceptionRules } from './shared'
import * as path from 'node:path'
import { pythonNameReader } from './pythonNames'
@@ -363,6 +363,42 @@ function pythonIteration(node: Node): IterationFacts | undefined {
}
/** elif / else 展平成紧跟 if 的兄弟块。 */
/** 调用的实参:name=value 按名字传,*x、**x 展开,别的按位置传;唯一的实参是生成器表达式(f(x for x in y))时就是它。 */
function callArgument(arg: Node): CallArgument | undefined {
switch (arg.type) {
case 'keyword_argument': {
const name = arg.childForFieldName('name')
const value = arg.childForFieldName('value')
return name && value ? { kind: 'keyword', name, value } : undefined
}
case 'list_splat':
case 'dictionary_splat': {
const [value] = syntaxChildren(arg)
if (!value)
return undefined
return { kind: arg.type === 'list_splat' ? 'spread' : 'keywordSpread', value }
}
default:
return { kind: 'positional', value: arg }
}
}
/** 调用的结构:新建对象和调用函数写法一样,不给 construct。被调用的是名字或点分名字时 name 是最后那个名字。 */
function pythonCall(node: Node): CallFacts | undefined {
const callee = node.type === 'call' ? node.childForFieldName('function') : null
const list = node.childForFieldName('arguments')
if (!callee || !list)
return undefined
const name = callee.type === 'identifier' ? callee : callee.type === 'attribute' ? callee.childForFieldName('attribute') : null
const args = list.type === 'generator_expression' ? [list] : syntaxChildren(list)
return {
callee,
...(name && { name }),
argumentList: list,
arguments: args.map(callArgument).filter(arg => arg !== undefined),
}
}
function ifBlocks(node: Node): CodeBlock[] {
const blocks = [bodyBlock('if', node, bodyOf(node), 'other')]
for (const alternative of node.childrenForFieldName('alternative')) {
@@ -603,6 +639,7 @@ export function createPythonAdapter(wasmDir: string): LanguageAdapter {
toBlocks: root => withExceptions(statements(named(root), 'module', -1), PYTHON_EXCEPTIONS),
tokenRole: pythonTokenRole,
iteration: pythonIteration,
call: pythonCall,
displayNames: pythonNameReader,
}
}