✨ feat(vscode): 代码阅读的调用与构造:跨多行写的调用排成「新建 / 调用 名字 · N 个参数」一行,实参摊成参数 / 值表;Python 查被调用名字的定义分新建和调用,查到后刷新
This commit is contained in:
1 parent
ebf228cdc7
commit
ecc415d763
30 files changed
+1033
-157
No files matched your search
@@ -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,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user