From afbadbede9a30811de9c3d0aa020c848312eb1df Mon Sep 17 00:00:00 2001 From: Triumph-light <2495685883@qq.com> Date: Mon, 15 Jun 2026 20:49:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=A8=A1=E7=89=88?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E7=9A=84=E5=8F=B3=E9=94=AE=E6=9F=A5=E7=9C=8B?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E7=9A=84=E8=B7=B3=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/plugins/mpx-sfc-template-links.ts | 221 ++++++++++++++---- 1 file changed, 174 insertions(+), 47 deletions(-) diff --git a/packages/language-service/src/plugins/mpx-sfc-template-links.ts b/packages/language-service/src/plugins/mpx-sfc-template-links.ts index b4bf627..4c7e95e 100644 --- a/packages/language-service/src/plugins/mpx-sfc-template-links.ts +++ b/packages/language-service/src/plugins/mpx-sfc-template-links.ts @@ -1,7 +1,14 @@ import type * as vscode from 'vscode-languageserver-protocol' -import type { LanguageServicePlugin } from '@volar/language-service' +import type { + LanguageServiceContext, + LanguageServicePlugin, +} from '@volar/language-service' import { URI } from 'vscode-uri' -import { MpxVirtualCode, Sfc, tsCodegen } from '@mpxjs/language-core' +import { + MpxVirtualCode, + SfcJsonBlockUsingComponents, + tsCodegen, +} from '@mpxjs/language-core' import { isMpPluginComponentPath } from '../utils' export function create(): LanguageServicePlugin { @@ -10,27 +17,23 @@ export function create(): LanguageServicePlugin { capabilities: { documentLinkProvider: {}, + definitionProvider: true, }, create(context) { return { async provideDocumentLinks(document) { - const uri = URI.parse(document.uri) - const decoded = context.decodeEmbeddedDocumentUri(uri) - if (!decoded) { - return - } - const [documentUri, embeddedCodeId] = decoded - const sourceScript = context.language.scripts.get(documentUri) - const virtualCode = - sourceScript?.generated?.embeddedCodes.get(embeddedCodeId) - if (!sourceScript?.generated || virtualCode?.id !== 'template') { - return - } - const root = sourceScript.generated.root - if (!(root instanceof MpxVirtualCode)) { + const tplCtx = await resolveTemplateContext(context, document.uri) + if (!tplCtx) { return } + const { + decoded, + sourceScript, + root, + templateNodeTags, + usingComponents, + } = tplCtx const result: vscode.DocumentLink[] = [] const { sfc } = root @@ -43,7 +46,7 @@ export function create(): LanguageServicePlugin { string, { index: number - style: Sfc['styles'][number] + style: (typeof sfc.styles)[number] classOffset: number }[] >() @@ -71,11 +74,11 @@ export function create(): LanguageServicePlugin { if (styles) { for (const style of styles) { const styleDocumentUri = context.encodeEmbeddedDocumentUri( - decoded![0], + decoded[0], 'style_' + style.index, ) const styleVirtualCode = - sourceScript.generated.embeddedCodes.get( + sourceScript.generated!.embeddedCodes.get( 'style_' + style.index, ) if (!styleVirtualCode) { @@ -97,7 +100,7 @@ export function create(): LanguageServicePlugin { }, target: context.encodeEmbeddedDocumentUri( - decoded![0], + decoded[0], 'style_' + style.index, ) + `#L${start.line + 1},${start.character + 1}-L${end.line + 1},${end.character + 1}`, @@ -108,10 +111,6 @@ export function create(): LanguageServicePlugin { // #endregion // #region document link for component tag - const templateNodeTags = - codegen?.getGeneratedTemplate()?.templateNodeTags ?? [] - const { result: usingComponents } = - (await sfc.json?.resolvedUsingComponents) || {} if (usingComponents?.size) { for (const nodeTag of templateNodeTags) { const { @@ -122,29 +121,9 @@ export function create(): LanguageServicePlugin { if (!usingComponents.has(componentTag) || !startTagOffset) { continue } - const rawComponentPaths = usingComponents.get(componentTag)! - - // 根据 text 字段去重,创建一个映射表保存唯一的路径 - const uniqueComponentMap = new Map< - string, - { - componentPath: string - targetFilePath: string - id: number - } - >() - - let _index = 1 - rawComponentPaths.forEach(path => { - if (!uniqueComponentMap.has(path.text) && path.realFilename) { - uniqueComponentMap.set(path.text, { - componentPath: path.text, - targetFilePath: path.realFilename, - id: _index++, - }) - } - }) - + const uniqueComponentMap = dedupeComponentPaths( + usingComponents.get(componentTag)!, + ) const uniqueComponentCount = uniqueComponentMap.size for (const [ @@ -181,7 +160,155 @@ export function create(): LanguageServicePlugin { return result }, + + /** + * 在