@@ -13,7 +13,7 @@ import {
1313 tsCodegen ,
1414 type VueVirtualCode ,
1515} from '@vue/language-core' ;
16- import { camelize , capitalize , isPromise } from '@vue/shared' ;
16+ import { camelize , capitalize } from '@vue/shared' ;
1717import type { ComponentPropInfo } from '@vue/typescript-plugin/lib/requests/getComponentProps' ;
1818import { create as createHtmlService , resolveReference } from 'volar-service-html' ;
1919import { create as createPugService } from 'volar-service-pug' ;
@@ -22,7 +22,7 @@ import { URI, Utils } from 'vscode-uri';
2222import { loadModelModifiersData , loadTemplateData } from '../data' ;
2323import { format } from '../htmlFormatter' ;
2424import { AttrNameCasing , getAttrNameCasing , getTagNameCasing , TagNameCasing } from '../nameCasing' ;
25- import { createReferenceResolver , resolveEmbeddedCode } from '../utils' ;
25+ import { resolveEmbeddedCode } from '../utils' ;
2626
2727const specialTags = new Set ( [
2828 'slot' ,
@@ -64,6 +64,9 @@ export function create(
6464) : LanguageServicePlugin {
6565 let customData : html . IHTMLDataProvider [ ] = [ ] ;
6666 let extraCustomData : html . IHTMLDataProvider [ ] = [ ] ;
67+ let modulePathCache :
68+ | Map < string , Promise < string | null | undefined > | string | null | undefined >
69+ | undefined ;
6770
6871 const onDidChangeCustomDataListeners = new Set < ( ) => void > ( ) ;
6972 const onDidChangeCustomData = ( listener : ( ) => void ) : Disposable => {
@@ -90,7 +93,37 @@ export function create(
9093 useDefaultDataProvider : false ,
9194 getDocumentContext ( context ) {
9295 return {
93- resolveReference : createReferenceResolver ( context , resolveReference , resolveModuleName ) as any ,
96+ resolveReference ( ref , base ) {
97+ let baseUri = URI . parse ( base ) ;
98+ const decoded = context . decodeEmbeddedDocumentUri ( baseUri ) ;
99+ if ( decoded ) {
100+ baseUri = decoded [ 0 ] ;
101+ }
102+ if (
103+ modulePathCache
104+ && baseUri . scheme === 'file'
105+ && ! ref . startsWith ( './' )
106+ && ! ref . startsWith ( '../' )
107+ ) {
108+ const map = modulePathCache ;
109+ if ( ! map . has ( ref ) ) {
110+ const fileName = baseUri . fsPath . replace ( / \\ / g, '/' ) ;
111+ const promise = resolveModuleName ( fileName , ref ) ;
112+ map . set ( ref , promise ) ;
113+ if ( promise instanceof Promise ) {
114+ promise . then ( res => map . set ( ref , res ) ) ;
115+ }
116+ }
117+ const cached = modulePathCache . get ( ref ) ;
118+ if ( cached instanceof Promise ) {
119+ throw cached ;
120+ }
121+ if ( cached ) {
122+ return cached ;
123+ }
124+ }
125+ return resolveReference ( ref , baseUri , context . env . workspaceFolders ) ;
126+ } ,
94127 } ;
95128 } ,
96129 getCustomData ( ) {
@@ -418,22 +451,22 @@ export function create(
418451 } ,
419452
420453 async provideDocumentLinks ( document , token ) {
421- if ( document . languageId !== languageId ) {
422- return ;
423- }
424- const info = resolveEmbeddedCode ( context , document . uri ) ;
425- if ( info ?. code . id !== 'template' ) {
426- return ;
427- }
428-
429- const documentLinks = await baseServiceInstance . provideDocumentLinks ?.( document , token ) ?? [ ] ;
430- for ( const link of documentLinks ) {
431- if ( link . target && isPromise ( link . target ) ) {
432- link . target = await link . target ;
454+ modulePathCache = new Map ( ) ;
455+ while ( true ) {
456+ try {
457+ const result = await baseServiceInstance . provideDocumentLinks ?.( document , token ) ;
458+ modulePathCache = undefined ;
459+ return result ;
460+ }
461+ catch ( e ) {
462+ if ( e instanceof Promise ) {
463+ await e ;
464+ }
465+ else {
466+ throw e ;
467+ }
433468 }
434469 }
435-
436- return documentLinks ;
437470 } ,
438471 } ;
439472
0 commit comments