✨ feat(vscode): 代码阅读的解析与模板直译核心
This commit is contained in:
1 parent
af56985d9a
commit
4d34b8c715
24 files changed
+2294
No files matched your search
@@ -0,0 +1,88 @@
|
||||
import type { Outline } from '../testSupport'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { outline, readFixture, WASM_DIR, withBlocks } from '../testSupport'
|
||||
import { createPythonAdapter } from './python'
|
||||
|
||||
const adapter = createPythonAdapter(WASM_DIR)
|
||||
|
||||
function tree(source: string): Promise<Outline[]> {
|
||||
return withBlocks(adapter, 'python', source, outline)
|
||||
}
|
||||
|
||||
// fixtures/sample.py:行号 1 起
|
||||
const SAMPLE: Outline[] = [
|
||||
{ at: 1, kind: 'comment' },
|
||||
{ at: 3, kind: 'import' },
|
||||
{ at: 4, kind: 'import' },
|
||||
{ at: 6, kind: 'const' },
|
||||
{ at: 7, kind: 'variable' },
|
||||
{ at: 10, kind: 'function', kids: [
|
||||
{ at: 11, kind: 'comment' },
|
||||
{ at: 12, kind: 'comment' },
|
||||
{ at: 13, kind: 'variable' },
|
||||
{ at: 14, kind: 'if', kids: [{ at: 15, kind: 'return' }] },
|
||||
{ at: 16, kind: 'else', kids: [{ at: 17, kind: 'variable' }] },
|
||||
{ at: 18, kind: 'else', kids: [{ at: 19, kind: 'statement' }] },
|
||||
{ at: 20, kind: 'loop', kids: [
|
||||
{ at: 21, kind: 'if', kids: [{ at: 22, kind: 'statement' }] },
|
||||
] },
|
||||
{ at: 23, kind: 'try', kids: [
|
||||
{ at: 24, kind: 'statement', kids: [{ at: 25, kind: 'statement' }] },
|
||||
] },
|
||||
{ at: 26, kind: 'catch', kids: [{ at: 27, kind: 'statement' }] },
|
||||
{ at: 28, kind: 'finally', kids: [{ at: 29, kind: 'statement' }] },
|
||||
{ at: 30, kind: 'return' },
|
||||
] },
|
||||
{ at: 33, kind: 'class', kids: [
|
||||
{ at: 34, kind: 'field' },
|
||||
{ at: 35, kind: 'field' },
|
||||
{ at: 36, kind: 'field' },
|
||||
{ at: 37, kind: 'variable' },
|
||||
{ at: 39, kind: 'function', kids: [{ at: 40, kind: 'return' }] },
|
||||
] },
|
||||
]
|
||||
|
||||
describe('python 代码块树', () => {
|
||||
it('样例覆盖 import / def / docstring / if-elif-else / for / try-except-finally / with / 推导式 / class 字段', async () => {
|
||||
expect(await tree(readFixture('sample.py'))).toEqual(SAMPLE)
|
||||
})
|
||||
|
||||
it('装饰器算进头部;冒号后、主体前的注释归子块;循环的 else 是兄弟块;match 的 case 是子块 if', async () => {
|
||||
const source = [
|
||||
'@cache',
|
||||
'def load(key):',
|
||||
' # 先查缓存',
|
||||
' while key:',
|
||||
' key = key[1:]',
|
||||
' else:',
|
||||
' pass',
|
||||
' match key:',
|
||||
' case \'a\':',
|
||||
' return 1',
|
||||
' case _:',
|
||||
' return 2',
|
||||
].join('\n')
|
||||
expect(await tree(source)).toEqual([
|
||||
{ at: [1, 2], kind: 'function', kids: [
|
||||
{ at: 3, kind: 'comment' },
|
||||
{ at: 4, kind: 'loop', kids: [{ at: 5, kind: 'variable' }] },
|
||||
{ at: 6, kind: 'else', kids: [{ at: 7, kind: 'statement' }] },
|
||||
{ at: 8, kind: 'if', kids: [
|
||||
{ at: 9, kind: 'if', kids: [{ at: 10, kind: 'return' }] },
|
||||
{ at: 11, kind: 'if', kids: [{ at: 12, kind: 'return' }] },
|
||||
] },
|
||||
] },
|
||||
])
|
||||
})
|
||||
|
||||
it('docstring 只认主体开头;不是开头的字符串表达式是语句', async () => {
|
||||
const source = [
|
||||
'def f():',
|
||||
' x = 1',
|
||||
' """not a docstring"""',
|
||||
].join('\n')
|
||||
expect(await tree(source)).toEqual([
|
||||
{ at: 1, kind: 'function', kids: [{ at: 2, kind: 'variable' }, { at: 3, kind: 'statement' }] },
|
||||
])
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user