@@ -163,16 +163,16 @@ function extractBalancedSymbols(text: string, openSymbol: string, closeSymbol: s
163
163
164
164
// Track depth when not in string
165
165
if ( ! inString ) {
166
- if ( char === openSymbol || char === '{' || char === '<' )
166
+ if ( char === openSymbol || char === '{' || char === '<' || char === '(' )
167
167
depth ++
168
- if ( char === closeSymbol || char === '}' || char === '>' )
168
+ if ( char === closeSymbol || char === '}' || char === '>' || char === ')' )
169
169
depth --
170
170
}
171
171
172
172
content . push ( char )
173
173
pos = i
174
174
175
- // Found matching closing symbol
175
+ // Found matching closing symbol at correct depth
176
176
if ( depth === 0 && content . length > 0 && char === closeSymbol ) {
177
177
return {
178
178
content : content . join ( '' ) ,
@@ -181,6 +181,18 @@ function extractBalancedSymbols(text: string, openSymbol: string, closeSymbol: s
181
181
}
182
182
}
183
183
184
+ // If we reach here without finding a match, return the best effort match
185
+ if ( content . length > 0 ) {
186
+ // Add closing symbol if missing
187
+ if ( content [ content . length - 1 ] !== closeSymbol ) {
188
+ content . push ( closeSymbol )
189
+ }
190
+ return {
191
+ content : content . join ( '' ) ,
192
+ rest : text . slice ( pos + 1 ) ,
193
+ }
194
+ }
195
+
184
196
return null
185
197
}
186
198
@@ -264,7 +276,7 @@ function extractFunctionSignature(declaration: string): FunctionSignature {
264
276
let rest = cleanDeclaration . slice ( cleanDeclaration . indexOf ( name ) + name . length ) . trim ( )
265
277
debugLog ( undefined , 'signature-content' , `Content after name: ${ rest } ` )
266
278
267
- // Extract generics
279
+ // Extract generics with improved depth tracking
268
280
const { generics, rest : restAfterGenerics } = extractGenerics ( rest )
269
281
rest = restAfterGenerics . trim ( )
270
282
debugLog ( undefined , 'signature-after-generics' , `Remaining content: ${ rest } ` )
@@ -300,26 +312,75 @@ function extractFunctionName(declaration: string): string {
300
312
function extractGenerics ( rest : string ) : { generics : string , rest : string } {
301
313
let generics = ''
302
314
if ( rest . startsWith ( '<' ) ) {
303
- let depth = 1
304
- let pos = 1
305
- let buffer = '<'
315
+ let depth = 1 // Start at 1 since we're starting with an opening bracket
316
+ let pos = 0
317
+ let buffer = '<' // Start buffer with opening bracket
318
+ let inString = false
319
+ let stringChar = ''
306
320
307
- for ( ; pos < rest . length && depth > 0 ; pos ++ ) {
308
- const char = rest [ pos ]
309
- if ( char === '<' )
310
- depth ++
311
- if ( char === '>' )
312
- depth --
313
- buffer += char
321
+ debugLog ( undefined , 'generics-input' , `Starting generic extraction with: ${ rest } ` )
322
+
323
+ // Start from position 1 since we already handled the first '<'
324
+ for ( let i = 1 ; i < rest . length ; i ++ ) {
325
+ const char = rest [ i ]
326
+ const nextChar = i < rest . length - 1 ? rest [ i + 1 ] : ''
327
+ const prevChar = i > 0 ? rest [ i - 1 ] : ''
328
+
329
+ debugLog ( undefined , 'generics-char' , `Processing char: ${ char } , next char: ${ nextChar } , depth: ${ depth } , pos: ${ i } ` )
330
+
331
+ // Handle string boundaries
332
+ if ( ( char === '"' || char === '\'' || char === '`' ) && prevChar !== '\\' ) {
333
+ if ( ! inString ) {
334
+ inString = true
335
+ stringChar = char
336
+ debugLog ( undefined , 'generics-string' , `Entering string with ${ stringChar } ` )
337
+ }
338
+ else if ( char === stringChar ) {
339
+ inString = false
340
+ debugLog ( undefined , 'generics-string' , 'Exiting string' )
341
+ }
342
+ }
343
+
344
+ // Track depth when not in string
345
+ if ( ! inString ) {
346
+ if ( char === '<' ) {
347
+ depth ++
348
+ debugLog ( undefined , 'generics-depth' , `Increasing depth to ${ depth } at pos ${ i } ` )
349
+ }
350
+ else if ( char === '>' ) {
351
+ depth --
352
+ debugLog ( undefined , 'generics-depth' , `Decreasing depth to ${ depth } at pos ${ i } ` )
353
+
354
+ // If we hit zero depth and the next char is also '>', include both
355
+ if ( depth === 0 && nextChar === '>' ) {
356
+ buffer += '>>' // Add both closing brackets
357
+ pos = i + 1 // Skip the next '>' since we've included it
358
+ debugLog ( undefined , 'generics-complete' , `Found double closing bracket at pos ${ i } , final buffer: ${ buffer } ` )
359
+ break
360
+ }
361
+ else if ( depth === 0 ) {
362
+ buffer += '>'
363
+ pos = i
364
+ debugLog ( undefined , 'generics-complete' , `Found single closing bracket at pos ${ i } , final buffer: ${ buffer } ` )
365
+ break
366
+ }
367
+ }
368
+ }
369
+
370
+ if ( depth > 0 ) { // Only add to buffer if we're still inside generic parameters
371
+ buffer += char
372
+ debugLog ( undefined , 'generics-buffer' , `Current buffer: ${ buffer } ` )
373
+ }
314
374
}
315
375
316
- if ( depth === 0 ) {
376
+ if ( buffer ) {
317
377
generics = buffer
318
- rest = rest . slice ( pos ) . trim ( )
319
- debugLog ( undefined , 'signature-generics' , `Extracted generics: ${ generics } ` )
378
+ rest = rest . slice ( pos + 1 )
379
+ debugLog ( undefined , 'generics-success' , `Successfully extracted generics: ${ generics } ` )
380
+ debugLog ( undefined , 'generics-rest' , `Remaining text: ${ rest } ` )
320
381
}
321
382
else {
322
- debugLog ( undefined , 'signature- generics' , `Unclosed generics in : ${ rest } ` )
383
+ debugLog ( undefined , 'generics-fail ' , `Failed to extract generics from : ${ rest } ` )
323
384
}
324
385
}
325
386
return { generics, rest }
@@ -373,17 +434,35 @@ function extractReturnType(rest: string, declaration: string): { returnType: str
373
434
let depth = 0
374
435
let buffer = ''
375
436
let i = 0
437
+ let inString = false
438
+ let stringChar = ''
439
+
376
440
while ( i < rest . length ) {
377
441
const char = rest [ i ]
442
+ const prevChar = i > 0 ? rest [ i - 1 ] : ''
378
443
379
- if ( char === '{' || char === '<' || char === '(' )
380
- depth ++
381
- else if ( char === '}' || char === '>' || char === ')' )
382
- depth --
444
+ // Handle string literals
445
+ if ( ( char === '"' || char === '\'' || char === '`' ) && prevChar !== '\\' ) {
446
+ if ( ! inString ) {
447
+ inString = true
448
+ stringChar = char
449
+ }
450
+ else if ( char === stringChar ) {
451
+ inString = false
452
+ }
453
+ }
383
454
384
- // Stop at function body start
385
- if ( depth === 0 && char === '{' ) {
386
- break
455
+ // Track depth when not in string
456
+ if ( ! inString ) {
457
+ if ( char === '{' || char === '<' || char === '(' )
458
+ depth ++
459
+ else if ( char === '}' || char === '>' || char === ')' )
460
+ depth --
461
+
462
+ // Stop at function body start or when we hit a semicolon outside any depth
463
+ if ( ( depth === 0 && char === '{' ) || ( depth === 0 && char === ';' ) ) {
464
+ break
465
+ }
387
466
}
388
467
389
468
buffer += char
0 commit comments