🐛 fix(vscode): 注释里不带路径的引用从被注释的声明起一层层往外找,同类的方法、类的成员都能链到

This commit is contained in:
cruldra committed 2026-10-12 16:56:31 +11:00
1 parent 15972c0b35
commit 5120e50228
15 files changed
+450 -167

No files matched your search

@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'
import { RepoLinks } from './repoLink'
import { commentLinkOf, RepoLinks } from './repoLink'
import { onMessage, postMessage } from './vscode'
/** 坏链接悬停上的字,走页面上统一的 data-tooltip,不用原生 title。 */
@@ -32,12 +32,13 @@ function paintLink(anchor: HTMLAnchorElement, broken: boolean): void {
function paint(links: RepoLinks): void {
for (const anchor of document.querySelectorAll<HTMLAnchorElement>('.cr-markdown a'))
paintLink(anchor, links.isBroken(anchor.getAttribute('href') ?? ''))
paintLink(anchor, links.isBroken(commentLinkOf(anchor)))
}
/**
* 注释、说明、问 AI 的回答里的仓库路径链接,和注释里不带路径的引用:点了发给扩展端打开(不走 webview 把 http 链接交给外部打开的那条),
* 画出来之后把路径、引用发去问哪些文件没有、哪些引用找不到;文档换了版本再问一次(引用跟着源码变)。
* 不带路径的引用都带着它写在哪块(见 commentLinkOf),扩展端从那块的声明起找。
*/
export function useRepoLinks(): void {
const [links] = useState(() => new RepoLinks(postMessage))
@@ -47,10 +48,10 @@ export function useRepoLinks(): void {
const scan = (): void => {
window.clearTimeout(timer)
timer = window.setTimeout(() => {
const anchors = [...document.querySelectorAll<HTMLAnchorElement>('.cr-markdown a')]
for (const anchor of anchors)
paintLink(anchor, links.isBroken(anchor.getAttribute('href') ?? ''))
links.scan(anchors.map(anchor => anchor.getAttribute('href') ?? ''))
const found = [...document.querySelectorAll<HTMLAnchorElement>('.cr-markdown a')].map(anchor => ({ anchor, link: commentLinkOf(anchor) }))
for (const { anchor, link } of found)
paintLink(anchor, links.isBroken(link))
links.scan(found.flatMap(({ link }) => link ?? []))
}, 50)
}
const off = onMessage((msg) => {
@@ -65,19 +66,19 @@ export function useRepoLinks(): void {
return
}
if (msg.type === 'repoLinkBroken') {
links.broken(msg.path, msg.symbol)
links.broken(msg)
paint(links)
return
}
if (msg.type === 'repoLinkOpened') {
links.opened(msg.path, msg.symbol)
links.opened(msg)
paint(links)
}
})
// 捕获阶段:赶在 webview 把 <a> 交给外部打开之前拦下仓库链接
const onClick = (event: MouseEvent): void => {
const anchor = event.target instanceof Element ? event.target.closest('a') : null
if (!anchor || !links.click(anchor.getAttribute('href')))
if (!anchor || !links.click(commentLinkOf(anchor)))
return
event.preventDefault()
event.stopPropagation()