@@ -4,13 +4,62 @@ import type { Declaration } from './types'
44import { createSourceFile , forEachChild , isArrayBindingPattern , isBindingElement , isCallSignatureDeclaration , isConstructorDeclaration , isConstructSignatureDeclaration , isEnumDeclaration , isEnumMember , isExportAssignment , isFunctionDeclaration , isIdentifier , isInterfaceDeclaration , isMethodDeclaration , isMethodSignature , isModuleBlock , isModuleDeclaration , isObjectBindingPattern , isPropertyDeclaration , isPropertySignature , isStringLiteral , isTypeAliasDeclaration , isVariableStatement , NodeFlags , ScriptKind , ScriptTarget , SyntaxKind } from 'typescript'
55
66/**
7- * Extract only public API declarations from TypeScript source code
8- * This focuses on what should be in .d.ts files, not implementation details
7+ * Cache for parsed SourceFile objects to avoid re-parsing
8+ * Key: filePath, Value: { sourceFile, contentHash, lastAccess }
99 */
10- export function extractDeclarations ( sourceCode : string , filePath : string , keepComments : boolean = true ) : Declaration [ ] {
11- const declarations : Declaration [ ] = [ ]
10+ const sourceFileCache = new Map < string , { sourceFile : SourceFile , contentHash : number , lastAccess : number } > ( )
11+
12+ /**
13+ * Maximum number of cached SourceFiles to prevent memory bloat
14+ */
15+ const MAX_CACHE_SIZE = 100
16+
17+ /**
18+ * Simple hash function for content comparison
19+ */
20+ function hashContent ( content : string ) : number {
21+ let hash = 0
22+ for ( let i = 0 ; i < content . length ; i ++ ) {
23+ const char = content . charCodeAt ( i )
24+ hash = ( ( hash << 5 ) - hash ) + char
25+ hash = hash & hash // Convert to 32-bit integer
26+ }
27+ return hash
28+ }
29+
30+ /**
31+ * Evict oldest entries if cache exceeds max size
32+ */
33+ function evictOldestEntries ( ) : void {
34+ if ( sourceFileCache . size <= MAX_CACHE_SIZE ) {
35+ return
36+ }
37+
38+ // Sort by last access time and remove oldest entries
39+ const entries = Array . from ( sourceFileCache . entries ( ) )
40+ . sort ( ( a , b ) => a [ 1 ] . lastAccess - b [ 1 ] . lastAccess )
41+
42+ const toRemove = entries . slice ( 0 , entries . length - MAX_CACHE_SIZE )
43+ for ( const [ key ] of toRemove ) {
44+ sourceFileCache . delete ( key )
45+ }
46+ }
47+
48+ /**
49+ * Get or create a cached SourceFile
50+ */
51+ function getSourceFile ( filePath : string , sourceCode : string ) : SourceFile {
52+ const contentHash = hashContent ( sourceCode )
53+ const cached = sourceFileCache . get ( filePath )
54+ const now = Date . now ( )
55+
56+ if ( cached && cached . contentHash === contentHash ) {
57+ // Update last access time
58+ cached . lastAccess = now
59+ return cached . sourceFile
60+ }
1261
13- // Create TypeScript source file
62+ // Create new SourceFile and cache it
1463 const sourceFile = createSourceFile (
1564 filePath ,
1665 sourceCode ,
@@ -19,6 +68,38 @@ export function extractDeclarations(sourceCode: string, filePath: string, keepCo
1968 ScriptKind . TS ,
2069 )
2170
71+ sourceFileCache . set ( filePath , { sourceFile, contentHash, lastAccess : now } )
72+
73+ // Evict old entries if needed
74+ evictOldestEntries ( )
75+
76+ return sourceFile
77+ }
78+
79+ /**
80+ * Clear the SourceFile cache (useful for testing or memory management)
81+ */
82+ export function clearSourceFileCache ( ) : void {
83+ sourceFileCache . clear ( )
84+ }
85+
86+ /**
87+ * Get the current cache size (useful for debugging)
88+ */
89+ export function getSourceFileCacheSize ( ) : number {
90+ return sourceFileCache . size
91+ }
92+
93+ /**
94+ * Extract only public API declarations from TypeScript source code
95+ * This focuses on what should be in .d.ts files, not implementation details
96+ */
97+ export function extractDeclarations ( sourceCode : string , filePath : string , keepComments : boolean = true ) : Declaration [ ] {
98+ const declarations : Declaration [ ] = [ ]
99+
100+ // Get or create cached TypeScript source file
101+ const sourceFile = getSourceFile ( filePath , sourceCode )
102+
22103 // Visit only top-level declarations
23104 function visitTopLevel ( node : Node ) {
24105 // Only process top-level declarations, skip function bodies and implementation details
0 commit comments