✨ feat(vscode): 代码阅读的 React 钩子统一成一张钩子卡片,照签名排参数和返回,自定义钩子有自己的卡片

This commit is contained in:
cruldra committed 2026-10-16 20:18:21 +11:00
1 parent 78d0c9dada
commit e7059bcc73
17 files changed
+1409 -589

No files matched your search

+2 -1
View File
@@ -7,7 +7,7 @@ import type { FileAttribute } from '../attributes'
import type { BlockSlot, CallTreeTarget, ChainSlot, CommentTarget, SourceColors } from '../blockView'
import type { ContractMiss } from '../callTree/endpoint'
import type { CallTree } from '../callTree/model'
import type { BlockAttributes, BlockConcept, KindBadge, Markdown, PreviewTable, PreviewText, PropertyItem, PropertyRow, SourceRange } from '../contract'
import type { BlockAttributes, BlockConcept, KindBadge, Markdown, PreviewTable, PreviewText, PropertyItem, PropertyRow, SourceRange, ThemeColor } from '../contract'
import type { OpenedFrom } from '../diff/diffBase'
import type { DocumentDiff } from '../diff/previewDiff'
import type { ShownName } from '../nameResolution'
@@ -84,6 +84,7 @@ interface PageCardBase {
concepts: BlockConcept[]
commentTarget?: CommentTarget['kind']
badge?: KindBadge
tint?: ThemeColor
slot?: BlockSlot
step?: ChainSlot
callTree?: CallTreeTarget
@@ -4,9 +4,12 @@ import { describe, expect, it } from 'vitest'
import { toBlockViews } from '../blockView'
import { createPythonAdapter } from '../languages/python'
import { createRustAdapter } from '../languages/rust'
import { createTypeScriptAdapter } from '../languages/typescript'
import { reactRule } from '../rules/react'
import { WASM_DIR, withBlocks } from '../testSupport'
import { pythonZhTranslator } from '../translators/pythonZh'
import { rustZhTranslator } from '../translators/rustZh'
import { typescriptZhTranslator } from '../translators/typescriptZh'
import { pageBlocks } from './pageBlocks'
const py = createPythonAdapter(WASM_DIR)
@@ -88,3 +91,16 @@ describe('链式调用卡片发给页面', () => {
expect(statement?.children[0]?.step).toEqual({ row: 1, step: 1 })
})
})
describe('react 钩子卡片发给页面', () => {
it('带着按来源分的淡底;调用树查的名字(返回的 setN)同别的下标从块第一行的行首算', async () => {
const ts = createTypeScriptAdapter(WASM_DIR)
const source = ['import { useState } from "react";', 'export function Box() {', ' const [n, setN] = useState(0);', ' return <i>{n}</i>;', '}'].join('\n')
const views = await withBlocks(ts, 'typescriptreact', source, blocks =>
toBlockViews(blocks, { source, language: ts, markers: [] }, typescriptZhTranslator, { rules: [reactRule], report: () => {} }))
const hook = pageBlocks(views, source)[1].children[0]
expect(hook.kind).toBe('react.hook')
expect(hook.tint).toEqual({ dark: '#61dafb', light: '#0a7ea4' })
expect(hook.callTree).toEqual({ name: { startIndex: ' const [n, '.length, endIndex: ' const [n, setN'.length } })
})
})
+2 -1
View File
@@ -97,9 +97,10 @@ export function pageCard(block: BlockView, base: number): PageCard {
concepts: block.concepts,
...(block.commentTarget && { commentTarget: block.commentTarget.kind }),
...(block.badge && { badge: block.badge }),
...(block.tint && { tint: block.tint }),
...(block.slot && { slot: block.slot }),
...(block.step && { step: block.step }),
...(block.callTree && { callTree: block.callTree }),
...(block.callTree && { callTree: block.callTree.name ? { ...block.callTree, name: shiftRange(block.callTree.name, base) } : block.callTree }),
}
if ('properties' in block)
return { ...card, properties: block.properties.map(row => shiftRow(row, base)) }