1- /// <reference types="@volar/typescript" />
2-
1+ import { createProxyLanguageService , decorateLanguageServiceHost } from '@volar/typescript' ;
32import { collectBindingRanges , hyphenateAttr , type Language , type SourceScript } from '@vue/language-core' ;
43import type * as ts from 'typescript' ;
54
@@ -27,21 +26,58 @@ interface ReactiveNode {
2726 callback ?: TSNode ;
2827}
2928
29+ let currentVersion = - 1 ;
30+ let currentFileName = '' ;
31+ let currentSnapshot : ts . IScriptSnapshot | undefined ;
32+ let languageService : ts . LanguageService | undefined ;
33+ let languageServiceHost : ts . LanguageServiceHost | undefined ;
34+
3035const analyzeCache = new WeakMap < ts . SourceFile , ReturnType < typeof analyze > > ( ) ;
3136
3237export function getReactiveReferences (
3338 ts : typeof import ( 'typescript' ) ,
34- language : Language ,
35- languageService : ts . LanguageService ,
36- sourceScript : SourceScript | undefined ,
37- fileName : string ,
39+ language : Language < string > ,
40+ sourceScript : SourceScript < string > ,
3841 position : number ,
3942 leadingOffset : number = 0 ,
4043) {
41- const serviceScript = sourceScript ?. generated ?. languagePlugin . typescript ?. getServiceScript (
44+ if ( currentSnapshot !== sourceScript . snapshot || currentFileName !== sourceScript . id ) {
45+ currentSnapshot = sourceScript . snapshot ;
46+ currentFileName = sourceScript . id ;
47+ currentVersion ++ ;
48+ }
49+ if ( ! languageService ) {
50+ languageServiceHost = {
51+ getProjectVersion : ( ) => currentVersion . toString ( ) ,
52+ getScriptVersion : ( ) => currentVersion . toString ( ) ,
53+ getScriptFileNames : ( ) => [ currentFileName ] ,
54+ getScriptSnapshot : fileName => fileName === currentFileName ? currentSnapshot : undefined ,
55+ getCompilationSettings : ( ) => ( { allowJs : true , allowNonTsExtensions : true } ) ,
56+ getCurrentDirectory : ( ) => '' ,
57+ getDefaultLibFileName : ( ) => '' ,
58+ readFile : ( ) => undefined ,
59+ fileExists : fileName => fileName === currentFileName ,
60+ } ;
61+ decorateLanguageServiceHost ( ts , language , languageServiceHost ) ;
62+ const proxied = createProxyLanguageService ( ts . createLanguageService ( languageServiceHost ) ) ;
63+ proxied . initialize ( language ) ;
64+ languageService = proxied . proxy ;
65+ }
66+ return getReactiveReferencesWorker ( ts , language , languageService , sourceScript , position , leadingOffset ) ;
67+ }
68+
69+ function getReactiveReferencesWorker (
70+ ts : typeof import ( 'typescript' ) ,
71+ language : Language < string > ,
72+ languageService : ts . LanguageService ,
73+ sourceScript : SourceScript < string > ,
74+ position : number ,
75+ leadingOffset : number ,
76+ ) {
77+ const serviceScript = sourceScript . generated ?. languagePlugin . typescript ?. getServiceScript (
4278 sourceScript . generated . root ,
4379 ) ;
44- const map = serviceScript ? language . maps . get ( serviceScript . code , sourceScript ! ) : undefined ;
80+ const map = serviceScript ? language . maps . get ( serviceScript . code , sourceScript ) : undefined ;
4581 const toSourceRange = map
4682 ? ( start : number , end : number ) => {
4783 for ( const [ mappedStart , mappedEnd ] of map . toSourceRange ( start - leadingOffset , end - leadingOffset , false ) ) {
@@ -57,7 +93,7 @@ export function getReactiveReferences(
5793 }
5894 } ;
5995
60- const sourceFile = languageService . getProgram ( ) ! . getSourceFile ( fileName ) ! ;
96+ const sourceFile = languageService . getProgram ( ) ! . getSourceFile ( sourceScript . id ) ! ;
6197
6298 if ( ! analyzeCache . has ( sourceFile ) ) {
6399 analyzeCache . set ( sourceFile , analyze ( ts , sourceFile , toSourceRange , toSourceNode ) ) ;
0 commit comments