@@ -618,8 +618,10 @@ export function parseFunctionDeclaration(declaration: string): FunctionParseStat
618
618
isAsync : false ,
619
619
}
620
620
621
- // Check for async and clean declaration
621
+ // Check for async
622
622
state . isAsync = declaration . includes ( 'async' )
623
+
624
+ // Clean declaration
623
625
let cleanDeclaration = declaration
624
626
. replace ( / ^ e x p o r t \s + / , '' )
625
627
. replace ( / ^ a s y n c \s + / , '' )
@@ -636,63 +638,26 @@ export function parseFunctionDeclaration(declaration: string): FunctionParseStat
636
638
cleanDeclaration = cleanDeclaration . slice ( functionMatch [ 0 ] . length ) . trim ( )
637
639
}
638
640
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 ( )
667
646
}
668
647
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 ( )
673
655
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 ( / P r o m i s e \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 ( )
693
660
}
694
-
695
- state . returnType = returnType
696
661
}
697
662
698
663
return state
@@ -792,6 +757,64 @@ export function processTypeDeclaration(declaration: string, isExported = true):
792
757
return `${ isExported ? 'export ' : '' } declare type ${ typeName } = ${ typeBody } ;`
793
758
}
794
759
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 ( / ^ ( e x p o r t \s + ) ? ( a s y n c \s + ) ? f u n c t i o n \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
+
795
818
/**
796
819
* Process function declarations with full type information preservation
797
820
*/
@@ -800,43 +823,48 @@ export function processFunctionDeclaration(
800
823
usedTypes : Set < string > ,
801
824
isExported = true ,
802
825
) : 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' )
805
831
return declaration
832
+ }
806
833
807
- const signature = signatureMatch [ 0 ] . trim ( )
834
+ console . log ( 'Using signature:' , signature )
808
835
const parseResult = parseFunctionDeclaration ( signature )
836
+ console . log ( 'Parse result:' , parseResult )
809
837
810
- // Track used types, handling complex type expressions
838
+ // Add types to usedTypes set
811
839
const addTypeToUsed = ( type : string ) => {
812
840
if ( ! type )
813
841
return
814
842
815
- // Handle types with generics
816
843
const typeMatches = type . match ( / ( [ A - Z _ ] \w * ) / gi) || [ ]
817
844
typeMatches . forEach ( ( t ) => {
818
845
if ( ! t . match ( / ^ ( v o i d | a n y | n u m b e r | s t r i n g | b o o l e a n | n u l l | u n d e f i n e d | n e v e r | u n k n o w n | P r o m i s e ) $ / ) ) {
819
846
usedTypes . add ( t )
847
+ console . log ( 'Added type to used:' , t )
820
848
}
821
849
} )
822
850
}
823
851
824
- // Process return type and parameters
852
+ // Process all types
825
853
addTypeToUsed ( parseResult . returnType )
826
854
addTypeToUsed ( parseResult . parameters )
827
855
828
- // Process generic type parameters
829
856
if ( parseResult . genericParams ) {
830
857
const genericContent = parseResult . genericParams . slice ( 1 , - 1 )
831
858
genericContent . split ( ',' ) . forEach ( ( param ) => {
832
859
const [ , constraint ] = param . split ( ' extends ' )
833
860
if ( constraint ) {
834
861
addTypeToUsed ( constraint )
862
+ console . log ( 'Added generic constraint:' , constraint )
835
863
}
836
864
} )
837
865
}
838
866
839
- // Preserve original parameter structure and return type
867
+ // Construct the declaration, ensuring proper spacing and no duplicate colons
840
868
return [
841
869
isExported ? 'export ' : '' ,
842
870
'declare ' ,
@@ -849,7 +877,7 @@ export function processFunctionDeclaration(
849
877
'): ' ,
850
878
parseResult . returnType ,
851
879
';' ,
852
- ] . join ( '' ) . replace ( / \s + / g , ' ' ) . trim ( )
880
+ ] . join ( '' )
853
881
}
854
882
855
883
// Helper functions for line processing
0 commit comments