Files
superwork/vscode/src/codeReader/editText.test.ts
T

80 lines
3.3 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { blockCodes, toBlockViews } from './blockView'
import { blockReplacement, commonIndent, reindentBlock, replaceLines } from './editText'
import { createPythonAdapter } from './languages/python'
import { createTypeScriptAdapter } from './languages/typescript'
import { readFixture, WASM_DIR, withBlocks } from './testSupport'
describe('行替换', () => {
it('多行块替换后每个非空行补回原来的缩进,空行保持空', () => {
const source = [
'function f() {',
' if (a)',
' return 1',
'}',
].join('\n')
const edited = replaceLines(source, 1, 2, 'if (a && b) {\n\n return 2\n}')
expect(edited).toBe([
'function f() {',
' if (a && b) {',
'',
' return 2',
' }',
'}',
].join('\n'))
})
it('保留 \\r\\n 换行', () => {
expect(replaceLines('a\r\n b\r\n c\r\n', 1, 1, 'x\ny')).toBe('a\r\n x\r\n y\r\n c\r\n')
})
it('共同缩进逐字符比,混用制表符和空格时只取相同的前缀', () => {
expect(commonIndent(['\t a', '', '\t b'])).toBe('\t ')
expect(commonIndent(['\ta', ' b'])).toBe('')
expect(reindentBlock([' x'], 'a\n b')).toBe(' a\n b')
})
it.each([
[createTypeScriptAdapter(WASM_DIR), 'typescript', 'envLock.ts.txt'],
[createTypeScriptAdapter(WASM_DIR), 'typescript', 'issueLock.ts.txt'],
[createTypeScriptAdapter(WASM_DIR), 'typescript', 'classes.ts.txt'],
[createPythonAdapter(WASM_DIR), 'python', 'sample.py'],
[createPythonAdapter(WASM_DIR), 'python', 'routes.py'],
[createPythonAdapter(WASM_DIR), 'python', 'classes.py'],
] as const)('%#: 把预览里的 code 原样写回,文件不变(去缩进与补缩进互逆,函数、类头部连着说明也一样)', async (adapter, languageId, fixture) => {
const source = readFixture(fixture)
const views = await withBlocks(adapter, languageId, source, blocks => toBlockViews(blocks, { source, language: adapter, markers: [] }, undefined))
const all = views.flatMap(function flat(view): typeof views {
return [view, ...view.children.flatMap(flat)]
})
for (const view of all)
expect(replaceLines(source, view.startLine, view.endLine, blockCodes(source)(view)), view.id).toBe(source)
})
})
describe('块内修改写回的替换范围', () => {
const doc = ['class A {', ' run() {', ' go()', ' }', '}']
const lineAt = (n: number): string => doc[n]
it('从起始行行首替换到结束行行尾,新文本补回原来的缩进', () => {
expect(blockReplacement(lineAt, doc.length, 1, 2, 'run(): void {\n go(1)')).toEqual({
startLine: 1,
endLine: 2,
endCharacter: 8,
text: ' run(): void {\n go(1)',
unchanged: false,
})
})
it('改完和原来一样时标记 unchanged', () => {
expect(blockReplacement(lineAt, doc.length, 1, 2, 'run() {\n go()')?.unchanged).toBe(true)
})
it('行号已不在文档里时不替换', () => {
expect(blockReplacement(lineAt, doc.length, 3, 5, 'x')).toBeUndefined()
expect(blockReplacement(lineAt, doc.length, -1, 0, 'x')).toBeUndefined()
expect(blockReplacement(lineAt, doc.length, 2, 1, 'x')).toBeUndefined()
expect(blockReplacement(lineAt, doc.length, 0.5, 1, 'x')).toBeUndefined()
})
})