@@ -3,6 +3,7 @@ import fs from 'fs';
33import path from 'path' ;
44import { getPackageJsons } from './get-package-json.js' ;
55import { getFilename , getSourceCode } from './compat.js' ;
6+ import { createCache } from './cache.js' ;
67
78const isRunInBrowser = ! fs . readFileSync ;
89
@@ -96,23 +97,51 @@ function getSvelteKitFileTypeFromFilePath(filePath: string): SvelteContext['svel
9697 }
9798}
9899
100+ function extractMajorVersion ( version : string , recognizePrereleaseVersion : boolean ) : string | null {
101+ if ( recognizePrereleaseVersion ) {
102+ const match = / ^ (?: \^ | ~ ) ? ( \d + \. 0 \. 0 - n e x t ) / . exec ( version ) ;
103+ if ( match && match [ 1 ] ) {
104+ return match [ 1 ] ;
105+ }
106+ }
107+
108+ const match = / ^ (?: \^ | ~ ) ? ( \d + ) \. / . exec ( version ) ;
109+ if ( match && match [ 1 ] ) {
110+ return match [ 1 ] ;
111+ }
112+ return null ;
113+ }
114+
115+ const svelteKitContextCache = createCache < Pick <
116+ SvelteContext ,
117+ 'svelteKitFileType' | 'svelteKitVersion'
118+ > | null > ( ) ;
119+
99120function getSvelteKitContext (
100121 context : RuleContext
101122) : Pick < SvelteContext , 'svelteKitFileType' | 'svelteKitVersion' > {
102123 const filePath = getFilename ( context ) ;
124+
125+ const cached = svelteKitContextCache . get ( filePath ) ;
126+ if ( cached ) return cached ;
127+
103128 const svelteKitVersion = getSvelteKitVersion ( filePath ) ;
104129 if ( svelteKitVersion == null ) {
105- return {
130+ const result : Pick < SvelteContext , 'svelteKitFileType' | 'svelteKitVersion' > = {
106131 svelteKitFileType : null ,
107132 svelteKitVersion : null
108133 } ;
134+ svelteKitContextCache . set ( filePath , result ) ;
135+ return result ;
109136 }
110137 if ( isRunInBrowser ) {
111- return {
138+ const result : Pick < SvelteContext , 'svelteKitFileType' | 'svelteKitVersion' > = {
112139 svelteKitVersion,
113140 // Judge by only file path if it runs in browser.
114141 svelteKitFileType : getSvelteKitFileTypeFromFilePath ( filePath )
115142 } ;
143+ svelteKitContextCache . set ( filePath , result ) ;
144+ return result ;
116145 }
117146
118147 const routes =
@@ -123,21 +152,34 @@ function getSvelteKitContext(
123152 const projectRootDir = getProjectRootDir ( getFilename ( context ) ) ?? '' ;
124153
125154 if ( ! filePath . startsWith ( path . join ( projectRootDir , routes ) ) ) {
126- return {
155+ const result : Pick < SvelteContext , 'svelteKitFileType' | 'svelteKitVersion' > = {
127156 svelteKitVersion,
128157 svelteKitFileType : null
129158 } ;
159+ svelteKitContextCache . set ( filePath , result ) ;
160+ return result ;
130161 }
131162
132- return {
163+ const result : Pick < SvelteContext , 'svelteKitFileType' | 'svelteKitVersion' > = {
133164 svelteKitVersion,
134165 svelteKitFileType : getSvelteKitFileTypeFromFilePath ( filePath )
135166 } ;
167+ svelteKitContextCache . set ( filePath , result ) ;
168+ return result ;
136169}
137170
138- function getSvelteVersion ( filePath : string ) : SvelteContext [ 'svelteVersion' ] {
171+ const svelteVersionCache = createCache < SvelteContext [ 'svelteVersion' ] > ( ) ;
172+
173+ export function getSvelteVersion ( filePath : string ) : SvelteContext [ 'svelteVersion' ] {
174+ const cached = svelteVersionCache . get ( filePath ) ;
175+ if ( cached ) return cached ;
176+
139177 // Hack: if it runs in browser, it regards as Svelte project.
140- if ( isRunInBrowser ) return '5' ;
178+ if ( isRunInBrowser ) {
179+ svelteVersionCache . set ( filePath , '5' ) ;
180+ return '5' ;
181+ }
182+
141183 try {
142184 const packageJsons = getPackageJsons ( filePath ) ;
143185 for ( const packageJson of packageJsons ) {
@@ -147,17 +189,22 @@ function getSvelteVersion(filePath: string): SvelteContext['svelteVersion'] {
147189 }
148190 const major = extractMajorVersion ( version , false ) ;
149191 if ( major === '3' || major === '4' ) {
192+ svelteVersionCache . set ( filePath , '3/4' ) ;
150193 return '3/4' ;
151194 }
195+ svelteVersionCache . set ( filePath , major as SvelteContext [ 'svelteVersion' ] ) ;
152196 return major as SvelteContext [ 'svelteVersion' ] ;
153197 }
154198 } catch {
155199 /** do nothing */
156200 }
157201
202+ svelteVersionCache . set ( filePath , null ) ;
158203 return null ;
159204}
160205
206+ const svelteKitVersionCache = createCache < SvelteContext [ 'svelteKitVersion' ] > ( ) ;
207+
161208/**
162209 * Check givin file is under SvelteKit project.
163210 *
@@ -167,14 +214,22 @@ function getSvelteVersion(filePath: string): SvelteContext['svelteVersion'] {
167214 * @returns
168215 */
169216function getSvelteKitVersion ( filePath : string ) : SvelteContext [ 'svelteKitVersion' ] {
217+ const cached = svelteKitVersionCache . get ( filePath ) ;
218+ if ( cached ) return cached ;
219+
170220 // Hack: if it runs in browser, it regards as SvelteKit project.
171- if ( isRunInBrowser ) return '2' ;
221+ if ( isRunInBrowser ) {
222+ svelteKitVersionCache . set ( filePath , '2' ) ;
223+ return '2' ;
224+ }
225+
172226 try {
173227 const packageJsons = getPackageJsons ( filePath ) ;
174228 if ( packageJsons . length === 0 ) return null ;
175229 if ( packageJsons [ 0 ] . name === 'eslint-plugin-svelte' ) {
176230 // Hack: CI removes `@sveltejs/kit` and it returns false and test failed.
177231 // So always it returns 2 if it runs on the package.
232+ svelteKitVersionCache . set ( filePath , '2' ) ;
178233 return '2' ;
179234 }
180235
@@ -183,32 +238,22 @@ function getSvelteKitVersion(filePath: string): SvelteContext['svelteKitVersion'
183238 packageJson . dependencies ?. [ '@sveltejs/kit' ] ??
184239 packageJson . devDependencies ?. [ '@sveltejs/kit' ] ;
185240 if ( typeof version !== 'string' ) {
241+ svelteKitVersionCache . set ( filePath , null ) ;
186242 return null ;
187243 }
188-
189- return extractMajorVersion ( version , true ) as SvelteContext [ 'svelteKitVersion' ] ;
244+ const major = extractMajorVersion ( version , true ) as SvelteContext [ 'svelteKitVersion' ] ;
245+ svelteKitVersionCache . set ( filePath , major ) ;
246+ return major ;
190247 }
191248 } catch {
192249 /** do nothing */
193250 }
194251
252+ svelteKitVersionCache . set ( filePath , null ) ;
195253 return null ;
196254}
197255
198- function extractMajorVersion ( version : string , recognizePrereleaseVersion : boolean ) : string | null {
199- if ( recognizePrereleaseVersion ) {
200- const match = / ^ (?: \^ | ~ ) ? ( \d + \. 0 \. 0 - n e x t ) / . exec ( version ) ;
201- if ( match && match [ 1 ] ) {
202- return match [ 1 ] ;
203- }
204- }
205-
206- const match = / ^ (?: \^ | ~ ) ? ( \d + ) \. / . exec ( version ) ;
207- if ( match && match [ 1 ] ) {
208- return match [ 1 ] ;
209- }
210- return null ;
211- }
256+ const projectRootDirCache = createCache < string | null > ( ) ;
212257
213258/**
214259 * Gets a project root folder path.
@@ -217,58 +262,81 @@ function extractMajorVersion(version: string, recognizePrereleaseVersion: boolea
217262 */
218263function getProjectRootDir ( filePath : string ) : string | null {
219264 if ( isRunInBrowser ) return null ;
265+ const cached = projectRootDirCache . get ( filePath ) ;
266+ if ( cached ) return cached ;
267+
220268 const packageJsons = getPackageJsons ( filePath ) ;
221269 if ( packageJsons . length === 0 ) {
270+ projectRootDirCache . set ( filePath , null ) ;
222271 return null ;
223272 }
224273 const packageJsonFilePath = packageJsons [ 0 ] . filePath ;
225- if ( ! packageJsonFilePath ) return null ;
226- return path . dirname ( path . resolve ( packageJsonFilePath ) ) ;
274+ if ( ! packageJsonFilePath ) {
275+ projectRootDirCache . set ( filePath , null ) ;
276+ return null ;
277+ }
278+ const projectRootDir = path . dirname ( path . resolve ( packageJsonFilePath ) ) ;
279+ projectRootDirCache . set ( filePath , projectRootDir ) ;
280+ return projectRootDir ;
227281}
228282
283+ const svelteContextCache = createCache < SvelteContext | null > ( ) ;
284+
229285export function getSvelteContext ( context : RuleContext ) : SvelteContext | null {
230286 const { parserServices } = getSourceCode ( context ) ;
231287 const { svelteParseContext } = parserServices ;
232288 const filePath = getFilename ( context ) ;
289+
290+ const cached = svelteContextCache . get ( filePath ) ;
291+ if ( cached ) return cached ;
292+
233293 const svelteKitContext = getSvelteKitContext ( context ) ;
234294 const svelteVersion = getSvelteVersion ( filePath ) ;
235295 const svelteFileType = getSvelteFileType ( filePath ) ;
236296
237297 if ( svelteVersion == null ) {
238- return {
298+ const result : SvelteContext = {
239299 svelteVersion : null ,
240300 svelteFileType : null ,
241301 runes : null ,
242302 svelteKitVersion : svelteKitContext . svelteKitVersion ,
243303 svelteKitFileType : svelteKitContext . svelteKitFileType
244304 } ;
305+ svelteContextCache . set ( filePath , result ) ;
306+ return result ;
245307 }
246308
247309 if ( svelteVersion === '3/4' ) {
248- return {
310+ const result : SvelteContext = {
249311 svelteVersion,
250312 svelteFileType : svelteFileType === '.svelte' ? '.svelte' : null ,
251313 runes : null ,
252314 svelteKitVersion : svelteKitContext . svelteKitVersion ,
253315 svelteKitFileType : svelteKitContext . svelteKitFileType
254316 } ;
317+ svelteContextCache . set ( filePath , result ) ;
318+ return result ;
255319 }
256320
257321 if ( svelteFileType == null ) {
258- return {
322+ const result : SvelteContext = {
259323 svelteVersion,
260324 svelteFileType : null ,
261325 runes : null ,
262326 svelteKitVersion : svelteKitContext . svelteKitVersion ,
263327 svelteKitFileType : svelteKitContext . svelteKitFileType
264328 } ;
329+ svelteContextCache . set ( filePath , result ) ;
330+ return result ;
265331 }
266332
267- return {
333+ const result : SvelteContext = {
268334 svelteVersion,
269335 runes : svelteParseContext ?. runes ?? 'undetermined' ,
270336 svelteFileType,
271337 svelteKitVersion : svelteKitContext . svelteKitVersion ,
272338 svelteKitFileType : svelteKitContext . svelteKitFileType
273339 } ;
340+ svelteContextCache . set ( filePath , result ) ;
341+ return result ;
274342}
0 commit comments