@@ -1109,39 +1109,209 @@ function parseObjectProperties(content: string): Array<[string, string]> {
1109
1109
return properties
1110
1110
}
1111
1111
1112
+ /**
1113
+ * Find matching bracket for nested structures
1114
+ */
1115
+ function findMatchingBracket ( str : string , start : number , openChar : string , closeChar : string ) : number {
1116
+ let depth = 0
1117
+ for ( let i = start ; i < str . length ; i ++ ) {
1118
+ if ( str [ i ] === openChar ) {
1119
+ depth ++
1120
+ } else if ( str [ i ] === closeChar ) {
1121
+ depth --
1122
+ if ( depth === 0 ) {
1123
+ return i
1124
+ }
1125
+ }
1126
+ }
1127
+ return - 1
1128
+ }
1129
+
1112
1130
/**
1113
1131
* Infer function type from function expression
1114
1132
*/
1115
1133
function inferFunctionType ( value : string , inUnion : boolean = false ) : string {
1116
- // Arrow functions
1117
- if ( value . includes ( '=>' ) ) {
1118
- const arrowIndex = value . indexOf ( '=>' )
1119
- let params = value . substring ( 0 , arrowIndex ) . trim ( )
1134
+ const trimmed = value . trim ( )
1120
1135
1121
- // Clean up params - remove extra parentheses if they exist
1136
+ // Handle very complex function types early (but not function expressions)
1137
+ if ( ( trimmed . length > 100 || ( trimmed . match ( / = > / g) || [ ] ) . length > 2 ) && ! trimmed . startsWith ( 'function' ) ) {
1138
+ // Extract just the basic signature pattern
1139
+ const genericMatch = trimmed . match ( / ^ < [ ^ > ] + > / )
1140
+ const generics = genericMatch ? genericMatch [ 0 ] : ''
1141
+
1142
+ // Look for first parameter pattern - need to find the complete parameter list
1143
+ let paramStart = trimmed . indexOf ( '(' )
1144
+ if ( paramStart !== - 1 ) {
1145
+ let paramEnd = findMatchingBracket ( trimmed , paramStart , '(' , ')' )
1146
+ if ( paramEnd !== - 1 ) {
1147
+ const params = trimmed . substring ( paramStart , paramEnd + 1 )
1148
+ const funcType = `${ generics } ${ params } => any`
1149
+ return inUnion ? `(${ funcType } )` : funcType
1150
+ }
1151
+ }
1152
+
1153
+ // Fallback if parameter extraction fails
1154
+ const funcType = `${ generics } (...args: any[]) => any`
1155
+ return inUnion ? `(${ funcType } )` : funcType
1156
+ }
1157
+
1158
+ // Handle async arrow functions
1159
+ if ( trimmed . startsWith ( 'async ' ) && trimmed . includes ( '=>' ) ) {
1160
+ const asyncRemoved = trimmed . slice ( 5 ) . trim ( ) // Remove 'async '
1161
+ const arrowIndex = asyncRemoved . indexOf ( '=>' )
1162
+ let params = asyncRemoved . substring ( 0 , arrowIndex ) . trim ( )
1163
+ let body = asyncRemoved . substring ( arrowIndex + 2 ) . trim ( )
1164
+
1165
+ // Clean up params
1122
1166
if ( params === '()' || params === '' ) {
1123
- params = ''
1124
- } else if ( params . startsWith ( '(' ) && params . endsWith ( ')' ) ) {
1125
- // Keep the parentheses for parameters
1126
- params = params
1167
+ params = '()'
1168
+ } else if ( ! params . startsWith ( '(' ) ) {
1169
+ // Single parameter without parentheses
1170
+ params = `(${ params } )`
1171
+ }
1172
+
1173
+ // Try to infer return type from body
1174
+ let returnType = 'unknown'
1175
+ if ( body . startsWith ( '{' ) ) {
1176
+ // Block body - can't easily infer return type
1177
+ returnType = 'unknown'
1127
1178
} else {
1179
+ // Expression body - try to infer
1180
+ returnType = inferNarrowType ( body , false )
1181
+ }
1182
+
1183
+ const funcType = `${ params } => Promise<${ returnType } >`
1184
+ return inUnion ? `(${ funcType } )` : funcType
1185
+ }
1186
+
1187
+ // Regular arrow functions
1188
+ if ( trimmed . includes ( '=>' ) ) {
1189
+ // Handle generics at the beginning
1190
+ let generics = ''
1191
+ let remaining = trimmed
1192
+
1193
+ // Check for generics at the start
1194
+ if ( trimmed . startsWith ( '<' ) ) {
1195
+ const genericEnd = findMatchingBracket ( trimmed , 0 , '<' , '>' )
1196
+ if ( genericEnd !== - 1 ) {
1197
+ generics = trimmed . substring ( 0 , genericEnd + 1 )
1198
+ remaining = trimmed . substring ( genericEnd + 1 ) . trim ( )
1199
+ }
1200
+ }
1201
+
1202
+ const arrowIndex = remaining . indexOf ( '=>' )
1203
+ if ( arrowIndex === - 1 ) {
1204
+ // Fallback if no arrow found
1205
+ const funcType = '() => unknown'
1206
+ return inUnion ? `(${ funcType } )` : funcType
1207
+ }
1208
+
1209
+ let params = remaining . substring ( 0 , arrowIndex ) . trim ( )
1210
+ let body = remaining . substring ( arrowIndex + 2 ) . trim ( )
1211
+
1212
+ // Handle explicit return type annotations in parameters
1213
+ // Look for pattern like (param: Type): ReturnType
1214
+ let explicitReturnType = ''
1215
+ const returnTypeMatch = params . match ( / \) : \s * ( [ ^ = ] + ) $ / )
1216
+ if ( returnTypeMatch ) {
1217
+ explicitReturnType = returnTypeMatch [ 1 ] . trim ( )
1218
+ params = params . substring ( 0 , params . lastIndexOf ( '):' ) ) + ')'
1219
+ }
1220
+
1221
+ // Clean up params
1222
+ if ( params === '()' || params === '' ) {
1223
+ params = '()'
1224
+ } else if ( ! params . startsWith ( '(' ) ) {
1128
1225
// Single parameter without parentheses
1129
1226
params = `(${ params } )`
1130
1227
}
1131
1228
1132
- // Try to parse return type from the body
1133
- const funcType = `${ params || '()' } => unknown`
1229
+ // Try to infer return type from body
1230
+ let returnType = 'unknown'
1231
+ if ( explicitReturnType ) {
1232
+ // Use explicit return type annotation
1233
+ returnType = explicitReturnType
1234
+ } else if ( body . startsWith ( '{' ) ) {
1235
+ // Block body - can't easily infer return type
1236
+ returnType = 'unknown'
1237
+ } else if ( body . includes ( '=>' ) ) {
1238
+ // This is a higher-order function returning another function
1239
+ // Try to infer the return function type
1240
+ const innerFuncType = inferFunctionType ( body , false )
1241
+ returnType = innerFuncType
1242
+ } else {
1243
+ // Expression body - try to infer
1244
+ returnType = inferNarrowType ( body , false )
1245
+ }
1134
1246
1135
- // Add extra parentheses if this function is part of a union type
1247
+ const funcType = ` ${ generics } ${ params } => ${ returnType } `
1136
1248
return inUnion ? `(${ funcType } )` : funcType
1137
1249
}
1138
1250
1139
- // Regular functions
1140
- if ( value . startsWith ( 'function' ) || value . startsWith ( 'async function' ) ) {
1251
+ // Function expressions
1252
+ if ( trimmed . startsWith ( 'function' ) ) {
1253
+ // Handle generics in function expressions like function* <T>(items: T[])
1254
+ let generics = ''
1255
+ let remaining = trimmed
1256
+
1257
+ // Look for generics after function keyword
1258
+ const genericMatch = trimmed . match ( / f u n c t i o n \s * \* ? \s * ( < [ ^ > ] + > ) / )
1259
+ if ( genericMatch ) {
1260
+ generics = genericMatch [ 1 ]
1261
+ }
1262
+
1263
+ // Try to extract function signature
1264
+ const funcMatch = trimmed . match ( / f u n c t i o n \s * ( \* ? ) \s * (?: < [ ^ > ] + > ) ? \s * ( [ ^ ( ] * ) \( ( [ ^ ) ] * ) \) / )
1265
+ if ( funcMatch ) {
1266
+ const isGenerator = ! ! funcMatch [ 1 ]
1267
+ const name = funcMatch [ 2 ] . trim ( )
1268
+ const params = funcMatch [ 3 ] . trim ( )
1269
+
1270
+ let paramTypes = '(...args: any[])'
1271
+ if ( params ) {
1272
+ // Try to parse parameters
1273
+ paramTypes = `(${ params } )`
1274
+ } else {
1275
+ paramTypes = '()'
1276
+ }
1277
+
1278
+ if ( isGenerator ) {
1279
+ // Try to extract return type from the function signature
1280
+ const returnTypeMatch = trimmed . match ( / : \s * G e n e r a t o r < ( [ ^ > ] + ) > / )
1281
+ if ( returnTypeMatch ) {
1282
+ const generatorTypes = returnTypeMatch [ 1 ]
1283
+ return inUnion ? `(${ generics } ${ paramTypes } => Generator<${ generatorTypes } >)` : `${ generics } ${ paramTypes } => Generator<${ generatorTypes } >`
1284
+ }
1285
+ return inUnion ? `(${ generics } ${ paramTypes } => Generator<any, any, any>)` : `${ generics } ${ paramTypes } => Generator<any, any, any>`
1286
+ }
1287
+
1288
+ return inUnion ? `(${ generics } ${ paramTypes } => unknown)` : `${ generics } ${ paramTypes } => unknown`
1289
+ }
1290
+
1141
1291
const funcType = '(...args: any[]) => unknown'
1142
1292
return inUnion ? `(${ funcType } )` : funcType
1143
1293
}
1144
1294
1295
+ // Higher-order functions (functions that return functions)
1296
+ if ( trimmed . includes ( '=>' ) && trimmed . includes ( '(' ) && trimmed . includes ( ')' ) ) {
1297
+ // For very complex function types, fall back to a simpler signature
1298
+ if ( trimmed . length > 100 || ( trimmed . match ( / = > / g) || [ ] ) . length > 2 ) {
1299
+ // Extract just the basic signature pattern
1300
+ const genericMatch = trimmed . match ( / ^ < [ ^ > ] + > / )
1301
+ const generics = genericMatch ? genericMatch [ 0 ] : ''
1302
+
1303
+ // Look for parameter pattern
1304
+ const paramMatch = trimmed . match ( / \( [ ^ ) ] * \) / )
1305
+ const params = paramMatch ? paramMatch [ 0 ] : '(...args: any[])'
1306
+
1307
+ const funcType = `${ generics } ${ params } => any`
1308
+ return inUnion ? `(${ funcType } )` : funcType
1309
+ }
1310
+
1311
+ // This might be a higher-order function, try to preserve the structure
1312
+ return inUnion ? `(${ trimmed } )` : trimmed
1313
+ }
1314
+
1145
1315
const funcType = '() => unknown'
1146
1316
return inUnion ? `(${ funcType } )` : funcType
1147
1317
}
0 commit comments