Skip to content

Commit

Permalink
chore: extract adjustments
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbbreuer committed Oct 20, 2024
1 parent 41a035a commit 3cc76b5
Showing 1 changed file with 42 additions and 60 deletions.
102 changes: 42 additions & 60 deletions src/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,25 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
const importMap = new Map<string, Set<string>>()

// 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())
Expand All @@ -33,70 +38,47 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
}
}

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])
}
}

Expand Down

0 comments on commit 3cc76b5

Please sign in to comment.