@@ -761,6 +761,67 @@ function inferConstArrayType(value: string, state?: ProcessingState): string {
761
761
return 'unknown'
762
762
}
763
763
764
+ function inferReturnType ( value : string , declaration : string ) : string {
765
+ debugLog ( undefined , 'return-type' , `Inferring return type from ${ declaration ? 'declaration' : 'value' } ` )
766
+
767
+ // First check if there's an explicit return type in the declaration
768
+ if ( declaration ) {
769
+ const explicitMatch = declaration . match ( / \) : \s * ( [ ^ { ; ] + ) / )
770
+ if ( explicitMatch ) {
771
+ const returnType = explicitMatch [ 1 ] . trim ( )
772
+ debugLog ( undefined , 'return-type' , `Found explicit return type: ${ returnType } ` )
773
+ return returnType
774
+ }
775
+ }
776
+
777
+ // Check if it's an async method
778
+ const isAsync = declaration . startsWith ( 'async ' ) || value . includes ( 'async ' ) || ( value . includes ( '=>' ) && value . includes ( 'await' ) )
779
+ debugLog ( undefined , 'return-type' , `Is async method: ${ isAsync } ` )
780
+
781
+ let effectiveReturnType = 'void'
782
+
783
+ // Check for known return patterns
784
+ if ( value . includes ( 'throw' ) ) {
785
+ effectiveReturnType = 'never'
786
+ }
787
+ else if ( value . includes ( 'toISOString()' ) || value . includes ( 'toString()' ) ) {
788
+ effectiveReturnType = 'string'
789
+ }
790
+ else if ( value . includes ( 'Intl.NumberFormat' ) && value . includes ( 'format' ) ) {
791
+ effectiveReturnType = 'string'
792
+ }
793
+ else if ( value . match ( / ^ \{ \s * \/ \/ [ ^ } ] * \} $ / ) || value . match ( / ^ \{ \s * \} $ / ) || value . match ( / ^ \{ \s * \/ \* [ \s \S ] * ?\* \/ \s * \} $ / ) ) {
794
+ effectiveReturnType = 'void'
795
+ }
796
+ else {
797
+ // Check for return statements
798
+ const returnMatch = value . match ( / r e t u r n \s + ( [ ^ ; \s ] + ) / )
799
+ if ( returnMatch ) {
800
+ const returnValue = returnMatch [ 1 ]
801
+ if ( / ^ [ ' " ` ] / . test ( returnValue ) )
802
+ effectiveReturnType = 'string'
803
+ else if ( ! Number . isNaN ( Number ( returnValue ) ) )
804
+ effectiveReturnType = 'number'
805
+ else if ( returnValue === 'true' || returnValue === 'false' )
806
+ effectiveReturnType = 'boolean'
807
+ else if ( returnValue === 'null' )
808
+ effectiveReturnType = 'null'
809
+ else if ( returnValue === 'undefined' )
810
+ effectiveReturnType = 'undefined'
811
+ else effectiveReturnType = 'unknown'
812
+ }
813
+ }
814
+
815
+ // Wrap in Promise for async functions
816
+ if ( isAsync && ! effectiveReturnType . includes ( 'Promise' ) ) {
817
+ debugLog ( undefined , 'return-type' , `Wrapping ${ effectiveReturnType } in Promise for async method` )
818
+ effectiveReturnType = `Promise<${ effectiveReturnType } >`
819
+ }
820
+
821
+ debugLog ( undefined , 'return-type' , `Final inferred return type: ${ effectiveReturnType } ` )
822
+ return effectiveReturnType
823
+ }
824
+
764
825
function inferTypeFromDefaultValue ( defaultValue : string ) : string {
765
826
// Handle string literals
766
827
if ( / ^ [ ' " ` ] .* [ ' " ` ] $ / . test ( defaultValue ) ) {
@@ -843,6 +904,12 @@ export function isDeclarationComplete(content: string | string[]): boolean {
843
904
return / ; \s * $ / . test ( trimmedContent ) || / \} \s * $ / . test ( trimmedContent )
844
905
}
845
906
907
+ function isMethodDeclaration ( text : string ) : boolean {
908
+ debugLog ( undefined , 'method-check' , `Checking if method declaration: ${ text } ` )
909
+ // Simple check - either has parentheses in the key or starts with async
910
+ return text . includes ( '(' ) || text . startsWith ( 'async' )
911
+ }
912
+
846
913
function needsMultilineFormat ( types : string [ ] ) : boolean {
847
914
return types . some ( type =>
848
915
type . includes ( '\n' )
@@ -1380,27 +1447,18 @@ function processObjectMethod(declaration: string, value: string, state?: Process
1380
1447
const [ , name , typeParams , params , returnType ] = match
1381
1448
debugLog ( state , 'process-method-parsed' , `Name: ${ name } , TypeParams: ${ typeParams } , Params: ${ params } , ReturnType: ${ returnType } ` )
1382
1449
1450
+ // Check if method is async
1383
1451
const isAsync = declaration . startsWith ( 'async ' )
1384
- let effectiveReturnType = ( returnType || 'void' ) . trim ( )
1452
+ debugLog ( state , 'process-method-async' , `Method ${ name } async status: ${ isAsync } ` )
1385
1453
1386
- // Infer return types from implementation
1387
- if ( value . includes ( 'throw' ) && ! effectiveReturnType . includes ( 'Promise' ) ) {
1388
- effectiveReturnType = 'never'
1389
- }
1390
- else if ( isAsync && ! effectiveReturnType . includes ( 'Promise' ) ) {
1391
- effectiveReturnType = `Promise<${ effectiveReturnType } >`
1392
- }
1393
- else if ( value . includes ( 'toISOString()' ) || value . includes ( 'toString()' ) ) {
1394
- effectiveReturnType = 'string'
1395
- }
1396
- else if ( value . includes ( 'console.log' ) || value . match ( / v o i d \s * [ ; { ] / ) ) {
1397
- effectiveReturnType = 'void'
1398
- }
1399
- else if ( value . includes ( 'Intl.NumberFormat' ) && value . includes ( 'format' ) ) {
1400
- effectiveReturnType = 'string'
1401
- }
1454
+ // Use explicit return type if available, otherwise infer
1455
+ const effectiveReturnType = returnType
1456
+ ? returnType . trim ( )
1457
+ : inferReturnType ( value , declaration )
1458
+
1459
+ debugLog ( state , 'process-method-return' , `Return type for ${ name } : ${ effectiveReturnType } ` )
1402
1460
1403
- const cleanParams = cleanParameterTypes ( params )
1461
+ const cleanParams = cleanParameterTypes ( params || '' )
1404
1462
const signature = [
1405
1463
typeParams ? `<${ typeParams } >` : '' ,
1406
1464
`(${ cleanParams } )` ,
@@ -1411,7 +1469,7 @@ function processObjectMethod(declaration: string, value: string, state?: Process
1411
1469
. join ( ' ' )
1412
1470
. trim ( )
1413
1471
1414
- debugLog ( state , 'process-method-result' , `Generated signature: ${ signature } ` )
1472
+ debugLog ( state , 'process-method-result' , `Generated signature for ${ name } : ${ signature } ` )
1415
1473
return { name, signature }
1416
1474
}
1417
1475
@@ -1433,7 +1491,6 @@ function processObjectProperties(content: string, state?: ProcessingState, inden
1433
1491
for ( let i = 0 ; i < cleanContent . length ; i ++ ) {
1434
1492
const char = cleanContent [ i ]
1435
1493
const prevChar = i > 0 ? cleanContent [ i - 1 ] : ''
1436
- const nextChar = i < cleanContent . length - 1 ? cleanContent [ i + 1 ] : ''
1437
1494
1438
1495
// Handle string boundaries
1439
1496
if ( ( char === '"' || char === '\'' || char === '`' ) && prevChar !== '\\' ) {
@@ -1464,13 +1521,15 @@ function processObjectProperties(content: string, state?: ProcessingState, inden
1464
1521
continue
1465
1522
}
1466
1523
else if ( ( char === ',' || char === ';' ) && ! isParsingKey ) {
1467
- if ( currentKey && buffer . trim ( ) ) {
1524
+ if ( currentKey ) {
1468
1525
const trimmedBuffer = buffer . trim ( )
1469
1526
debugLog ( state , 'process-props-value' , `Processing value for key ${ currentKey } : ${ trimmedBuffer . substring ( 0 , 50 ) } ...` )
1470
1527
1471
- // Check if this is a method declaration
1472
- if ( currentKey . includes ( '(' ) ) {
1473
- debugLog ( state , 'process-props-method' , `Detected method declaration: ${ currentKey } ` )
1528
+ const isMethodDecl = currentKey . includes ( '(' ) || currentKey . match ( / ^ \s * (?: a s y n c \s + ) ? \w + \s * (?: < [ ^ > ] + > ) ? \s * \( / )
1529
+ debugLog ( state , 'method-check' , `Checking if method declaration: ${ currentKey } ` )
1530
+
1531
+ if ( isMethodDecl ) {
1532
+ debugLog ( state , 'process-props-method' , `Detected method: ${ currentKey } with body length: ${ trimmedBuffer . length } ` )
1474
1533
const { name, signature } = processObjectMethod ( currentKey , trimmedBuffer , state )
1475
1534
properties . push ( { key : name , value : signature } )
1476
1535
}
@@ -1494,10 +1553,9 @@ function processObjectProperties(content: string, state?: ProcessingState, inden
1494
1553
// Handle final property
1495
1554
if ( currentKey && ! isParsingKey && buffer . trim ( ) ) {
1496
1555
const trimmedBuffer = buffer . trim ( )
1497
- debugLog ( state , 'process-props-final' , `Processing final property ${ currentKey } : ${ trimmedBuffer . substring ( 0 , 50 ) } ...` )
1498
-
1499
- if ( currentKey . includes ( '(' ) ) {
1500
- debugLog ( state , 'process-props-method' , `Detected method declaration: ${ currentKey } ` )
1556
+ const isMethodDecl = currentKey . includes ( '(' ) || currentKey . match ( / ^ \s * (?: a s y n c \s + ) ? \w + \s * (?: < [ ^ > ] + > ) ? \s * \( / )
1557
+ if ( isMethodDecl ) {
1558
+ debugLog ( state , 'process-props-method' , `Detected final method: ${ currentKey } ` )
1501
1559
const { name, signature } = processObjectMethod ( currentKey , trimmedBuffer , state )
1502
1560
properties . push ( { key : name , value : signature } )
1503
1561
}
0 commit comments