Skip to content

Commit

Permalink
chore: wip
Browse files Browse the repository at this point in the history
chore: wip

chore: wip
  • Loading branch information
chrisbbreuer committed Oct 28, 2024
1 parent e17362a commit efb6e86
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 80 deletions.
20 changes: 10 additions & 10 deletions fixtures/input/example-0001.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,16 +329,16 @@ export const complexArrays = {
// }
// }

// TODO: Default Type Parameters
// export interface DefaultGeneric<
// T = string,
// K extends keyof any = string,
// V extends Record<K, T> = Record<K, T>
// > {
// key: K
// value: T
// record: V
// }
// Default Type Parameters
export interface DefaultGeneric<
T = string,
K extends keyof any = string,
V extends Record<K, T> = Record<K, T>
> {
key: K
value: T
record: V
}

// TODO: Method Decorators and Metadata
// export const methodDecorator = (
Expand Down
23 changes: 16 additions & 7 deletions fixtures/output/example-0001.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export declare interface AuthResponse {
token: string
expiresIn: number
}
export declare type AuthStatus = 'authenticated' | 'unauthenticated';
export declare type AuthStatus = 'authenticated' | 'unauthenticated'
export declare function authenticate(user: string, password: string): Promise<AuthResponse>;
export declare const defaultHeaders: {
'Content-Type': 'application/json';
Expand All @@ -101,7 +101,7 @@ export declare interface ComplexGeneric<T extends Record<string, unknown>, K ext
transform: (input: T[K]) => string
nested: Array<Partial<T>>
}
export declare type ComplexUnionIntersection =
export declare type ComplexUnionIntersection =
| (User & { role: 'admin' })
| (Product & { category: string })
& {
Expand All @@ -120,9 +120,9 @@ export declare function processData(data: number): number;
export declare function processData(data: boolean): boolean;
export declare function processData<T extends object>(data: T): T;
export declare function processData(data: unknown): unknown;
export declare type EventType = 'click' | 'focus' | 'blur';
export declare type ElementType = 'button' | 'input' | 'form';
export declare type EventHandler = `on${Capitalize<EventType>}${Capitalize<ElementType>}`;
export declare type EventType = 'click' | 'focus' | 'blur'
export declare type ElementType = 'button' | 'input' | 'form'
export declare type EventHandler = `on${Capitalize<EventType>}${Capitalize<ElementType>}`
export declare type RecursiveObject = {
id: string
children?: RecursiveObject[]
Expand All @@ -133,9 +133,18 @@ export declare const complexArrays: {
matrix: Array<Array<1 | 2 | Array<3 | 4 | Array<5 | 6>>> | Array<'a' | 'b' | Array<'c' | 'd'>> | Array<true | Array<false | Array<true>>>>;
tuples: Array<Array<1 | 'string' | true> | Array<'literal' | 42 | false>>;
};
export declare interface DefaultGeneric<
T = string,
K extends keyof any = string,
V extends Record<K, T> = Record<K, T>
> {
key: K
value: T
record: V
}
export declare function complexAsyncGenerator(): any;
export declare function isUser(value: unknown): value is User;
export declare type UserId = string & { readonly __brand: unique symbol };
export declare type UserId = string & { readonly __brand: unique symbol }
export declare type ProductId = number & {
readonly __brand: unique symbol
}
Expand All @@ -158,7 +167,7 @@ export declare type PolymorphicComponent<P = {}> = {
props: { as?: C } & Omit<React.ComponentPropsWithRef<C>, keyof P> & P
): React.ReactElement | null
}
export type DynamicRecord<K extends PropertyKey> = {
export declare type DynamicRecord<K extends PropertyKey> = {
[P in K]: P extends number
? Array<unknown>
: P extends string
Expand Down
83 changes: 20 additions & 63 deletions src/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -906,82 +906,44 @@ function processFunctionDeclaration(
*/
function processInterfaceDeclaration(declaration: string, isExported = true): string {
const lines = declaration.split('\n')
const baseIndent = getIndentation(lines[0])
const memberIndent = `${baseIndent} `

// Process the interface header
const firstLine = lines[0].trim()
const match = firstLine.match(/^(?:export\s+)?interface\s+([^<\s{]+)(<[^{]+>)?/)
if (!match)
return declaration

const [, name, generics = ''] = match
// Only modify the first line to add 'declare' if needed
const firstLine = lines[0]
const prefix = isExported ? 'export declare' : 'declare'

// Process interface members maintaining original indentation
const processedLines = [
`${baseIndent}${prefix} interface ${name}${generics} {`,
]

// Add members with preserved indentation
let seenContent = false
for (let i = 1; i < lines.length - 1; i++) {
const line = lines[i]
const content = line.trim()
if (content) {
seenContent = true
processedLines.push(`${memberIndent}${content}`)
}
}

// If no content was found, add a newline for better formatting
if (!seenContent) {
processedLines.push('')
}
// Replace 'export interface' or 'interface' with the correct prefix
const modifiedFirstLine = firstLine.replace(
/^(\s*)(?:export\s+)?interface/,
`$1${prefix} interface`,
)

processedLines.push(`${baseIndent}}`)
return processedLines.join('\n')
// Return the modified first line with all other lines unchanged
return [modifiedFirstLine, ...lines.slice(1)].join('\n')
}

/**
* Process type declarations
*/
function processTypeDeclaration(declaration: string, isExported = true): string {
const lines = declaration.split('\n')
const baseIndent = getIndentation(lines[0])
const firstLine = lines[0].trim()

// Handle type exports
if (lines[0].includes('type {')) {
// Preserve direct type exports (export type { X })
if (firstLine.startsWith('export type {')) {
return declaration
}

// Extract type name and initial content
const typeMatch = lines[0].match(/^(?:export\s+)?type\s+([^=\s]+)\s*=\s*(.*)/)
if (!typeMatch)
return declaration

const [, name, initialContent] = typeMatch
// Only modify the first line to add 'declare' if needed
const prefix = isExported ? 'export declare' : 'declare'

// If it's a simple single-line type
if (lines.length === 1) {
return `${baseIndent}${prefix} type ${name} = ${initialContent};`
}

// For multi-line types, properly format with line breaks
const processedLines = [`${baseIndent}${prefix} type ${name} = ${initialContent.trim()}`]
const remainingLines = lines.slice(1)

for (const line of remainingLines) {
const trimmed = line.trim()
if (trimmed) {
// Keep original indentation for the line
const lineIndent = getIndentation(line)
processedLines.push(`${lineIndent}${trimmed}`)
}
}
// Replace 'export type' or 'type' with the correct prefix
const modifiedFirstLine = lines[0].replace(
/^(\s*)(?:export\s+)?type(?!\s*\{)/,
`$1${prefix} type`,
)

return processedLines.join('\n')
// Return the modified first line with all other lines unchanged
return [modifiedFirstLine, ...lines.slice(1)].join('\n')
}

function processSourceFile(content: string, state: ProcessingState): void {
Expand Down Expand Up @@ -1447,11 +1409,6 @@ function generateOptimizedImports(state: ImportTrackingState, dtsLines: string[]
return imports.sort()
}

function getIndentation(line: string): string {
const match = line.match(/^(\s+)/)
return match ? match[1] : ''
}

/**
* Normalize type references
*/
Expand Down

0 comments on commit efb6e86

Please sign in to comment.