Skip to content

Commit 38c8c80

Browse files
committed
chore: wip
chore: wip chore: wip
1 parent 6c9e509 commit 38c8c80

File tree

1 file changed

+91
-63
lines changed

1 file changed

+91
-63
lines changed

src/extract.ts

Lines changed: 91 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -618,8 +618,10 @@ export function parseFunctionDeclaration(declaration: string): FunctionParseStat
618618
isAsync: false,
619619
}
620620

621-
// Check for async and clean declaration
621+
// Check for async
622622
state.isAsync = declaration.includes('async')
623+
624+
// Clean declaration
623625
let cleanDeclaration = declaration
624626
.replace(/^export\s+/, '')
625627
.replace(/^async\s+/, '')
@@ -636,63 +638,26 @@ export function parseFunctionDeclaration(declaration: string): FunctionParseStat
636638
cleanDeclaration = cleanDeclaration.slice(functionMatch[0].length).trim()
637639
}
638640

639-
// Extract full parameter string by matching balanced parentheses
640-
let paramDepth = 0
641-
let paramStart = -1
642-
let paramEnd = -1
643-
let inGeneric = false
644-
645-
for (let i = 0; i < cleanDeclaration.length; i++) {
646-
const char = cleanDeclaration[i]
647-
if (char === '<') {
648-
inGeneric = true
649-
}
650-
else if (char === '>') {
651-
inGeneric = false
652-
}
653-
else if (!inGeneric) {
654-
if (char === '(') {
655-
if (paramDepth === 0)
656-
paramStart = i
657-
paramDepth++
658-
}
659-
else if (char === ')') {
660-
paramDepth--
661-
if (paramDepth === 0) {
662-
paramEnd = i
663-
break
664-
}
665-
}
666-
}
641+
// Extract parameters
642+
const paramsMatch = cleanDeclaration.match(/\(([\s\S]*?)\)/)
643+
if (paramsMatch) {
644+
state.parameters = paramsMatch[1].trim()
645+
cleanDeclaration = cleanDeclaration.slice(paramsMatch[0].length).trim()
667646
}
668647

669-
if (paramStart !== -1 && paramEnd !== -1) {
670-
state.parameters = cleanDeclaration.slice(paramStart + 1, paramEnd).trim()
671-
cleanDeclaration = cleanDeclaration.slice(paramEnd + 1).trim()
672-
}
648+
// Extract return type, removing any duplicate colons
649+
if (cleanDeclaration.startsWith(':')) {
650+
let returnType = cleanDeclaration.slice(1).trim()
651+
returnType = returnType
652+
.replace(/:\s*$/, '') // Remove trailing colons
653+
.replace(/\s+/g, ' ') // Normalize spaces
654+
.trim()
673655

674-
// Extract return type, handling Promise types correctly
675-
// eslint-disable-next-line regexp/no-super-linear-backtracking
676-
const returnMatch = cleanDeclaration.match(/^:\s*(.+?)(?:$|\{)/)
677-
if (returnMatch) {
678-
let returnType = returnMatch[1].trim()
679-
.replace(/;$/, '')
680-
.replace(/\s+/g, ' ')
681-
682-
// Parse Promise return types
683-
if (returnType.includes('Promise')) {
684-
const promiseMatch = returnType.match(/Promise\s*<(.+)>/)
685-
if (promiseMatch) {
686-
returnType = `Promise<${promiseMatch[1].trim()}>`
687-
}
688-
else {
689-
// If Promise is specified without type parameter, try to infer it
690-
const typeParam = returnType.replace('Promise', '').trim()
691-
returnType = typeParam ? `Promise<${typeParam}>` : 'Promise<void>'
692-
}
656+
// Match the return type up to any trailing colon
657+
const returnMatch = returnType.match(/^([^:]+)/)
658+
if (returnMatch) {
659+
state.returnType = returnMatch[1].trim()
693660
}
694-
695-
state.returnType = returnType
696661
}
697662

698663
return state
@@ -792,6 +757,64 @@ export function processTypeDeclaration(declaration: string, isExported = true):
792757
return `${isExported ? 'export ' : ''}declare type ${typeName} = ${typeBody};`
793758
}
794759

760+
/**
761+
* Extract complete function signature handling multi-line declarations
762+
*/
763+
export function extractFunctionSignature(declaration: string): string {
764+
// First, normalize line breaks and whitespace
765+
const normalized = declaration
766+
.split('\n')
767+
.map(line => line.trim())
768+
.join(' ')
769+
770+
// Match function declaration including parameters and return type
771+
const match = normalized.match(/^(export\s+)?(async\s+)?function\s+([^{]+)/)
772+
if (!match)
773+
return ''
774+
775+
let signature = match[0]
776+
let depth = 0
777+
let genericDepth = 0
778+
let foundBody = false
779+
780+
// Process character by character to find the complete signature
781+
for (let i = match[0].length; i < normalized.length && !foundBody; i++) {
782+
const char = normalized[i]
783+
784+
if (char === '<') {
785+
genericDepth++
786+
}
787+
else if (char === '>') {
788+
genericDepth--
789+
}
790+
else if (genericDepth === 0) {
791+
if (char === '(') {
792+
depth++
793+
}
794+
else if (char === ')') {
795+
depth--
796+
}
797+
else if (char === '{') {
798+
foundBody = true
799+
break
800+
}
801+
}
802+
803+
if (!foundBody) {
804+
signature += char
805+
}
806+
}
807+
808+
// Clean up the signature
809+
signature = signature
810+
.replace(/\s+/g, ' ')
811+
.replace(/:\s+/g, ': ')
812+
.trim()
813+
814+
console.log('Extracted raw signature:', signature)
815+
return signature
816+
}
817+
795818
/**
796819
* Process function declarations with full type information preservation
797820
*/
@@ -800,43 +823,48 @@ export function processFunctionDeclaration(
800823
usedTypes: Set<string>,
801824
isExported = true,
802825
): string {
803-
const signatureMatch = declaration.match(/^.*?(?=\{|$)/)
804-
if (!signatureMatch)
826+
console.log('Processing declaration:', declaration)
827+
828+
const signature = extractFunctionSignature(declaration)
829+
if (!signature) {
830+
console.log('No valid signature found')
805831
return declaration
832+
}
806833

807-
const signature = signatureMatch[0].trim()
834+
console.log('Using signature:', signature)
808835
const parseResult = parseFunctionDeclaration(signature)
836+
console.log('Parse result:', parseResult)
809837

810-
// Track used types, handling complex type expressions
838+
// Add types to usedTypes set
811839
const addTypeToUsed = (type: string) => {
812840
if (!type)
813841
return
814842

815-
// Handle types with generics
816843
const typeMatches = type.match(/([A-Z_]\w*)/gi) || []
817844
typeMatches.forEach((t) => {
818845
if (!t.match(/^(void|any|number|string|boolean|null|undefined|never|unknown|Promise)$/)) {
819846
usedTypes.add(t)
847+
console.log('Added type to used:', t)
820848
}
821849
})
822850
}
823851

824-
// Process return type and parameters
852+
// Process all types
825853
addTypeToUsed(parseResult.returnType)
826854
addTypeToUsed(parseResult.parameters)
827855

828-
// Process generic type parameters
829856
if (parseResult.genericParams) {
830857
const genericContent = parseResult.genericParams.slice(1, -1)
831858
genericContent.split(',').forEach((param) => {
832859
const [, constraint] = param.split(' extends ')
833860
if (constraint) {
834861
addTypeToUsed(constraint)
862+
console.log('Added generic constraint:', constraint)
835863
}
836864
})
837865
}
838866

839-
// Preserve original parameter structure and return type
867+
// Construct the declaration, ensuring proper spacing and no duplicate colons
840868
return [
841869
isExported ? 'export ' : '',
842870
'declare ',
@@ -849,7 +877,7 @@ export function processFunctionDeclaration(
849877
'): ',
850878
parseResult.returnType,
851879
';',
852-
].join('').replace(/\s+/g, ' ').trim()
880+
].join('')
853881
}
854882

855883
// Helper functions for line processing

0 commit comments

Comments
 (0)