Skip to content

Commit 764b967

Browse files
committed
chore: wip
1 parent f1a8c70 commit 764b967

File tree

1 file changed

+137
-48
lines changed

1 file changed

+137
-48
lines changed

src/extract.ts

Lines changed: 137 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -532,18 +532,87 @@ function createImportTrackingState(): ImportTrackingState {
532532
}
533533

534534
function indentMultilineType(type: string, baseIndent: string, isLast: boolean): string {
535+
debugLog(undefined, 'indent-multiline', `Processing multiline type with baseIndent="${baseIndent}", isLast=${isLast}`)
536+
debugLog(undefined, 'indent-input', `Input type:\n${type}`)
537+
535538
const lines = type.split('\n')
536-
return lines
537-
.map((line, i) => {
538-
if (i === 0)
539-
return `${baseIndent}${line}`
540-
const trimmed = line.trim()
541-
if (!trimmed)
542-
return ''
543-
return `${baseIndent} ${trimmed}`
544-
})
545-
.filter(Boolean)
546-
.join('\n') + (isLast ? '' : ' |')
539+
debugLog(undefined, 'indent-lines', `Split into ${lines.length} lines`)
540+
541+
if (lines.length === 1) {
542+
const result = `${baseIndent}${type}${isLast ? '' : ' |'}`
543+
debugLog(undefined, 'indent-single', `Single line result: ${result}`)
544+
return result
545+
}
546+
547+
// Initialize bracket stack with additional context
548+
interface BracketInfo {
549+
char: string
550+
indent: string
551+
isArray: boolean // Track if this is an Array type bracket
552+
}
553+
const bracketStack: BracketInfo[] = []
554+
debugLog(undefined, 'indent-stack', 'Initializing bracket stack')
555+
556+
const formattedLines = lines.map((line, i) => {
557+
const trimmed = line.trim()
558+
if (!trimmed) {
559+
debugLog(undefined, 'indent-empty', `Empty line at index ${i}`)
560+
return ''
561+
}
562+
563+
// Track Array type specifically
564+
const isArrayStart = trimmed.startsWith('Array<')
565+
const openBrackets = (trimmed.match(/[{<[]/g) || [])
566+
const closeBrackets = (trimmed.match(/[}\]>]/g) || [])
567+
568+
debugLog(undefined, 'indent-brackets', `Line ${i}: opens=${openBrackets.length}, closes=${closeBrackets.length}, isArray=${isArrayStart}, content="${trimmed}"`)
569+
570+
let currentIndent = baseIndent
571+
if (i > 0 || closeBrackets.length > 0) {
572+
if (closeBrackets.length > 0 && bracketStack.length > 0) {
573+
const lastBracket = bracketStack[bracketStack.length - 1]
574+
// For Array closing bracket, use base indent
575+
if (lastBracket.isArray) {
576+
currentIndent = baseIndent
577+
debugLog(undefined, 'indent-close-array', `Using base indent for Array closing: "${currentIndent}"`)
578+
}
579+
else {
580+
currentIndent = lastBracket.indent
581+
debugLog(undefined, 'indent-close', `Using stack indent for closing: "${currentIndent}"`)
582+
}
583+
bracketStack.pop()
584+
}
585+
else {
586+
currentIndent = baseIndent + ' '.repeat(bracketStack.length)
587+
debugLog(undefined, 'indent-content', `Using content indent at depth ${bracketStack.length}: "${currentIndent}"`)
588+
}
589+
}
590+
591+
// Handle opening brackets with Array context
592+
if (openBrackets.length > 0) {
593+
openBrackets.forEach((bracket) => {
594+
const isArrayBracket = trimmed.startsWith('Array') && bracket === '<'
595+
bracketStack.push({
596+
char: bracket,
597+
indent: currentIndent,
598+
isArray: isArrayBracket,
599+
})
600+
debugLog(undefined, 'indent-open', `Pushed bracket "${bracket}" with indent "${currentIndent}", isArray=${isArrayBracket}`)
601+
})
602+
}
603+
604+
const formattedLine = `${currentIndent}${trimmed}`
605+
debugLog(undefined, 'indent-line', `Formatted line ${i}: "${formattedLine}"`)
606+
607+
if (!isLast && i === lines.length - 1 && !formattedLine.endsWith(' |')) {
608+
return `${formattedLine} |`
609+
}
610+
return formattedLine
611+
}).filter(Boolean)
612+
613+
const result = formattedLines.join('\n')
614+
debugLog(undefined, 'indent-result', `Final multiline result:\n${result}`)
615+
return result
547616
}
548617

