Skip to content

Commit 9cf9a18

Browse files
committed
chore: wip
1 parent 3ae49be commit 9cf9a18

File tree

1 file changed

+145
-7
lines changed

1 file changed

+145
-7
lines changed

src/extract.ts

Lines changed: 145 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ export interface RegexPatterns {
4040
readonly exportCleanup: RegExp
4141
/** Default export */
4242
readonly defaultExport: RegExp
43+
44+
readonly complexType: RegExp
45+
readonly unionIntersection: RegExp
46+
readonly mappedType: RegExp
47+
readonly conditionalType: RegExp
48+
readonly genericConstraints: RegExp
49+
readonly functionOverload: RegExp
4350
}
4451

4552
/**
@@ -79,6 +86,14 @@ export const REGEX: RegexPatterns = {
7986
// Export patterns
8087
exportCleanup: /^export\s+default\s+/,
8188
defaultExport: /export\s+default\s+/,
89+
90+
// New patterns for complex types
91+
complexType: /type\s+([^=<]+)(?:<[^>]+>)?\s*=\s*([^;]+)/,
92+
unionIntersection: /([^|&]+)(?:\s*[|&]\s*([^|&]+))+/,
93+
mappedType: /\{\s*\[\s*([^\]]+)\s*in\s*([^\]]+)\s*\]:/,
94+
conditionalType: /([^extnds]+)\s+extends\s+([^?]+)\s*\?\s*([^:]+)\s*:\s*([^;]+)/,
95+
genericConstraints: /<([^>]+)>/,
96+
functionOverload: /^(?:export\s+)?(?:declare\s+)?function\s+([^(<\s]+)/,
8297
} as const satisfies RegexPatterns
8398

8499
/**
@@ -416,11 +431,12 @@ export function processImports(imports: string[], usedTypes: Set<string>): strin
416431
}
417432

418433
/**
419-
* Process declarations with type inference
434+
* Process declarations
420435
*/
421436
export function processDeclaration(declaration: string, state: ProcessingState): string {
422437
const trimmed = declaration.trim()
423438

439+
// Handle different declaration types with proper formatting
424440
if (trimmed.startsWith('export const')) {
425441
return processConstDeclaration(trimmed)
426442
}
@@ -451,7 +467,7 @@ export function processDeclaration(declaration: string, state: ProcessingState):
451467

452468
if (trimmed.startsWith('export function') || trimmed.startsWith('export async function')) {
453469
const processed = trimmed.replace(/\basync\s+/, '')
454-
return processFunctionDeclaration(processed, state.usedTypes)
470+
return processFunctionDeclaration(processed, state.usedTypes, true)
455471
}
456472

457473
if (trimmed.startsWith('function') || trimmed.startsWith('async function')) {
@@ -607,6 +623,60 @@ export function processCompleteProperty({ key, content }: { key?: string, conten
607623
return processSimpleValue(key, valueContent)
608624
}
609625

626+
/**
627+
* Process complex type declarations
628+
*/
629+
function processComplexTypeDeclaration(declaration: string): string {
630+
// Handle union and intersection types
631+
if (declaration.includes('|') || declaration.includes('&')) {
632+
const match = declaration.match(REGEX.unionIntersection)
633+
if (match) {
634+
const types = declaration.split(/\s*[|&]\s*/)
635+
return types.join(declaration.includes('|') ? ' | ' : ' & ')
636+
}
637+
}
638+
639+
// Handle mapped types
640+
if (declaration.includes('[') && declaration.includes('in')) {
641+
const match = declaration.match(REGEX.mappedType)
642+
if (match) {
643+
const [, keyType, valueType] = match
644+
return `{ [${keyType} in ${valueType}]: ${processTypeExpression(valueType)} }`
645+
}
646+
}
647+
648+
// Handle conditional types
649+
if (declaration.includes('extends') && declaration.includes('?')) {
650+
const match = declaration.match(REGEX.conditionalType)
651+
if (match) {
652+
const [, condition, constraint, trueType, falseType] = match
653+
return `${condition} extends ${constraint} ? ${trueType} : ${falseType}`
654+
}
655+
}
656+
657+
return declaration
658+
}
659+
660+
/**
661+
* Process type expressions
662+
*/
663+
function processTypeExpression(expression: string): string {
664+
// Handle generics
665+
if (expression.includes('<')) {
666+
const match = expression.match(REGEX.genericConstraints)
667+
if (match) {
668+
const [fullMatch, constraints] = match
669+
const processedConstraints = constraints.split(',').map((c) => {
670+
const [name, constraint] = c.split('extends').map(s => s.trim())
671+
return constraint ? `${name} extends ${constraint}` : name
672+
})
673+
return expression.replace(fullMatch, `<${processedConstraints.join(', ')}>`)
674+
}
675+
}
676+
677+
return expression
678+
}
679+
610680
/**
611681
* Extract nested content between delimiters
612682
*/
@@ -699,6 +769,36 @@ function inferArrayType(value: string): string {
699769
return `Array<${uniqueTypes.join(' | ')}>`
700770
}
701771

772+
/**
773+
* Enhanced type inference for complex cases
774+
*/
775+
export function inferComplexType(value: string): string {
776+
const trimmed = value.trim()
777+
778+
if (trimmed.includes('=>')) {
779+
return inferFunctionType(trimmed)
780+
}
781+
782+
if (trimmed.startsWith('[')) {
783+
return inferArrayType(trimmed)
784+
}
785+
786+
if (trimmed.startsWith('{')) {
787+
return processObjectLiteral(trimmed)
788+
}
789+
790+
if (trimmed.includes('extends')) {
791+
return processComplexTypeDeclaration(trimmed)
792+
}
793+
794+
if (trimmed.includes('|') || trimmed.includes('&')) {
795+
return processComplexTypeDeclaration(trimmed)
796+
}
797+
798+
// Pass through direct type references and primitives
799+
return trimmed
800+
}
801+
702802
/**
703803
* Infer element type with improved type detection
704804
*/
@@ -858,6 +958,14 @@ export function parseObjectLiteral(objStr: string): PropertyInfo[] {
858958
return extractObjectProperties([content])
859959
}
860960

961+
/**
962+
* Process object type literals
963+
*/
964+
function processObjectLiteral(obj: string): string {
965+
const properties = extractObjectProperties([obj])
966+
return formatObjectType(properties)
967+
}
968+
861969
/**
862970
* Process interface declarations
863971
*/
@@ -879,9 +987,13 @@ export function processTypeDeclaration(declaration: string, isExported = true):
879987
const lines = declaration.split('\n')
880988
const firstLine = lines[0]
881989
const typeName = firstLine.split('type')[1].split('=')[0].trim()
882-
const typeBody = firstLine.split('=')[1]?.trim() || lines.slice(1).join('\n').trim().replace(/;$/, '')
990+
const typeBody = firstLine.split('=')[1]?.trim()
991+
|| lines.slice(1).join('\n').trim().replace(/;$/, '')
992+
993+
// Use complex type inference for the type body
994+
const inferredType = inferComplexType(typeBody)
883995

884-
return `${isExported ? 'export ' : ''}declare type ${typeName} = ${typeBody};`
996+
return `${isExported ? 'export ' : ''}declare type ${typeName} = ${inferredType};`
885997
}
886998

887999
/**
@@ -929,11 +1041,14 @@ export function extractFunctionSignature(declaration: string): FunctionSignature
9291041
}
9301042

9311043
/**
932-
* Process function declarations
1044+
* Process function declarations with overloads
1045+
* @param declaration - Function declaration to process
1046+
* @param usedTypes - Set of used types to track
1047+
* @param isExported - Whether the function is exported
9331048
*/
9341049
export function processFunctionDeclaration(
9351050
declaration: string,
936-
usedTypes: Set<string>,
1051+
usedTypes?: Set<string>,
9371052
isExported = true,
9381053
): string {
9391054
const {
@@ -944,7 +1059,10 @@ export function processFunctionDeclaration(
9441059
generics,
9451060
} = extractFunctionSignature(declaration)
9461061

947-
trackUsedTypes(`${generics} ${params} ${returnType}`, usedTypes)
1062+
// Track used types if provided
1063+
if (usedTypes) {
1064+
trackUsedTypes(`${generics} ${params} ${returnType}`, usedTypes)
1065+
}
9481066

9491067
const parts = [
9501068
isExported ? 'export' : '',
@@ -1246,6 +1364,26 @@ function formatSingleDeclaration(declaration: string): string {
12461364
return formatted
12471365
}
12481366

1367+
/**
1368+
* Format function declaration
1369+
*/
1370+
function formatFunctionDeclaration(
1371+
signature: FunctionSignature,
1372+
isExported: boolean,
1373+
): string {
1374+
const {
1375+
name,
1376+
params,
1377+
returnType,
1378+
isAsync,
1379+
generics,
1380+
} = signature
1381+
1382+
return `${isExported ? 'export ' : ''}declare ${isAsync ? 'async ' : ''}function ${name}${
1383+
generics ? `<${generics}>` : ''
1384+
}(${params}): ${returnType};`
1385+
}
1386+
12491387
/**
12501388
* Check if semicolon should be added
12511389
*/

0 commit comments

Comments
 (0)