Skip to content

Commit 75afa55

Browse files
committed
chore: wip
chore: wip
1 parent 9c11f7a commit 75afa55

File tree

1 file changed

+86
-28
lines changed

1 file changed

+86
-28
lines changed

src/extract.ts

Lines changed: 86 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,67 @@ function inferConstArrayType(value: string, state?: ProcessingState): string {
761761
return 'unknown'
762762
}
763763

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(/return\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+
764825
function inferTypeFromDefaultValue(defaultValue: string): string {
765826
// Handle string literals
766827
if (/^['"`].*['"`]$/.test(defaultValue)) {
@@ -843,6 +904,12 @@ export function isDeclarationComplete(content: string | string[]): boolean {
843904
return /;\s*$/.test(trimmedContent) || /\}\s*$/.test(trimmedContent)
844905
}
845906

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+
846913
function needsMultilineFormat(types: string[]): boolean {
847914
return types.some(type =>
848915
type.includes('\n')
@@ -1380,27 +1447,18 @@ function processObjectMethod(declaration: string, value: string, state?: Process
13801447
const [, name, typeParams, params, returnType] = match
13811448
debugLog(state, 'process-method-parsed', `Name: ${name}, TypeParams: ${typeParams}, Params: ${params}, ReturnType: ${returnType}`)
13821449

1450+
// Check if method is async
13831451
const isAsync = declaration.startsWith('async ')
1384-
let effectiveReturnType = (returnType || 'void').trim()
1452+
debugLog(state, 'process-method-async', `Method ${name} async status: ${isAsync}`)
13851453

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(/void\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}`)
14021460

1403-
const cleanParams = cleanParameterTypes(params)
1461+
const cleanParams = cleanParameterTypes(params || '')
14041462
const signature = [
14051463
typeParams ? `<${typeParams}>` : '',
14061464
`(${cleanParams})`,
@@ -1411,7 +1469,7 @@ function processObjectMethod(declaration: string, value: string, state?: Process
14111469
.join(' ')
14121470
.trim()
14131471

1414-
debugLog(state, 'process-method-result', `Generated signature: ${signature}`)
1472+
debugLog(state, 'process-method-result', `Generated signature for ${name}: ${signature}`)
14151473
return { name, signature }
14161474
}
14171475

@@ -1433,7 +1491,6 @@ function processObjectProperties(content: string, state?: ProcessingState, inden
14331491
for (let i = 0; i < cleanContent.length; i++) {
14341492
const char = cleanContent[i]
14351493
const prevChar = i > 0 ? cleanContent[i - 1] : ''
1436-
const nextChar = i < cleanContent.length - 1 ? cleanContent[i + 1] : ''
14371494

14381495
// Handle string boundaries
14391496
if ((char === '"' || char === '\'' || char === '`') && prevChar !== '\\') {
@@ -1464,13 +1521,15 @@ function processObjectProperties(content: string, state?: ProcessingState, inden
14641521
continue
14651522
}
14661523
else if ((char === ',' || char === ';') && !isParsingKey) {
1467-
if (currentKey && buffer.trim()) {
1524+
if (currentKey) {
14681525
const trimmedBuffer = buffer.trim()
14691526
debugLog(state, 'process-props-value', `Processing value for key ${currentKey}: ${trimmedBuffer.substring(0, 50)}...`)
14701527

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*(?:async\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}`)
14741533
const { name, signature } = processObjectMethod(currentKey, trimmedBuffer, state)
14751534
properties.push({ key: name, value: signature })
14761535
}
@@ -1494,10 +1553,9 @@ function processObjectProperties(content: string, state?: ProcessingState, inden
14941553
// Handle final property
14951554
if (currentKey && !isParsingKey && buffer.trim()) {
14961555
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*(?:async\s+)?\w+\s*(?:<[^>]+>)?\s*\(/)
1557+
if (isMethodDecl) {
1558+
debugLog(state, 'process-props-method', `Detected final method: ${currentKey}`)
15011559
const { name, signature } = processObjectMethod(currentKey, trimmedBuffer, state)
15021560
properties.push({ key: name, value: signature })
15031561
}

0 commit comments

Comments
 (0)