@@ -794,6 +794,14 @@ export interface FunctionSignature {
794
794
generics : string
795
795
}
796
796
797
+ /**
798
+ * Represents a tracked type reference
799
+ */
800
+ export interface TypeReference {
801
+ name : string
802
+ generics : string [ ]
803
+ isExternal : boolean
804
+ }
797
805
798
806
/**
799
807
* Extract complete function signature handling multi-line declarations
@@ -821,13 +829,8 @@ export function extractFunctionSignature(declaration: string): FunctionSignature
821
829
const paramsMatch = withoutGenerics . match ( / \( ( [ \s \S ] * ?) \) (? = \s * : ) / )
822
830
let params = paramsMatch ? paramsMatch [ 1 ] . trim ( ) : ''
823
831
824
- // Handle destructured parameters
825
- if ( params . startsWith ( '{' ) ) {
826
- const typeMatch = params . match ( / \} : \s * ( [ ^ ) ] + ) $ / )
827
- if ( typeMatch ) {
828
- params = `options: ${ typeMatch [ 1 ] . trim ( ) } `
829
- }
830
- }
832
+ // Clean up parameters
833
+ params = cleanParameters ( params )
831
834
832
835
// Extract return type
833
836
const returnTypeMatch = withoutGenerics . match ( / \) \s * : \s * ( [ \s \S ] + ?) (? = \{ | $ ) / )
@@ -858,18 +861,10 @@ export function processFunctionDeclaration(
858
861
generics,
859
862
} = extractFunctionSignature ( declaration )
860
863
861
- // Track generic types
862
- if ( generics ) {
863
- const genericTypes = generics
864
- . slice ( 1 , - 1 )
865
- . split ( ',' )
866
- . map ( t => t . trim ( ) . split ( 'extends' ) [ 0 ] . trim ( ) )
867
-
868
- genericTypes . forEach ( ( type ) => {
869
- if ( type )
870
- usedTypes . add ( type )
871
- } )
872
- }
864
+ // Track types used in the signature
865
+ trackUsedTypes ( generics , usedTypes )
866
+ trackUsedTypes ( params , usedTypes )
867
+ trackUsedTypes ( returnType , usedTypes )
873
868
874
869
// Build declaration string
875
870
let result = `${ isExported ? 'export ' : '' } declare `
@@ -882,23 +877,81 @@ export function processFunctionDeclaration(
882
877
}
883
878
884
879
export function cleanParameters ( params : string ) : string {
880
+ if ( ! params . trim ( ) )
881
+ return ''
882
+
885
883
return params
884
+ // Handle destructured parameters
885
+ . replace ( / \{ ( [ ^ } ] + ) \} : \s * ( [ ^ , ) ] + ) / g, ( _ , props , type ) => {
886
+ // Convert destructured parameters to a single options parameter
887
+ const typeName = type . trim ( )
888
+ return `options: ${ typeName } `
889
+ } )
890
+ // Normalize spaces around special characters
891
+ . replace ( / \s * ( [ , : ] ) \s * / g, '$1 ' )
892
+ // Clean up multiple spaces
886
893
. replace ( / \s + / g, ' ' )
887
- . replace ( / \s * , \s * / g, ', ' )
888
- . replace ( / \s * : \s * / g, ': ' )
894
+ // Add space after commas if missing
895
+ . replace ( / , ( \S ) / g, ', $1' )
896
+ // Normalize optional parameter syntax
897
+ . replace ( / \s * \? \s * : / g, '?: ' )
898
+ // Clean up spaces around array/generic brackets
899
+ . replace ( / \s * ( [ < [ \] > ] ) \s * / g, '$1' )
900
+ // Final cleanup of any double spaces
901
+ . replace ( / \s { 2 , } / g, ' ' )
889
902
. trim ( )
890
903
}
891
904
892
905
/**
893
906
* Analyze a function body to track used type references
894
907
*/
895
- export function trackUsedTypes ( body : string , usedTypes : Set < string > ) : void {
896
- const typeMatches = body . match ( / [ A - Z ] [ a - z A - Z 0 - 9 ] * (?: < [ ^ > ] + > ) ? / g) || [ ]
897
- typeMatches . forEach ( ( type ) => {
898
- const baseType = type . split ( '<' ) [ 0 ]
899
- if ( baseType )
900
- usedTypes . add ( baseType )
901
- } )
908
+ export function trackUsedTypes ( content : string , usedTypes : Set < string > ) : void {
909
+ // Reset tracking for this content
910
+ const typeRefs = new Set < string > ( )
911
+
912
+ // Track explicit type references
913
+ const typeMatches = content . matchAll ( / (?: t y p e o f \s + ) ? ( [ A - Z ] \w * (?: < [ ^ > ] + > ) ? ) / g)
914
+ for ( const match of typeMatches ) {
915
+ const fullType = match [ 1 ]
916
+ const baseType = fullType . split ( '<' ) [ 0 ]
917
+
918
+ // Add base type
919
+ typeRefs . add ( baseType )
920
+
921
+ // Extract and track generic parameter types
922
+ const genericMatch = fullType . match ( / < ( .+ ) > / )
923
+ if ( genericMatch ) {
924
+ const genericTypes = genericMatch [ 1 ] . split ( ',' )
925
+ for ( const genericType of genericTypes ) {
926
+ const cleanType = genericType . trim ( ) . split ( / [ < > \s ] / ) [ 0 ]
927
+ if ( / ^ [ A - Z ] / . test ( cleanType ) )
928
+ typeRefs . add ( cleanType )
929
+ }
930
+ }
931
+ }
932
+
933
+ // Track types used in extends clauses
934
+ const extendsMatches = content . matchAll ( / e x t e n d s \s + ( [ A - Z ] \w * (?: < [ ^ > ] + > ) ? ) / g)
935
+ for ( const match of extendsMatches ) {
936
+ const fullType = match [ 1 ]
937
+ const baseType = fullType . split ( '<' ) [ 0 ]
938
+ typeRefs . add ( baseType )
939
+ }
940
+
941
+ // Track types used in type predicates
942
+ const predicateMatches = content . matchAll ( / i s \s + ( [ A - Z ] \w * ) / g)
943
+ for ( const match of predicateMatches ) {
944
+ typeRefs . add ( match [ 1 ] )
945
+ }
946
+
947
+ // Track mapped type references
948
+ const mappedMatches = content . matchAll ( / (?: i n | o f ) \s + ( [ A - Z ] \w * ) / g)
949
+ for ( const match of mappedMatches ) {
950
+ typeRefs . add ( match [ 1 ] )
951
+ }
952
+
953
+ // Add all discovered types to the main set
954
+ typeRefs . forEach ( type => usedTypes . add ( type ) )
902
955
}
903
956
904
957
// Helper functions for line processing
@@ -1024,3 +1077,16 @@ export function formatObjectType(properties: PropertyInfo[]): string {
1024
1077
1025
1078
return `{ ${ formattedProps } }`
1026
1079
}
1080
+
1081
+ /**
1082
+ * Utility function to format type parameters
1083
+ */
1084
+ export function formatTypeParameters ( params : string ) : string {
1085
+ return params
1086
+ . split ( ',' )
1087
+ . map ( ( param ) => {
1088
+ const [ name , constraint ] = param . split ( 'extends' ) . map ( p => p . trim ( ) )
1089
+ return constraint ? `${ name } extends ${ constraint } ` : name
1090
+ } )
1091
+ . join ( ', ' )
1092
+ }
0 commit comments