Skip to content

Commit 3fbbdd5

Browse files
committed
chore: wip
chore: wip
1 parent 1e6a590 commit 3fbbdd5

File tree

3 files changed

+115
-41
lines changed

3 files changed

+115
-41
lines changed

fixtures/input/variable.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -156,17 +156,29 @@ export const complexObject = {
156156
}
157157
}
158158

159-
// TODO: Method Decorators and Metadata
160-
// export const methodDecorator = (
161-
// target: any,
162-
// propertyKey: string,
163-
// descriptor: PropertyDescriptor
164-
// ) => {
165-
// return {
166-
// ...descriptor,
167-
// enumerable: true,
168-
// }
169-
// }
159+
// Method Decorators and Metadata (declares as unknown, because it should rely on explicit type)
160+
export const methodDecorator = (
161+
target: any,
162+
propertyKey: string,
163+
descriptor: PropertyDescriptor
164+
) => {
165+
return {
166+
...descriptor,
167+
enumerable: true,
168+
}
169+
}
170+
171+
// declares as SomeType
172+
export const methodDecoratorWithExplicitType = (
173+
target: any,
174+
propertyKey: string,
175+
descriptor: PropertyDescriptor
176+
): SomeType => {
177+
return {
178+
...descriptor,
179+
enumerable: true,
180+
}
181+
}
170182

171183
// TODO: Complex Constants with Type Inference
172184
// export const CONFIG_MAP = {

fixtures/output/variable.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,5 @@ export declare const complexObject: {
9999
}
100100
}
101101
};
102+
export declare const methodDecorator: (...args: any[]) => unknown;
103+
export declare const methodDecoratorWithExplicitType: SomeType;

src/extract.ts

Lines changed: 90 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ interface ProcessedMethod {
66
signature: string
77
}
88

9+
function cleanDeclaration(declaration: string): string {
10+
return declaration
11+
.replace(/\r\n/g, '\n') // Normalize line endings
12+
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove multi-line comments
13+
.replace(/\/\/.*/g, '') // Remove single-line comments
14+
.replace(/\s+/g, ' ') // Normalize whitespace
15+
.trim()
16+
}
17+
918
function cleanParameterTypes(params: string): string {
1019
if (!params.trim())
1120
return ''
@@ -573,25 +582,31 @@ function indentMultilineType(type: string, baseIndent: string, isLast: boolean):
573582
}
574583

