@@ -75,12 +75,18 @@ export function activateExtension(context: vscode.ExtensionContext, magentoRoot:
7575 const reportPath = path . join ( magentoRoot , 'var' , 'report' ) ;
7676
7777 const logWatcher = vscode . workspace . createFileSystemWatcher ( new vscode . RelativePattern ( logPath , '*' ) ) ;
78- logWatcher . onDidChange ( ( ) => logViewerProvider . refresh ( ) ) ;
78+ logWatcher . onDidChange ( ( uri ) => {
79+ invalidateFileCache ( uri . fsPath ) ;
80+ logViewerProvider . refresh ( ) ;
81+ } ) ;
7982 logWatcher . onDidCreate ( ( ) => logViewerProvider . refresh ( ) ) ;
8083 logWatcher . onDidDelete ( ( ) => logViewerProvider . refresh ( ) ) ;
8184
8285 const reportWatcher = vscode . workspace . createFileSystemWatcher ( new vscode . RelativePattern ( reportPath , '*' ) ) ;
83- reportWatcher . onDidChange ( ( ) => reportViewerProvider . refresh ( ) ) ;
86+ reportWatcher . onDidChange ( ( uri ) => {
87+ invalidateFileCache ( uri . fsPath ) ;
88+ reportViewerProvider . refresh ( ) ;
89+ } ) ;
8490 reportWatcher . onDidCreate ( ( ) => reportViewerProvider . refresh ( ) ) ;
8591 reportWatcher . onDidDelete ( ( ) => reportViewerProvider . refresh ( ) ) ;
8692
@@ -181,23 +187,6 @@ export function deleteReportFile(filePath: string): void {
181187 }
182188}
183189
184- // Clears all report files in the Magento report directory.
185- export function clearAllReportFiles ( reportViewerProvider : ReportViewerProvider , magentoRoot : string ) : void {
186- vscode . window . showWarningMessage ( 'Are you sure you want to delete all report files?' , 'Yes' , 'No' ) . then ( selection => {
187- if ( selection === 'Yes' ) {
188- const reportPath = path . join ( magentoRoot , 'var' , 'report' ) ;
189- if ( pathExists ( reportPath ) ) {
190- const files = fs . readdirSync ( reportPath ) ;
191- files . forEach ( file => fs . unlinkSync ( path . join ( reportPath , file ) ) ) ;
192- reportViewerProvider . refresh ( ) ;
193- showInformationMessage ( 'All report files have been cleared.' ) ;
194- } else {
195- showInformationMessage ( 'No report files found to clear.' ) ;
196- }
197- }
198- } ) ;
199- }
200-
201190// Cache for badge updates
202191let lastUpdateTime = 0 ;
203192const BADGE_UPDATE_THROTTLE = 1000 ; // Maximum one update per second
@@ -363,8 +352,12 @@ export function getLineCount(filePath: string): number {
363352
364353 return estimatedLines ;
365354 } else {
366- // For smaller files, we read them completely
367- const fileContent = fs . readFileSync ( filePath , 'utf-8' ) ;
355+ // For smaller files, use cached content
356+ const fileContent = getCachedFileContent ( filePath ) ;
357+ if ( ! fileContent ) {
358+ return 0 ;
359+ }
360+
368361 const lineCount = fileContent . split ( '\n' ) . length ;
369362
370363 lineCountCache . set ( filePath , {
@@ -430,6 +423,11 @@ export function getLogItems(dir: string, parseTitle: (filePath: string) => strin
430423// Cache for JSON reports to avoid repeated parsing
431424const reportCache = new Map < string , { content : unknown , timestamp : number } > ( ) ;
432425
426+ // Cache for file contents to avoid repeated reads
427+ const fileContentCache = new Map < string , { content : string , timestamp : number } > ( ) ;
428+ const FILE_CACHE_MAX_SIZE = 50 ; // Maximum number of files to cache
429+ const FILE_CACHE_MAX_FILE_SIZE = 5 * 1024 * 1024 ; // 5MB max file size for caching
430+
433431// Helper function for reading and parsing JSON reports with caching
434432function getReportContent ( filePath : string ) : unknown | null {
435433 try {
@@ -440,7 +438,11 @@ function getReportContent(filePath: string): unknown | null {
440438 return cachedReport . content ;
441439 }
442440
443- const fileContent = fs . readFileSync ( filePath , 'utf-8' ) ;
441+ const fileContent = getCachedFileContent ( filePath ) ;
442+ if ( ! fileContent ) {
443+ return null ;
444+ }
445+
444446 const report = JSON . parse ( fileContent ) ;
445447
446448 reportCache . set ( filePath , {
@@ -454,6 +456,64 @@ function getReportContent(filePath: string): unknown | null {
454456 }
455457}
456458
459+ // Enhanced file content caching function
460+ export function getCachedFileContent ( filePath : string ) : string | null {
461+ try {
462+ // Check if file exists first
463+ if ( ! fs . existsSync ( filePath ) ) {
464+ return null ;
465+ }
466+
467+ const stats = fs . statSync ( filePath ) ;
468+
469+ // Don't cache files larger than 5MB to prevent memory issues
470+ if ( stats . size > FILE_CACHE_MAX_FILE_SIZE ) {
471+ return fs . readFileSync ( filePath , 'utf-8' ) ;
472+ }
473+
474+ const cachedContent = fileContentCache . get ( filePath ) ;
475+
476+ // Return cached content if it's still valid
477+ if ( cachedContent && cachedContent . timestamp >= stats . mtime . getTime ( ) ) {
478+ return cachedContent . content ;
479+ }
480+
481+ // Read file content
482+ const content = fs . readFileSync ( filePath , 'utf-8' ) ;
483+
484+ // Manage cache size - remove oldest entries if cache is full
485+ if ( fileContentCache . size >= FILE_CACHE_MAX_SIZE ) {
486+ const oldestKey = fileContentCache . keys ( ) . next ( ) . value ;
487+ if ( oldestKey ) {
488+ fileContentCache . delete ( oldestKey ) ;
489+ }
490+ }
491+
492+ // Cache the content
493+ fileContentCache . set ( filePath , {
494+ content,
495+ timestamp : stats . mtime . getTime ( )
496+ } ) ;
497+
498+ return content ;
499+ } catch ( error ) {
500+ console . error ( `Error reading file ${ filePath } :` , error ) ;
501+ return null ;
502+ }
503+ }
504+
505+ // Function to clear file content cache (useful for testing or memory management)
506+ export function clearFileContentCache ( ) : void {
507+ fileContentCache . clear ( ) ;
508+ }
509+
510+ // Function to invalidate cache for a specific file
511+ export function invalidateFileCache ( filePath : string ) : void {
512+ fileContentCache . delete ( filePath ) ;
513+ reportCache . delete ( filePath ) ;
514+ lineCountCache . delete ( filePath ) ;
515+ }
516+
457517export function parseReportTitle ( filePath : string ) : string {
458518 try {
459519 const report = getReportContent ( filePath ) ;
0 commit comments