47 lines
2.2 KiB
TypeScript
47 lines
2.2 KiB
TypeScript
import type { CodeBlock, Node } from '../contract'
|
|
import { syntaxChildren } from './pythonTree'
|
|
|
|
/** 库规则共用的挑子块的办法。 */
|
|
|
|
/** 紧挨在 child 前面的注释块(连着几块都算,中间没隔别的子块),照源码顺序:讲的是它下面的这个 child。 */
|
|
export function leadingComments(children: readonly CodeBlock[], child: CodeBlock): CodeBlock[] {
|
|
const at = children.indexOf(child)
|
|
let from = at
|
|
while (from > 0 && children[from - 1].kind === 'comment')
|
|
from--
|
|
return children.slice(from, at)
|
|
}
|
|
|
|
/**
|
|
* 要并进卡片的子块:成员连同各自前面紧挨着的注释块,照源码顺序。成员并进来了,讲它的注释跟着并,不在卡片下面单独留一块;
|
|
* 讲别的子块(方法)的注释、最后一个子块后面的注释照常留下。
|
|
*/
|
|
export function withLeadingComments(children: readonly CodeBlock[], members: readonly CodeBlock[]): CodeBlock[] {
|
|
return children.filter(child => members.includes(child))
|
|
.flatMap(member => [...leadingComments(children, member), member])
|
|
}
|
|
|
|
/** 注释块里的各条注释(几条行注释连成的一块是好几个节点);当注释用的字符串是那个字符串。 */
|
|
function commentNodes(block: CodeBlock): Node[] {
|
|
if (block.node.type !== 'comment')
|
|
return syntaxChildren(block.node).slice(0, 1)
|
|
const nodes: Node[] = []
|
|
for (let node: Node | null = block.node; node?.type === 'comment' && node.endIndex <= block.header.endIndex; node = node.nextSibling)
|
|
nodes.push(node)
|
|
return nodes
|
|
}
|
|
|
|
/**
|
|
* Python 类主体里一个成员(赋值、只写注解的字段)的说明,照源码顺序:紧挨在它上面的注释块、它这一行行尾的注释、
|
|
* 紧跟在它后面的属性 docstring。
|
|
*/
|
|
export function memberDocs(children: readonly CodeBlock[], block: CodeBlock): Node[] {
|
|
const trailing = block.node.nextSibling
|
|
const doc = block.kind === 'variable' ? block.facts.doc : block.kind === 'field' ? block.doc : undefined
|
|
return [
|
|
...leadingComments(children, block).flatMap(commentNodes),
|
|
...(trailing?.type === 'comment' && trailing.startPosition.row === block.node.endPosition.row ? [trailing] : []),
|
|
...(doc ? [doc] : []),
|
|
]
|
|
}
|