From 3cc76b536af9deec534cf90bb25d94be6573c98a Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 20 Oct 2024 12:32:20 +0200 Subject: [PATCH] chore: extract adjustments --- src/extract.ts | 102 ++++++++++++++++++++----------------------------- 1 file changed, 42 insertions(+), 60 deletions(-) diff --git a/src/extract.ts b/src/extract.ts index ebf0c69..7c2d187 100644 --- a/src/extract.ts +++ b/src/extract.ts @@ -8,20 +8,25 @@ export async function extractTypeFromSource(filePath: string): Promise { const importMap = new Map>() // Handle re-exports - const reExportRegex = /export\s*(?:\*|\{[^}]*\})\s*from\s*['"][^'"]+['"]/g - const reExports = fileContent.match(reExportRegex) || [] - declarations += `${reExports.join('\n')}\n` + const reExportRegex = /export\s*(?:\*|\{[^}]*\})\s*from\s*['"]([^'"]+)['"]/g + let reExportMatch + + while ((reExportMatch = reExportRegex.exec(fileContent)) !== null) { + declarations += `${reExportMatch[0]}\n` + } // Capture all imports const importRegex = /import\s+(?:(type)\s+)?(?:(\{[^}]+\})|(\w+))(?:\s*,\s*(?:(\{[^}]+\})|(\w+)))?\s+from\s+['"]([^'"]+)['"]/g - const imports = Array.from(fileContent.matchAll(importRegex)) - - imports.forEach(([, isTypeImport, namedImports1, defaultImport1, namedImports2, defaultImport2, from]) => { + let importMatch + // eslint-disable-next-line no-cond-assign + while ((importMatch = importRegex.exec(fileContent)) !== null) { + // eslint-disable-next-line unused-imports/no-unused-vars + const [, isTypeImport, namedImports1, defaultImport1, namedImports2, defaultImport2, from] = importMatch if (!importMap.has(from)) { importMap.set(from, new Set()) } - const processImports = (imports: string | undefined, _isType: boolean) => { + const processImports = (imports: string | undefined) => { if (imports) { const types = imports.replace(/[{}]/g, '').split(',').map((t) => { const [name, alias] = t.split(' as ').map(s => s.trim()) @@ -33,70 +38,47 @@ export async function extractTypeFromSource(filePath: string): Promise { } } - processImports(namedImports1, !!isTypeImport) - processImports(namedImports2, !!isTypeImport) + processImports(namedImports1) + processImports(namedImports2) + if (defaultImport1) importMap.get(from)!.add(defaultImport1) if (defaultImport2) importMap.get(from)!.add(defaultImport2) - }) + } // Handle exports with comments - const exportLines = fileContent.split('\n') - let i = 0 - while (i < exportLines.length) { - let comment = '' - let exportStatement = '' - - // Collect comment - if (exportLines[i].trim().startsWith('/**')) { - while (i < exportLines.length && !exportLines[i].includes('*/')) { - comment += `${exportLines[i]}\n` - i++ + const exportRegex = /(\/\*\*[\s\S]*?\*\/\s*)?(export\s+(?:async\s+)?(?:function|const|let|var|class|interface|type)\s+\w[\s\S]*?)(?=\n\s*(?:\/\*\*|export|$))/g + let match + // eslint-disable-next-line no-cond-assign + while ((match = exportRegex.exec(fileContent)) !== null) { + const [, comment, exportStatement] = match + const formattedComment = comment ? formatComment(comment.trim()) : '' + let formattedExport = exportStatement.trim() + + if (formattedExport.startsWith('export function') || formattedExport.startsWith('export async function')) { + formattedExport = formattedExport.replace(/^export\s+(async\s+)?function/, 'export declare function') + const functionSignature = formattedExport.match(/^.*?\)/) + if (functionSignature) { + let params = functionSignature[0].slice(functionSignature[0].indexOf('(') + 1, -1) + params = params.replace(/\s*=[^,)]+/g, '') // Remove default values + const returnType = formattedExport.match(/\):\s*([^{]+)/) + formattedExport = `export declare function ${formattedExport.split('function')[1].split('(')[0].trim()}(${params})${returnType ? `: ${returnType[1].trim()}` : ''};` } - comment += `${exportLines[i]}\n` - i++ } - - // Collect export statement - if (i < exportLines.length && exportLines[i].trim().startsWith('export')) { - exportStatement = exportLines[i] - i++ - while (i < exportLines.length && !exportLines[i].trim().startsWith('export') && !exportLines[i].trim().startsWith('/**')) { - exportStatement += `\n${exportLines[i]}` - i++ - } + else if (formattedExport.startsWith('export const') || formattedExport.startsWith('export let') || formattedExport.startsWith('export var')) { + formattedExport = formattedExport.replace(/^export\s+(const|let|var)/, 'export declare $1') + formattedExport = `${formattedExport.split('=')[0].trim()};` } - if (exportStatement) { - const formattedComment = comment ? formatComment(comment.trim()) : '' - let formattedExport = exportStatement.trim() - - if (formattedExport.startsWith('export function') || formattedExport.startsWith('export async function')) { - formattedExport = formattedExport.replace(/^export\s+(async\s+)?function/, 'export declare function') - const functionSignature = formattedExport.match(/^.*?\)/) - if (functionSignature) { - let params = functionSignature[0].slice(functionSignature[0].indexOf('(') + 1, -1) - params = params.replace(/\s*=[^,)]+/g, '') // Remove default values - const returnType = formattedExport.match(/\):\s*([^{]+)/) - formattedExport = `export declare function ${formattedExport.split('function')[1].split('(')[0].trim()}(${params})${returnType ? `: ${returnType[1].trim()}` : ''};` - } - } - else if (formattedExport.startsWith('export const') || formattedExport.startsWith('export let') || formattedExport.startsWith('export var')) { - formattedExport = formattedExport.replace(/^export\s+(const|let|var)/, 'export declare $1') - formattedExport = `${formattedExport.split('=')[0].trim()};` - } - - declarations += `${formattedComment}\n${formattedExport}\n\n` - - // Add types used in the export to usedTypes - const typeRegex = /\b([A-Z]\w+)(?:<[^>]*>)?/g - const types = Array.from(formattedExport.matchAll(typeRegex)) - types.forEach(([, type]) => usedTypes.add(type)) - } + declarations += `${formattedComment}\n${formattedExport}\n\n` - if (!exportStatement && !comment) { - i++ + // Add types used in the export to usedTypes + const typeRegex = /\b([A-Z]\w+)(?:<[^>]*>)?/g + let typeMatch + // eslint-disable-next-line no-cond-assign + while ((typeMatch = typeRegex.exec(formattedExport)) !== null) { + usedTypes.add(typeMatch[1]) } }