🐛 fix(vscode): 写注释时改已有说明,不再在声明上面另插一行

This commit is contained in:
cruldra committed 2026-10-08 09:55:36 +08:00
1 parent 63dfb658e9
commit 7f39345d03
11 files changed
+196 -36

No files matched your search

+76 -10
View File
@@ -5,9 +5,11 @@ import { toBlockViews } from './blockView'
import { COMMENT_SKILL, commentEdit, commentRewritePrompt, commentSource, createCommentParser, findBlock, refillComment, rewriteBlockComment } from './commentRewrite'
import { commonIndent, replaceLines, splitLines } from './editText'
import { createPythonAdapter } from './languages/python'
import { createRustAdapter } from './languages/rust'
import { createTypeScriptAdapter } from './languages/typescript'
import { WASM_DIR, withBlocks } from './testSupport'
import { pythonZhTranslator } from './translators/pythonZh'
import { rustZhTranslator } from './translators/rustZh'
import { typescriptZhTranslator } from './translators/typescriptZh'
/** 和预览写回同一条路:正文套回壳,再按原来的缩进替换这几行。 */
@@ -90,6 +92,11 @@ describe('重写注释后套回原来的壳', () => {
].join('\n'))
})
it('三斜杠和模块内文档注释:记号留着,不收成 //', () => {
expect(refillComment('/// 旧说明', '新说明')).toBe('/// 新说明')
expect(refillComment('//! 旧说明', '新说明')).toBe('//! 新说明')
})
it('双斜杠行注释同样只换正文', () => {
const file = [
'function keep() {',
@@ -194,10 +201,10 @@ async function pythonBlock(source: string, line: number): Promise<BlockView> {
return found
}
function job(block: BlockView, path = 'src/a.py', lineComment = '#'): CommentRewriteJob {
function job(block: BlockView, path = 'src/a.py'): CommentRewriteJob {
if (!block.commentTarget)
throw new Error('这块不能写注释')
return { target: block.commentTarget, startLine: block.startLine, endLine: block.endLine, path, lineComment }
return { target: block.commentTarget, startLine: block.startLine, endLine: block.endLine, path }
}
const SOURCE = [
@@ -227,13 +234,54 @@ describe('重写一块代码的注释', () => {
expect(file.text()).toBe(SOURCE.replace('# 旧的说明\n\n# 第二段', '# 仓库:按名字找文件。'))
})
it('还没有注释的块:用行注释记号新写一段,插在块上面,缩进同块的第一行;说明(docstring)不动', async () => {
it('函数已经有 docstring、上面没有 #:换掉 docstring 的正文,不在 def 上面再插一行', async () => {
const source = 'class Repo:\n def find(self):\n """找。"""\n return 1\n'
const find = await pythonBlock(source, 2)
expect(find.commentTarget).toEqual({ kind: 'insert', line: 1 })
expect(find.commentTarget).toEqual({ kind: 'replace', startLine: 2, endLine: 2 })
const file = memoryFile(source)
expect(await rewriteBlockComment(job(find), file.deps(async () => '按名字找\n\n找不到时返回 1'))).toEqual({ status: 'done' })
expect(file.text()).toBe('class Repo:\n # 按名字找\n #\n # 找不到时返回 1\n def find(self):\n """找。"""\n return 1\n')
const prompts: string[] = []
expect(await rewriteBlockComment(job(find), file.deps(async (prompt) => {
prompts.push(prompt)
return '按名字找\n\n找不到时返回 1'
}))).toEqual({ status: 'done' })
expect(prompts).toEqual(['/ecc:writing-code-comments src/a.py:2-4'])
expect(file.text()).toBe('class Repo:\n def find(self):\n """按名字找\n\n 找不到时返回 1\n """\n return 1\n')
})
it('函数既没有 docstring 也没有前面的 #:在主体里插一段 docstring,不在 def 上面写 #', async () => {
const source = 'def find(self):\n return 1\n'
const find = await pythonBlock(source, 1)
expect(find.commentTarget).toEqual({ kind: 'insert', line: 1, shell: '"""_"""' })
const file = memoryFile(source)
expect(await rewriteBlockComment(job(find), file.deps(async () => '按名字找。'))).toEqual({ status: 'done' })
expect(file.text()).toBe('def find(self):\n """按名字找。"""\n return 1\n')
})
it('声明和主体写在同一行:docstring 插进主体,不写在 def 上面', async () => {
const source = 'def find(): return 1\n'
const find = await pythonBlock(source, 1)
expect(find.commentTarget).toMatchObject({ kind: 'insert', line: 0, shell: '"""_"""' })
const file = memoryFile(source)
expect(await rewriteBlockComment(job(find), file.deps(async () => '按名字找。'))).toEqual({ status: 'done' })
expect(file.text()).toBe('def find():\n """按名字找。"""\n return 1\n')
})
it('函数只有前面的 #、没有 docstring:仍换掉那段 #', async () => {
const source = '# 旧的说明\ndef find():\n return 1\n'
const find = await pythonBlock(source, 1)
expect(find.commentTarget).toEqual({ kind: 'replace', startLine: 0, endLine: 0 })
const file = memoryFile(source)
expect(await rewriteBlockComment(job(find), file.deps(async () => '按名字找。'))).toEqual({ status: 'done' })
expect(file.text()).toBe('# 按名字找。\ndef find():\n return 1\n')
})
it('docstring 和前面的 # 都有:只换 docstring,# 留着', async () => {
const source = '# 旧的说明\ndef find():\n """找。"""\n return 1\n'
const find = await pythonBlock(source, 1)
expect(find.commentTarget).toEqual({ kind: 'replace', startLine: 2, endLine: 2 })
const file = memoryFile(source)
expect(await rewriteBlockComment(job(find), file.deps(async () => '新的说明。'))).toEqual({ status: 'done' })
expect(file.text()).toBe('# 旧的说明\ndef find():\n """新的说明。"""\n return 1\n')
})
it('文件开头的说明卡片换的是它自己:范围就是这段注释', async () => {
@@ -284,13 +332,31 @@ describe('重写一块代码的注释', () => {
expect(stopped.writes).toEqual([])
})
it('用 // 写 TypeScript 的块:JSDoc 是说明,不当成要换掉的注释', async () => {
it('typescript 已经有 JSDoc:换掉这段说明,不在声明上面再写 //', async () => {
const ts = createTypeScriptAdapter(WASM_DIR)
const source = '/** 读配置。 */\nexport function load() {}\n'
const [view] = await withBlocks(ts, 'typescript', source, blocks => toBlockViews(blocks, { source, language: ts, markers: [] }, typescriptZhTranslator))
expect(view.commentTarget).toEqual({ kind: 'insert', line: 0 })
const edit = commentEdit(view.commentTarget as CommentTarget, index => splitLines(source)[index], '启动时读一次', ts.lineComment)
expect(edit).toEqual({ kind: 'insert', line: 0, text: '// 启动时读一次' })
expect(view.commentTarget).toEqual({ kind: 'replace', startLine: 0, endLine: 0 })
const edit = commentEdit(view.commentTarget as CommentTarget, index => splitLines(source)[index], '启动时读一次')
expect(edit).toEqual({ kind: 'replace', startLine: 0, endLine: 0, text: '/** 启动时读一次 */' })
})
it('typescript 还没有说明:在声明上面插 /** */,不写 //', async () => {
const ts = createTypeScriptAdapter(WASM_DIR)
const source = 'export function load() {}\n'
const [view] = await withBlocks(ts, 'typescript', source, blocks => toBlockViews(blocks, { source, language: ts, markers: [] }, typescriptZhTranslator))
expect(view.commentTarget).toEqual({ kind: 'insert', line: 0, shell: '/** _ */' })
const edit = commentEdit(view.commentTarget as CommentTarget, index => splitLines(source)[index], '启动时读一次')
expect(edit).toEqual({ kind: 'insert', line: 0, text: '/** 启动时读一次 */' })
})
it('rust 还没有说明:在项上面插 ///,不写 //', async () => {
const rust = createRustAdapter(WASM_DIR)
const source = 'fn load() {}\n'
const [view] = await withBlocks(rust, 'rust', source, blocks => toBlockViews(blocks, { source, language: rust, markers: [] }, rustZhTranslator))
expect(view.commentTarget).toEqual({ kind: 'insert', line: 0, shell: '/// _' })
const edit = commentEdit(view.commentTarget as CommentTarget, index => splitLines(source)[index], '启动时读一次')
expect(edit).toEqual({ kind: 'insert', line: 0, text: '/// 启动时读一次' })
})
})