@@ -16,12 +16,12 @@ import { VirtualTypeScriptContext } from "../context";
16
16
import type { TSESParseForESLintResult } from "../types" ;
17
17
import type ESTree from "estree" ;
18
18
import type { SvelteAttribute , SvelteHTMLElement } from "../../../ast" ;
19
+ import { globalsForSvelte5 , globals } from "../../../parser/globals" ;
19
20
20
21
export type AnalyzeTypeScriptContext = {
21
22
slots : Set < SvelteHTMLElement > ;
22
23
} ;
23
24
24
- const RESERVED_NAMES = new Set < string > ( [ "$$props" , "$$restProps" , "$$slots" ] ) ;
25
25
/**
26
26
* Analyze TypeScript source code.
27
27
* Generate virtual code to provide correct type information for Svelte store reference namess and scopes.
@@ -75,8 +75,8 @@ function analyzeStoreReferenceNames(
75
75
if (
76
76
// Begin with `$`.
77
77
reference . identifier . name . startsWith ( "$" ) &&
78
- // Ignore it is a reserved variable.
79
- ! RESERVED_NAMES . has ( reference . identifier . name ) &&
78
+ // Ignore globals
79
+ ! globals . includes ( reference . identifier . name ) &&
80
80
// Ignore if it is already defined.
81
81
! programScope . set . has ( reference . identifier . name )
82
82
) {
@@ -215,6 +215,59 @@ function analyzeDollarDollarVariables(
215
215
) ;
216
216
}
217
217
218
+ addSvelte5Globals ( ) ;
219
+
220
+ function addSvelte5Globals ( ) {
221
+ for ( const svelte5Global of globalsForSvelte5 ) {
222
+ if (
223
+ ! scopeManager . globalScope ! . through . some (
224
+ ( reference ) => reference . identifier . name === svelte5Global ,
225
+ )
226
+ ) {
227
+ continue ;
228
+ }
229
+ switch ( svelte5Global ) {
230
+ case "$state" : {
231
+ appendDeclareFunctionVirtualScript (
232
+ svelte5Global ,
233
+ "<T>(initial: T): T" ,
234
+ ) ;
235
+ appendDeclareFunctionVirtualScript (
236
+ svelte5Global ,
237
+ "<T>(): T | undefined" ,
238
+ ) ;
239
+ break ;
240
+ }
241
+ case "$derived" : {
242
+ appendDeclareFunctionVirtualScript (
243
+ svelte5Global ,
244
+ "<T>(expression: T): T" ,
245
+ ) ;
246
+ break ;
247
+ }
248
+ case "$effect" : {
249
+ appendDeclareFunctionVirtualScript (
250
+ svelte5Global ,
251
+ "(fn: () => void | (() => void)): void" ,
252
+ ) ;
253
+ appendDeclareNamespaceVirtualScript (
254
+ svelte5Global ,
255
+ "export function pre(fn: () => void | (() => void)): void;" ,
256
+ ) ;
257
+ break ;
258
+ }
259
+ case "$props" : {
260
+ appendDeclareFunctionVirtualScript ( svelte5Global , "<T>(): T" ) ;
261
+ break ;
262
+ }
263
+ default : {
264
+ const _ : never = svelte5Global ;
265
+ throw Error ( `Unknown global: ${ _ } ` ) ;
266
+ }
267
+ }
268
+ }
269
+ }
270
+
218
271
/** Append declare virtual script */
219
272
function appendDeclareVirtualScript ( name : string , type : string ) {
220
273
ctx . appendVirtualScript ( `declare let ${ name } : ${ type } ;` ) ;
@@ -242,6 +295,59 @@ function analyzeDollarDollarVariables(
242
295
return true ;
243
296
} ) ;
244
297
}
298
+
299
+ /** Append declare virtual script */
300
+ function appendDeclareFunctionVirtualScript ( name : string , type : string ) {
301
+ ctx . appendVirtualScript ( `declare function ${ name } ${ type } ;` ) ;
302
+ ctx . restoreContext . addRestoreStatementProcess ( ( node , result ) => {
303
+ if (
304
+ node . type !== "TSDeclareFunction" ||
305
+ ! node . declare ||
306
+ node . id ?. type !== "Identifier" ||
307
+ node . id . name !== name
308
+ ) {
309
+ return false ;
310
+ }
311
+ const program = result . ast ;
312
+ program . body . splice ( program . body . indexOf ( node ) , 1 ) ;
313
+
314
+ const scopeManager = result . scopeManager as ScopeManager ;
315
+
316
+ // Remove `declare` variable
317
+ removeAllScopeAndVariableAndReference ( node , {
318
+ visitorKeys : result . visitorKeys ,
319
+ scopeManager,
320
+ } ) ;
321
+
322
+ return true ;
323
+ } ) ;
324
+ }
325
+
326
+ function appendDeclareNamespaceVirtualScript ( name : string , script : string ) {
327
+ ctx . appendVirtualScript ( `declare namespace $effect { ${ script } }` ) ;
328
+ ctx . restoreContext . addRestoreStatementProcess ( ( node , result ) => {
329
+ if (
330
+ node . type !== "TSModuleDeclaration" ||
331
+ ! node . declare ||
332
+ node . id ?. type !== "Identifier" ||
333
+ node . id . name !== name
334
+ ) {
335
+ return false ;
336
+ }
337
+ const program = result . ast ;
338
+ program . body . splice ( program . body . indexOf ( node ) , 1 ) ;
339
+
340
+ const scopeManager = result . scopeManager as ScopeManager ;
341
+
342
+ // Remove `declare` variable
343
+ removeAllScopeAndVariableAndReference ( node , {
344
+ visitorKeys : result . visitorKeys ,
345
+ scopeManager,
346
+ } ) ;
347
+
348
+ return true ;
349
+ } ) ;
350
+ }
245
351
}
246
352
247
353
/**
0 commit comments