🐛 fix(vscode): 代码阅读把 Python 赋值后面的字符串当变量说明,其余单独的字符串显示成注释

This commit is contained in:
cruldra committed 2026-09-26 18:57:07 +08:00
1 parent a51f90e34d
commit 1f86201373
14 files changed
+358 -59

No files matched your search

@@ -209,6 +209,35 @@ describe('sqlAlchemy 库规则', () => {
expect(user.children.map(child => [child.kind, child.startLine])).toEqual([['function', 20]])
})
it('字段的属性 docstring:没写 comment= 时当说明,写了以 comment= 为准;它并进卡片,编辑范围到最后一个字段的说明为止', async () => {
const source = [
'from sqlalchemy.orm import Mapped, mapped_column',
'',
'',
'class Case(Base):',
' __tablename__ = "case_library"',
'',
' title: Mapped[str] = mapped_column(String(120))',
' """案例标题, 用户可编辑"""',
' summary: Mapped[str] = mapped_column(Text, comment="案例描述")',
' """不显示"""',
' status = mapped_column(String(16))',
' """案例状态"""',
'',
' def label(self) -> str:',
' return self.title',
].join('\n')
const [, table] = await views(source)
expect(propertyLines(properties(table)).slice(-4)).toEqual([
'字段: 3 个',
' title | 字符串(120) | | 案例标题, 用户可编辑',
' summary | 长文本 | | 案例描述',
' status | 字符串(16) | 可空 | 案例状态',
])
expect([table.startLine, table.endLine]).toEqual([3, 11])
expect(table.children.map(child => [child.kind, child.startLine])).toEqual([['function', 13]])
})
it('没导入 SQLAlchemy 的文件不认', async () => {
const list = await views('class User(Base):\n __tablename__ = "users"\n')
expect(list.map(view => view.kind)).toEqual(['class'])
+12 -4
View File
@@ -123,12 +123,13 @@ interface Call {
keywords: Map<string, Node>
}
/** 类主体里一条给名字赋值(或只写注解)的语句。 */
/** 类主体里一条给名字赋值(或只写注解)的语句;doc 是它的属性 docstring(字段的 doc、变量的 facts.doc)。 */
interface Member {
block: CodeBlock
name: Node
annotation?: Node
value?: Node
doc?: Node
}
/** 一个字段:只写 `Mapped[...]` 注解的没有 call。 */
@@ -225,7 +226,13 @@ function memberOf(block: CodeBlock): Member | undefined {
const name = assignment?.type === 'assignment' ? assignment.childForFieldName('left') : null
if (!assignment || name?.type !== 'identifier')
return undefined
return { block, name, annotation: assignment.childForFieldName('type') ?? undefined, value: assignment.childForFieldName('right') ?? undefined }
return {
block,
name,
annotation: assignment.childForFieldName('type') ?? undefined,
value: assignment.childForFieldName('right') ?? undefined,
doc: 'facts' in block ? block.facts.doc : block.doc,
}
}
/** 注解里 `type` 节点只包着一个类型时取里面那个。 */
@@ -424,7 +431,7 @@ function isNullable(call: Call | undefined, optional: boolean | undefined): bool
return call?.name === 'Column' || optional === undefined ? true : optional
}
/** 字段表的一行:字段 | 类型 | 约束 | 说明。讲的定义是字段名。 */
/** 字段表的一行:字段 | 类型 | 约束 | 说明(`comment=`,没写时用字段的属性 docstring 原文)。讲的定义是字段名。 */
function columnItem({ member, call }: Column, env: Env): PropertyItem {
const { words, context } = env
const mapped = mappedType(member.annotation)
@@ -452,12 +459,13 @@ function columnItem({ member, call }: Column, env: Env): PropertyItem {
for (const foreign of calls.filter((found): found is Call => found?.name === 'ForeignKey'))
constraints.push(foreignKey(foreign, env))
const comment = keywords.get('comment')
const doc = member.doc && context.doc(member.doc)
return {
cells: [
[name(member.name, 'variable')],
typeArg ? sqlType(typeArg, env) : annotated ? context.translate(annotated.type) : [hint(words.unannotated)],
joined(constraints, hint(' · ')),
comment ? textOr(comment, 'comment', env) : [],
comment ? textOr(comment, 'comment', env) : doc ? [{ text: doc.markdown, role: 'comment' }] : [],
],
defines: range(member.name),
}