575584
function inferValueType(value: string): string {
576-
value = value.trim()
585+
const normalizedValue = value.split('\n').map(line => line.trim()).join(' ')
577586

578-
// For string literals, return the literal itself as the type
579-
if (/^['"`].*['"`]$/.test(value)) {
580-
return value
587+
// For string literals
588+
if (/^['"`].*['"`]$/.test(normalizedValue)) {
589+
return normalizedValue
581590
}
582591

583592
// For numeric literals
584-
if (!Number.isNaN(Number(value))) {
585-
return value
593+
if (!Number.isNaN(Number(normalizedValue))) {
594+
return normalizedValue
586595
}
587596

588597
// For boolean literals
589-
if (value === 'true' || value === 'false') {
590-
return value
598+
if (normalizedValue === 'true' || normalizedValue === 'false') {
599+
return normalizedValue
600+
}
601+
602+
// Check for explicit return type annotations with better multiline handling
603+
const returnTypeMatch = normalizedValue.match(/\([^)]*\)\s*:\s*([^=>{]+)/)
604+
if (returnTypeMatch) {
605+
return returnTypeMatch[1].trim()
591606
}
592607

593608
// For function expressions
594-
if (value.includes('=>')) {
609+
if (normalizedValue.includes('=>')) {
595610
return '(...args: any[]) => unknown'
596611
}
597612

@@ -869,7 +884,7 @@ export function isDefaultExport(line: string): boolean {
869884
return line.trim().startsWith('export default')
870885
}
871886

872-
export function isDeclarationStart(line: string): boolean {
887+
function isDeclarationStart(line: string): boolean {
873888
return (
874889
line.startsWith('export ')
875890
|| line.startsWith('interface ')
@@ -953,10 +968,10 @@ export function processBlock(lines: string[], comments: string[], state: Process
953968

954969
// Keep track of declaration for debugging
955970
state.debug.currentProcessing = cleanDeclaration
956-
debugLog(state, 'processing', `Processing block: ${cleanDeclaration.substring(0, 100)}...`)
971+
debugLog(state, 'block-processing', `Full block content:\n${cleanDeclaration}`)
957972

958973
if (!cleanDeclaration) {
959-
debugLog(state, 'processing', 'Empty declaration block')
974+
debugLog(state, 'block-processing', 'Empty declaration block')
960975
return
961976
}
962977

@@ -973,7 +988,11 @@ export function processBlock(lines: string[], comments: string[], state: Process
973988
if (cleanDeclaration.startsWith('const') || cleanDeclaration.startsWith('let') || cleanDeclaration.startsWith('var')
974989
|| cleanDeclaration.startsWith('export const') || cleanDeclaration.startsWith('export let') || cleanDeclaration.startsWith('export var')) {
975990
const isExported = cleanDeclaration.startsWith('export')
976-
state.dtsLines.push(processVariable(declarationText, isExported, state))
991+
992+
// For variable declarations, ensure we have the complete declaration
993+
const fullDeclaration = lines.join('\n')
994+
debugLog(state, 'block-processing', `Processing variable declaration:\n${fullDeclaration}`)
995+
state.dtsLines.push(processVariable(fullDeclaration, isExported, state))
977996
return
978997
}
979998

@@ -998,6 +1017,24 @@ export function processBlock(lines: string[], comments: string[], state: Process
9981017
debugLog(state, 'processing', `Unhandled declaration type: ${cleanDeclaration.split('\n')[0]}`)
9991018
}
10001019

1020+
function processDeclaration(declaration: string): boolean {
1021+
let bracketDepth = 0
1022+
let parenDepth = 0
1023+
1024+
for (const char of declaration) {
1025+
if (char === '(')
1026+
parenDepth++
1027+
if (char === ')')
1028+
parenDepth--
1029+
if (char === '{')
1030+
bracketDepth++
1031+
if (char === '}')
1032+
bracketDepth--
1033+
}
1034+
1035+
return bracketDepth === 0 && parenDepth === 0
1036+
}
1037+
10011038
export function processSpecificDeclaration(declarationWithoutComments: string, fullDeclaration: string, state: ProcessingState): void {
10021039
state.debug.currentProcessing = declarationWithoutComments
10031040
debugLog(state, 'processing', `Processing declaration: ${declarationWithoutComments.substring(0, 100)}...`)
@@ -1148,13 +1185,13 @@ export function processSpecificDeclaration(declarationWithoutComments: string, f
11481185
console.warn('Unhandled declaration type:', declarationWithoutComments.split('\n')[0])
11491186
}
11501187

1151-
export function processSourceFile(content: string, state: ProcessingState): void {
1188+
function processSourceFile(content: string, state: ProcessingState): void {
11521189
const lines = content.split('\n')
11531190
let currentBlock: string[] = []
11541191
let currentComments: string[] = []
11551192
let bracketDepth = 0
1193+
let parenDepth = 0
11561194
let inDeclaration = false
1157-
// let declarationStart = -1
11581195

11591196
for (let i = 0; i < lines.length; i++) {
11601197
const line = lines[i]
@@ -1170,43 +1207,57 @@ export function processSourceFile(content: string, state: ProcessingState): void
11701207
continue
11711208
}
11721209

1173-
// Track brackets for nesting depth
1174-
bracketDepth += (line.match(/\{/g) || []).length
1175-
bracketDepth -= (line.match(/\}/g) || []).length
1176-
1177-
// Handle declaration starts
1210+
// Track brackets and parentheses for nesting depth
11781211
if (isDeclarationStart(trimmedLine)) {
11791212
if (inDeclaration && currentBlock.length > 0) {
11801213
processBlock(currentBlock, currentComments, state)
11811214
currentBlock = []
11821215
currentComments = []
1216+
bracketDepth = 0
1217+
parenDepth = 0
11831218
}
11841219
inDeclaration = true
1185-
// declarationStart = i
11861220
currentBlock = [line]
1221+
1222+
// Initialize depths for the first line
1223+
parenDepth += (line.match(/\(/g) || []).length
1224+
parenDepth -= (line.match(/\)/g) || []).length
1225+
bracketDepth += (line.match(/\{/g) || []).length
1226+
bracketDepth -= (line.match(/\}/g) || []).length
1227+
11871228
continue
11881229
}
11891230

1190-
// Add line to current block if in declaration
1231+
// If we're in a declaration, track the nesting
11911232
if (inDeclaration) {
11921233
currentBlock.push(line)
11931234

1194-
// Check for declaration end
1235+
// Update depths
1236+
parenDepth += (line.match(/\(/g) || []).length
1237+
parenDepth -= (line.match(/\)/g) || []).length
1238+
bracketDepth += (line.match(/\{/g) || []).length
1239+
bracketDepth -= (line.match(/\}/g) || []).length
1240+
1241+
// Check if the declaration is complete
11951242
const isComplete = (
1196-
bracketDepth === 0 && (
1243+
parenDepth === 0
1244+
&& bracketDepth === 0 && (
11971245
trimmedLine.endsWith(';')
11981246
|| trimmedLine.endsWith('}')
11991247
|| trimmedLine.endsWith(',')
12001248
|| trimmedLine.match(/\bas\s+const[,;]?$/)
12011249
)
12021250
)
12031251

1252+
debugLog(state, 'source-processing', `Line "${trimmedLine}": parenDepth=${parenDepth}, bracketDepth=${bracketDepth}, complete=${isComplete}`)
1253+
12041254
if (isComplete) {
12051255
processBlock(currentBlock, currentComments, state)
12061256
currentBlock = []
12071257
currentComments = []
12081258
inDeclaration = false
1209-
// declarationStart = -1
1259+
bracketDepth = 0
1260+
parenDepth = 0
12101261
}
12111262
}
12121263
}
@@ -1273,7 +1324,17 @@ function processType(declaration: string, isExported = true): string {
12731324
* Process variable (const, let, var) declarations with type inference
12741325
*/
12751326
function processVariable(declaration: string, isExported: boolean, state: ProcessingState): string {
1276-
// Handle explicit type annotations first
1327+
debugLog(state, 'process-variable', `Processing complete declaration:\n${declaration}`)
1328+
1329+
// First, try to match explicit return type for function declarations
1330+
const functionTypeMatch = declaration.match(/(?:export\s+)?(?:const|let|var)\s+([^=\s]+)\s*=\s*\([^)]*\)\s*:\s*([^=>{]+)/)
1331+
if (functionTypeMatch) {
1332+
const [, name, returnType] = functionTypeMatch
1333+
debugLog(state, 'process-variable', `Found explicit return type for ${name}: ${returnType}`)
1334+
return `${isExported ? 'export ' : ''}declare const ${name}: ${returnType.trim()};`
1335+
}
1336+
1337+
// Handle explicit type annotations in the declaration
12771338
const explicitTypeMatch = declaration.match(/(?:export\s+)?(?:const|let|var)\s+([^:\s]+)\s*:\s*([^=]+)=/)
12781339
if (explicitTypeMatch) {
12791340
const [, name, type] = explicitTypeMatch
@@ -1282,7 +1343,7 @@ function processVariable(declaration: string, isExported: boolean, state: Proces
12821343
}
12831344

12841345
// Handle value assignments
1285-
const valueMatch = declaration.match(/(?:export\s+)?(?:const|let|var)\s+([^=\s]+)\s*=\s*(.+)$/s)
1346+
const valueMatch = declaration.match(/(?:export\s+)?(?:const|let|var)\s+([^=\s]+)\s*=\s*([\s\S]+)$/)
12861347
if (!valueMatch) {
12871348
debugLog(state, 'process-variable', 'Failed to match variable declaration')
12881349
return declaration
@@ -1292,11 +1353,10 @@ function processVariable(declaration: string, isExported: boolean, state: Proces
12921353
const declarationType = getDeclarationType(declaration)
12931354
const trimmedValue = rawValue.trim()
12941355

1295-
debugLog(state, 'process-variable', `Processing ${name} with value length ${trimmedValue.length}`)
1356+
debugLog(state, 'process-variable', `Processing ${name} with value:\n${trimmedValue}`)
12961357

12971358
// Handle string literals
1298-
if (/^(['"`]).*\1$/.test(trimmedValue)) {
1299-
// For string literals, use type annotation instead of value assignment
1359+
if (/^['"`].*['"`]$/.test(trimmedValue)) {
13001360
return `${isExported ? 'export ' : ''}declare ${declarationType} ${name}: ${trimmedValue};`
13011361
}
13021362

0 commit comments

Comments
 (0)