Skip to content

Commit

Permalink
chore: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbbreuer committed Oct 18, 2024
1 parent fc7283c commit 1aa14fd
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 34 deletions.
1 change: 1 addition & 0 deletions bin/cli.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { DtsGenerationConfig, DtsGenerationOption } from '../src/types'
import { resolve } from 'node:path'
import process from 'node:process'
import { CAC } from '@stacksjs/cli'
import { version } from '../package.json'
import { generate } from '../src/generate'
Expand Down
92 changes: 58 additions & 34 deletions src/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,20 @@ 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
let reExportMatch
while ((reExportMatch = reExportRegex.exec(fileContent)) !== null) {
declarations += `${reExportMatch[0]}\n`
}
const reExportRegex = /export\s*(?:\*|\{[^}]*\})\s*from\s*['"][^'"]+['"]/g
const reExports = fileContent.match(reExportRegex) || []
declarations += `${reExports.join('\n')}\n`

// Capture all imports
const importRegex = /import\s+(?:(type)\s+)?(?:(\{[^}]+\})|(\w+))(?:\s*,\s*(?:(\{[^}]+\})|(\w+)))?\s+from\s+['"]([^'"]+)['"]/g
let importMatch
while ((importMatch = importRegex.exec(fileContent)) !== null) {
const [, isTypeImport, namedImports1, defaultImport1, namedImports2, defaultImport2, from] = importMatch
const imports = Array.from(fileContent.matchAll(importRegex))

imports.forEach(([, isTypeImport, namedImports1, defaultImport1, namedImports2, defaultImport2, from]) => {
if (!importMap.has(from)) {
importMap.set(from, new Set())
}

const processImports = (imports: string | undefined, isType: boolean) => {
const processImports = (imports: string | undefined, _isType: boolean) => {
if (imports) {
const types = imports.replace(/[{}]/g, '').split(',').map((t) => {
const [name, alias] = t.split(' as ').map(s => s.trim())
Expand All @@ -41,38 +39,64 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
importMap.get(from)!.add(defaultImport1)
if (defaultImport2)
importMap.get(from)!.add(defaultImport2)
}
})

// Handle exports with comments
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
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()}` : ''};`
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++
}
comment += `${exportLines[i]}\n`
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()};`

// 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++
}
}

declarations += `${formattedComment}\n${formattedExport}\n\n`
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))
}

// Add types used in the export to usedTypes
const typeRegex = /\b([A-Z]\w+)(?:<[^>]*>)?/g
let typeMatch
while ((typeMatch = typeRegex.exec(formattedExport)) !== null) {
usedTypes.add(typeMatch[1])
if (!exportStatement && !comment) {
i++
}
}

Expand Down
1 change: 1 addition & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { DtsGenerationConfig } from './types'
import { readdir, readFile } from 'node:fs/promises'
import { extname, join } from 'node:path'
import process from 'node:process'
import { config } from './config'

export async function writeToFile(filePath: string, content: string): Promise<void> {
Expand Down

0 comments on commit 1aa14fd

Please # to comment.