🐛 fix(vscode): 切走标签再回来,调用树棵数不用重算,开着的弹框和选中的入口照旧
This commit is contained in:
1 parent
6cf053dcd0
commit
32018e71f1
9 files changed
+542
-110
No files matched your search
@@ -43,6 +43,28 @@ function savedBlockModes(): BlockModes {
|
||||
return { editing, folds }
|
||||
}
|
||||
|
||||
/** 开着的调用树弹框:哪一版文档的哪一块、选中第几个入口,扩展端发来的树 */
|
||||
interface OpenCall {
|
||||
anchor: string
|
||||
version: number
|
||||
entry: number
|
||||
status: 'loading' | 'ready'
|
||||
name: string
|
||||
where: string
|
||||
kind: string
|
||||
badge?: KindBadge
|
||||
trees: CallTree[]
|
||||
contractMiss?: ContractMiss
|
||||
}
|
||||
|
||||
/** 打开 doc 里 anchor 那块的调用树弹框,先是「正在查」,等扩展端发树来;这块不在了、或者它看不了调用树时是 undefined。 */
|
||||
function openingCall(doc: DocumentMessage, anchor: string, entry: number): OpenCall | undefined {
|
||||
const block = blockAt(doc.blocks, anchor)
|
||||
if (!block?.callTree)
|
||||
return undefined
|
||||
return { anchor, version: doc.version, entry, status: 'loading', name: '', where: '', kind: block.kind, ...(block.badge && { badge: block.badge }), trees: [] }
|
||||
}
|
||||
|
||||
function blockAt(blocks: readonly BlockView[], anchor: string): BlockView | undefined {
|
||||
for (const block of blocks) {
|
||||
if (block.anchor === anchor)
|
||||
@@ -79,17 +101,9 @@ export function App(): ReactElement | null {
|
||||
/** 页面上这份文档的版本:调用树的回答不是这一版就丢掉 */
|
||||
const docVersion = useRef<number | undefined>(undefined)
|
||||
const [callCounts, setCallCounts] = useState<{ version: number, counts: Record<string, number> }>()
|
||||
const [openCall, setOpenCall] = useState<{
|
||||
anchor: string
|
||||
version: number
|
||||
status: 'loading' | 'ready'
|
||||
name: string
|
||||
where: string
|
||||
kind: string
|
||||
badge?: KindBadge
|
||||
trees: CallTree[]
|
||||
contractMiss?: ContractMiss
|
||||
} | null>(null)
|
||||
const [openCall, setOpenCall] = useState<OpenCall | null>(null)
|
||||
/** 页面重新加载前开着的调用树弹框:第一份文档到了,那块还在就重新打开;到之前记着的不动 */
|
||||
const restoreCall = useRef(viewState.get().callTree)
|
||||
/** 块树所在的页面内容:钉住卡片时在这里面量 */
|
||||
const content = useRef<HTMLDivElement>(null)
|
||||
// 解析失败的文档没有块,不标差异;删掉的块按块筛选同样藏
|
||||
@@ -138,16 +152,24 @@ export function App(): ReactElement | null {
|
||||
useEffect(() => {
|
||||
const off = onMessage((msg) => {
|
||||
switch (msg.type) {
|
||||
case 'document':
|
||||
case 'document': {
|
||||
const restoring = restoreCall.current
|
||||
restoreCall.current = undefined
|
||||
const reopened = restoring && openingCall(msg, restoring.anchor, restoring.entry)
|
||||
docVersion.current = msg.version
|
||||
setDoc(msg)
|
||||
setNames(documentNames(msg.version, msg.names))
|
||||
setKeep(prev => keptWhileEditing(prev, editing.current))
|
||||
setCallCounts(prev => prev?.version === msg.version ? prev : undefined)
|
||||
setOpenCall(prev => prev?.version === msg.version ? prev : null)
|
||||
setOpenCall(prev => prev?.version === msg.version ? prev : reopened ?? null)
|
||||
if (reopened)
|
||||
postMessage({ type: 'openCallTree', version: msg.version, anchor: reopened.anchor })
|
||||
else if (restoring)
|
||||
viewState.update({ callTree: undefined })
|
||||
if (msg.reveal)
|
||||
setReveal(msg.reveal)
|
||||
return
|
||||
}
|
||||
case 'callTreeCounts':
|
||||
if (msg.version !== docVersion.current)
|
||||
return
|
||||
@@ -195,13 +217,19 @@ export function App(): ReactElement | null {
|
||||
editing.current = view.editing
|
||||
}, [view])
|
||||
|
||||
useEffect(() => {
|
||||
if (restoreCall.current)
|
||||
return
|
||||
viewState.update({ callTree: openCall ? { anchor: openCall.anchor, entry: openCall.entry } : undefined })
|
||||
}, [openCall])
|
||||
|
||||
const onFocused = useCallback(() => setFocusId(null), [])
|
||||
const onOpenCall = useCallback((anchor: string) => {
|
||||
if (!doc)
|
||||
const opening = doc && openingCall(doc, anchor, 0)
|
||||
if (!opening)
|
||||
return
|
||||
const block = blockAt(doc.blocks, anchor)
|
||||
setOpenCall({ anchor, version: doc.version, status: 'loading', name: '', where: '', kind: block?.kind ?? 'function', ...(block?.badge && { badge: block.badge }), trees: [] })
|
||||
postMessage({ type: 'openCallTree', version: doc.version, anchor })
|
||||
setOpenCall(opening)
|
||||
postMessage({ type: 'openCallTree', version: opening.version, anchor })
|
||||
}, [doc])
|
||||
const kindNames = useMemo(() => new Map(doc?.attributes.find(attribute => attribute.id === 'kind')?.values.map(value => [value.id, value.name])), [doc])
|
||||
const kindName = useCallback((kind: string) => kindNames.get(kind) ?? kind, [kindNames])
|
||||
@@ -315,7 +343,9 @@ export function App(): ReactElement | null {
|
||||
where={openCall.where}
|
||||
status={openCall.status === 'loading' ? 'loading' : openCall.trees.length === 0 ? 'empty' : 'ready'}
|
||||
trees={openCall.trees}
|
||||
selected={openCall.entry}
|
||||
contractMiss={openCall.contractMiss}
|
||||
onSelect={entry => setOpenCall(prev => prev && { ...prev, entry })}
|
||||
onClose={() => setOpenCall(null)}
|
||||
onJump={(jump) => {
|
||||
setOpenCall(null)
|
||||
|
||||
Reference in new issue
Block a user