549618
function inferValueType(value: string): string {
@@ -576,83 +645,103 @@ function inferValueType(value: string): string {
576645
* Infer array type from array literal with support for nested arrays and mixed elements
577646
*/
578647
function inferArrayType(value: string, state?: ProcessingState, indentLevel = 0): string {
579-
debugLog(state, 'infer-array', `Inferring array type for: ${value}`)
648+
debugLog(state, 'infer-array-start', `Starting array inference at level ${indentLevel}`)
649+
debugLog(state, 'infer-array-value', `Input value:\n${value}`)
650+
580651
const content = value.slice(1, -1).trim()
581-
if (!content)
652+
if (!content) {
653+
debugLog(state, 'infer-array-empty', 'Empty array content')
582654
return 'unknown[]'
655+
}
583656

584657
const baseIndent = ' '.repeat(indentLevel)
585658
const elementIndent = ' '.repeat(indentLevel + 1)
659+
debugLog(state, 'infer-array-indent', `Base indent="${baseIndent}", Element indent="${elementIndent}"`)
586660

587-
// Handle const assertions first
588661
const elements = splitArrayElements(content, state)
662+
debugLog(state, 'array-split', `Elements after split: ${JSON.stringify(elements)}`)
663+
589664
const allConstTuples = elements.every(el => el.trim().endsWith('as const'))
665+
debugLog(state, 'array-tuples', `All const tuples: ${allConstTuples}`)
590666

591667
if (allConstTuples) {
592668
const tuples = elements.map((el) => {
593669
const tupleContent = el.slice(0, el.indexOf('as const')).trim()
594670
return inferConstArrayType(tupleContent, state)
595671
})
672+
debugLog(state, 'const-tuple', `Tuples inferred: ${tuples}`)
596673
return `Array<${tuples.join(' | ')}>`
597674
}
598675

599-
// Process each element
600-
const elementTypes = elements.map((element) => {
676+
const elementTypes = elements.map((element, index) => {
601677
const trimmed = element.trim()
678+
debugLog(state, 'element-processing', `Processing element ${index}: "${trimmed}"`)
602679

603-
// Handle nested arrays
680+
let type: string
604681
if (trimmed.startsWith('[')) {
605-
return inferArrayType(trimmed, state, indentLevel + 1)
682+
debugLog(state, 'element-nested', `Found nested array at index ${index}`)
683+
type = inferArrayType(trimmed, state, indentLevel + 1)
606684
}
607-
608-
// Handle objects with proper indentation
609-
if (trimmed.startsWith('{')) {
610-
return inferComplexObjectType(trimmed, state, indentLevel + 1)
685+
else if (trimmed.startsWith('{')) {
686+
debugLog(state, 'element-object', `Found object at index ${index}`)
687+
type = inferComplexObjectType(trimmed, state, indentLevel + 1)
611688
}
612-
613-
// Handle function expressions - always parenthesize
614-
if (trimmed.includes('=>') || trimmed.includes('function')) {
689+
else if (trimmed.includes('=>') || trimmed.includes('function')) {
690+
debugLog(state, 'element-function', `Found function at index ${index}`)
615691
const funcType = extractFunctionType(trimmed, state)
616-
return funcType ? `(${funcType})` : '((...args: any[]) => unknown)'
692+
type = funcType ? `(${funcType})` : '((...args: any[]) => unknown)'
617693
}
618-
619-
// Handle method/function references
620-
if (trimmed.includes('.') || /\w+\(/.test(trimmed)) {
621-
return 'unknown'
694+
else {
695+
type = normalizeTypeReference(trimmed)
622696
}
623697

624-
// Handle other literals
625-
return normalizeTypeReference(trimmed)
698+
debugLog(state, 'element-type', `Element ${index} type: "${type}"`)
699+
return type
626700
})
627701

628-
// Format the array type with proper indentation
629702
const types = elementTypes.filter(Boolean)
630-
if (types.length === 0)
631-
return 'unknown[]'
703+
debugLog(state, 'types', `Filtered types: ${types.length}`)
632704

633-
// Check if we need multiline formatting
634705
const needsMultiline = types.some(type =>
635-
type.includes('\n')
636-
|| type.includes('{')
637-
|| type.length > 40
638-
|| types.join(' | ').length > 60,
706+
type.includes('\n') || type.includes('{') || type.length > 40 || types.join(' | ').length > 60,
639707
)
708+
debugLog(state, 'multiline-check', `Needs multiline: ${needsMultiline}, Reason: ${
709+
types.find(type => type.includes('\n'))
710+
? 'contains newline'
711+
: types.find(type => type.includes('{'))
712+
? 'contains object'
713+
: types.find(type => type.length > 40)
714+
? 'type too long'
715+
: types.join(' | ').length > 60 ? 'combined types too long' : 'none'
716+
}`)
640717

641718
if (needsMultiline) {
719+
debugLog(state, 'multiline-start', `Starting multiline formatting with ${types.length} types`)
720+
721+
// Construct parts separately for better control
642722
const formattedTypes = types.map((type, index) => {
643723
const isLast = index === types.length - 1
644-
// For types that contain newlines
645-
if (type.includes('\n')) {
646-
return indentMultilineType(type, elementIndent, isLast)
647-
}
648-
// For single-line types
649-
return `${elementIndent}${type}${isLast ? '' : ' |'}`
724+
debugLog(state, 'type-formatting', `Formatting type ${index}, isLast: ${isLast}`)
725+
const formatted = indentMultilineType(type, elementIndent, isLast)
726+
debugLog(state, 'type-formatted', `Type ${index} formatted result:\n${formatted}`)
727+
return formatted
650728
})
651729

652-
return `Array<\n${formattedTypes.join('\n')}\n${baseIndent}>`
730+
// Build multiline array with controlled indentation
731+
const typeContent = formattedTypes.join('\n')
732+
const result = [
733+
`${baseIndent}Array<`,
734+
typeContent,
735+
`${baseIndent}>`,
736+
].join('\n')
737+
738+
debugLog(state, 'multiline-result', `Final multiline result:\n${result}`)
739+
return result
653740
}
654741

655-
return `Array<${types.join(' | ')}>`
742+
const singleLineResult = `Array<${types.join(' | ')}>`
743+
debugLog(state, 'single-line-array', `Single-line array type: ${singleLineResult}`)
744+
return singleLineResult
656745
}
657746

658747
/**

0 commit comments

Comments
 (0)