@@ -179,7 +179,7 @@ export interface FunctionSignature {
179179 name : string
180180 params : string
181181 returnType : string
182- isAsync : boolean
182+ // isAsync: boolean
183183 generics : string
184184}
185185
@@ -286,6 +286,72 @@ export function extractDtsTypes(sourceCode: string): string {
286286 return formatOutput ( state )
287287}
288288
289+ /**
290+ * Extracts a substring that contains balanced opening and closing symbols, handling nested structures.
291+ * @param text - The text to extract from.
292+ * @param openSymbol - The opening symbol (e.g., '<', '(', '{').
293+ * @param closeSymbol - The closing symbol (e.g., '>', ')', '}').
294+ * @returns An object containing the content and the rest of the string.
295+ */
296+ function extractBalancedSymbols ( text : string , openSymbol : string , closeSymbol : string ) : { content : string , rest : string } | null {
297+ if ( ! text . startsWith ( openSymbol ) ) {
298+ return null
299+ }
300+
301+ const stack : string [ ] = [ ]
302+ let inString = false
303+ let stringChar = ''
304+ for ( let i = 0 ; i < text . length ; i ++ ) {
305+ const char = text [ i ]
306+ const prevChar = text [ i - 1 ]
307+
308+ // Handle string literals
309+ if ( ( char === '"' || char === '\'' || char === '`' ) && prevChar !== '\\' ) {
310+ if ( ! inString ) {
311+ inString = true
312+ stringChar = char
313+ }
314+ else if ( char === stringChar ) {
315+ inString = false
316+ }
317+ }
318+
319+ if ( ! inString ) {
320+ if ( char === openSymbol ) {
321+ stack . push ( char )
322+ }
323+ else if ( char === closeSymbol ) {
324+ if ( stack . length === 0 ) {
325+ // Unbalanced closing symbol
326+ return null
327+ }
328+ stack . pop ( )
329+ if ( stack . length === 0 ) {
330+ // All symbols balanced, return substring
331+ return {
332+ content : text . slice ( 0 , i + 1 ) ,
333+ rest : text . slice ( i + 1 ) . trim ( ) ,
334+ }
335+ }
336+ }
337+ }
338+ }
339+
340+ return null // Unbalanced symbols
341+ }
342+
343+ function extractFunctionName ( declaration : string ) : { name : string , rest : string } {
344+ const match = declaration . match ( / ^ ( [ a - z _ $ ] [ \w $ ] * ) / i)
345+ if ( match ) {
346+ const name = match [ 1 ]
347+ const rest = declaration . slice ( match [ 0 ] . length ) . trim ( )
348+ return { name, rest }
349+ }
350+ else {
351+ return { name : '' , rest : declaration }
352+ }
353+ }
354+
289355/**
290356 * Main line processing function
291357 * Handles different types of content and maintains state
@@ -1079,6 +1145,8 @@ function isDeclarationStart(line: string): boolean {
10791145 || line . startsWith ( 'declare ' )
10801146 // Handle possible export combinations
10811147 || / ^ e x p o r t \s + ( i n t e r f a c e | t y p e | c o n s t | f u n c t i o n | a s y n c \s + f u n c t i o n ) / . test ( line )
1148+ // Handle 'export async function'
1149+ || line . startsWith ( 'export async function' )
10821150 )
10831151}
10841152
@@ -1531,80 +1599,89 @@ function netBraceCount(line: string): number {
15311599}
15321600
15331601/**
1534- * Extract complete function signature
1602+ * Extract complete function signature using regex
15351603 */
1536- export function extractFunctionSignature ( declaration : string ) : FunctionSignature {
1604+ function extractFunctionSignature ( declaration : string ) : FunctionSignature {
15371605 // Remove comments from the declaration
15381606 const cleanDeclaration = removeLeadingComments ( declaration ) . trim ( )
15391607
1540- // Check if the function is async
1541- const isAsync = / ^ a s y n c \s + / . test ( cleanDeclaration )
1542-
1543- // Remove 'export' and 'async' keywords
1544- let declarationWithoutKeywords = cleanDeclaration
1545- . replace ( / ^ e x p o r t \s + / , '' )
1546- . replace ( / ^ a s y n c \s + / , '' )
1547- . trim ( )
1548-
1549- // Remove 'function' keyword
1550- declarationWithoutKeywords = declarationWithoutKeywords . replace ( / ^ f u n c t i o n \s + / , '' ) . trim ( )
1551-
1552- // Extract the function name
1553- const nameMatch = declarationWithoutKeywords . match ( / ^ ( [ a - z _ $ ] [ \w $ ] * ) / i)
1554- const name = nameMatch ? nameMatch [ 1 ] : ''
1608+ // Remove leading 'export', 'async', 'function' keywords
1609+ const withoutKeywords = cleanDeclaration . replace ( / ^ \s * ( e x p o r t \s + ) ? ( a s y n c \s + ) ? f u n c t i o n \s + / , '' ) . trim ( )
15551610
1611+ // Extract function name
1612+ const { name, rest : afterName } = extractFunctionName ( withoutKeywords )
15561613 if ( ! name ) {
15571614 console . error ( 'Function name could not be extracted from declaration:' , declaration )
15581615 return {
15591616 name : '' ,
15601617 params : '' ,
15611618 returnType : 'void' ,
1562- isAsync : false ,
15631619 generics : '' ,
15641620 }
15651621 }
15661622
1567- // Remove the function name from the declaration
1568- let afterName = declarationWithoutKeywords . slice ( name . length ) . trim ( )
1623+ let rest = afterName
15691624
1570- // Extract generics if present
1625+ // Extract generics
15711626 let generics = ''
1572- const genericsMatch = afterName . match ( / ^ < [ ^ > ] + > / )
1573- if ( genericsMatch ) {
1574- generics = genericsMatch [ 0 ]
1575- afterName = afterName . slice ( generics . length ) . trim ( )
1627+ if ( rest . startsWith ( '<' ) ) {
1628+ const genericsResult = extractBalancedSymbols ( rest , '<' , '>' )
1629+ if ( genericsResult ) {
1630+ generics = genericsResult . content
1631+ rest = genericsResult . rest . trim ( )
1632+ }
1633+ else {
1634+ console . error ( 'Generics could not be extracted from declaration:' , declaration )
1635+ }
15761636 }
15771637
15781638 // Extract parameters
1579- const paramsMatch = afterName . match ( / ^ \( ( [ ^ ) ] * ) \) / )
15801639 let params = ''
1581- if ( paramsMatch ) {
1582- params = paramsMatch [ 1 ] . trim ( )
1583- afterName = afterName . slice ( paramsMatch [ 0 ] . length ) . trim ( )
1640+ if ( rest . startsWith ( '(' ) ) {
1641+ const paramsResult = extractBalancedSymbols ( rest , '(' , ')' )
1642+ if ( paramsResult ) {
1643+ params = paramsResult . content . slice ( 1 , - 1 ) . trim ( ) // Remove the surrounding parentheses
1644+ rest = paramsResult . rest . trim ( )
1645+ }
1646+ else {
1647+ console . error ( 'Parameters could not be extracted from declaration:' , declaration )
1648+ return {
1649+ name,
1650+ params : '' ,
1651+ returnType : 'void' ,
1652+ generics,
1653+ }
1654+ }
1655+ }
1656+ else {
1657+ console . error ( 'Parameters could not be extracted from declaration:' , declaration )
1658+ return {
1659+ name,
1660+ params : '' ,
1661+ returnType : 'void' ,
1662+ generics,
1663+ }
15841664 }
1585-
1586- params = cleanParameters ( params )
15871665
15881666 // Extract return type
1589- const returnTypeMatch = afterName . match ( / ^ : \s * ( [ ^ ; { ] + ) / )
1590- let returnType = returnTypeMatch ? returnTypeMatch [ 1 ] . trim ( ) : 'void'
1591-
1592- returnType = normalizeType ( returnType )
1667+ let returnType = 'void'
1668+ if ( rest . startsWith ( ':' ) ) {
1669+ const match = rest . match ( / ^ : \s * ( [ ^ { ] + ) / )
1670+ if ( match ) {
1671+ returnType = match [ 1 ] . trim ( )
1672+ }
1673+ }
15931674
15941675 return {
15951676 name,
15961677 params,
1597- returnType,
1598- isAsync,
1678+ returnType : normalizeType ( returnType ) ,
15991679 generics,
16001680 }
16011681}
16021682
16031683/**
16041684 * Process function declarations with overloads
1605- * @param declaration - Function declaration to process
1606- * @param usedTypes - Set of used types to track
1607- * @param isExported - Whether the function is exported
16081685 */
16091686export function processFunctionDeclaration (
16101687 declaration : string ,
@@ -1614,16 +1691,18 @@ export function processFunctionDeclaration(
16141691 // Remove comments from the declaration for parsing
16151692 const cleanDeclaration = removeLeadingComments ( declaration ) . trim ( )
16161693
1617- // Strip out the function body by removing everything after the parameter list and return type
1618- const functionSignature = cleanDeclaration . replace ( / \{ [ \s \S ] * $ / , '' ) . trim ( )
1619-
16201694 const {
16211695 name,
16221696 params,
16231697 returnType,
1624- isAsync,
16251698 generics,
1626- } = extractFunctionSignature ( functionSignature )
1699+ } = extractFunctionSignature ( cleanDeclaration )
1700+
1701+ // Add logs to verify extracted components
1702+ console . log ( 'Function Name:' , name )
1703+ console . log ( 'Generics:' , generics )
1704+ console . log ( 'Parameters:' , params )
1705+ console . log ( 'Return Type:' , returnType )
16271706
16281707 // Track used types if provided
16291708 if ( usedTypes ) {
@@ -1645,6 +1724,7 @@ export function processFunctionDeclaration(
16451724 return parts
16461725 . filter ( Boolean )
16471726 . join ( ' ' )
1727+ // Include ':' in the character classes to handle spacing around colons
16481728 . replace ( / \s + ( [ < > ( ) , ; : ] ) / g, '$1' )
16491729 . replace ( / ( [ < > ( ) , ; : ] ) \s + / g, '$1 ' )
16501730 . replace ( / \s { 2 , } / g, ' ' )
@@ -1662,42 +1742,7 @@ function cleanDeclaration(text: string): string {
16621742 * Clean and normalize parameters
16631743 */
16641744export function cleanParameters ( params : string ) : string {
1665- if ( ! params . trim ( ) )
1666- return ''
1667-
1668- return params
1669- . replace ( REGEX . destructuredParams , ( _ , props , type ) => {
1670- const typeName = normalizeType ( type . trim ( ) )
1671- return `options: ${ typeName } `
1672- } )
1673- . replace ( / \s * ( [ , : ] ) \s * / g, '$1 ' )
1674- . replace ( / , ( \S ) / g, ', $1' )
1675- . replace ( / \s * \? \s * : / g, '?: ' )
1676- . replace ( / \s * ( [ < [ \] > ] ) \s * / g, '$1' )
1677- . replace ( / \s { 2 , } / g, ' ' )
1678- . trim ( )
1679- }
1680-
1681- function cleanImports ( imports : string [ ] ) : string [ ] {
1682- const seen = new Set < string > ( )
1683- return imports
1684- . filter ( ( imp ) => {
1685- const normalized = imp . trim ( )
1686- if ( seen . has ( normalized ) )
1687- return false
1688- seen . add ( normalized )
1689- return true
1690- } )
1691- . sort ( ( a , b ) => {
1692- // Sort type imports before regular imports
1693- const aIsType = a . includes ( 'import type' )
1694- const bIsType = b . includes ( 'import type' )
1695- if ( aIsType && ! bIsType )
1696- return - 1
1697- if ( ! aIsType && bIsType )
1698- return 1
1699- return a . localeCompare ( b )
1700- } )
1745+ return params . trim ( )
17011746}
17021747
17031748/**
0 commit comments