Skip to content

Commit

Permalink
chore: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbbreuer committed Nov 5, 2024
1 parent b3dcb31 commit 2710821
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 33 deletions.
14 changes: 7 additions & 7 deletions fixtures/output/variable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export declare const someObject: {
someNumber: 1000;
someBoolean: true;
someFalse: false;
someFunction: () => void;
someFunction: () => unknown;
anotherOne: () => unknown;
someArray: Array<1 | 2 | 3>;
someNestedArray: Array<Array<1 | 2 | 3> | Array<4 | 5 | 6 | 7 | 8 | 9 | 10>>;
Expand All @@ -24,7 +24,7 @@ export declare const someObject: {
Array<11 | 12 | 13>
>;
someOtherNestedArray: Array<
Array<'some text' | 2 | unknown | (() => void) | unknown> |
Array<'some text' | 2 | unknown | (() => unknown) | unknown> |
Array<4 | 5 | 6 | 7 | 8 | 9 | 10>
>;
someComplexArray: Array<
Expand All @@ -45,7 +45,7 @@ export declare const someObject: {
};
otherKey: {
nestedKey: unknown;
nestedKey2: () => void
nestedKey2: () => unknown
}
};
someNestedObjectArray: Array<
Expand Down Expand Up @@ -89,13 +89,13 @@ export declare const complexObject: {
};
utils: {
formatters: {
date: (input: Date) => string;
currency: (amount: number, currency: string) => string
date: (input: Date) => unknown;
currency: (amount: number, currency: string) => unknown
}
}
};
export declare const methodDecorator: (...args: any[]) => unknown;
export declare const methodDecoratorWithExplicitType: (...args: any[]) => unknown;
export declare const methodDecorator: (target: any, propertyKey: string, descriptor: PropertyDescriptor) => unknown;
export declare const methodDecoratorWithExplicitType: (target: any, propertyKey: string, descriptor: PropertyDescriptor) => SomeType;
export declare const CONFIG_MAP: {
development: {
features: {
Expand Down
116 changes: 90 additions & 26 deletions src/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,42 +411,106 @@ function extractFunctionType(value: string): string | null {
debugLog('extract-function', `Extracting function type from: ${value}`)

const cleanValue = value.trim()
let pos = 0
const length = cleanValue.length

// Check if the value starts with '(' (function expression)
if (!cleanValue.startsWith('(')) {
// Handle function keyword with explicit parameter types
const funcMatch = cleanValue.match(/^function\s*\w*\s*\((.*?)\)/s)
if (funcMatch) {
const [, params] = funcMatch
// Clean parameters while preserving type annotations
const cleanParams = cleanParameterTypes(params || '')
// Extract return type if available
const returnTypeMatch = cleanValue.match(/\):\s*([^{;]+)(?:[{;]|$)/)
const returnType = returnTypeMatch ? normalizeType(returnTypeMatch[1]) : 'unknown'
return `(${cleanParams}) => ${returnType}`
}
return null
}

// Handle explicit return type annotations
const returnTypeMatch = cleanValue.match(/\):\s*([^{;]+)(?:[{;]|$)/)
let returnType = returnTypeMatch ? normalizeType(returnTypeMatch[1]) : 'unknown'
// Now, handle arrow functions with possible return types
// Extract parameters using balanced parentheses
pos++ // Skip '('
let depth = 1
const paramsStart = pos
let inString = false
let stringChar = ''
for (; pos < length; pos++) {
const char = cleanValue[pos]
const prevChar = pos > 0 ? cleanValue[pos - 1] : ''

// Check value contents for return type inference
if (returnType === 'unknown') {
if (cleanValue.includes('toISOString()')) {
returnType = 'string'
}
else if (cleanValue.includes('Intl.NumberFormat') && cleanValue.includes('format')) {
returnType = 'string'
if (inString) {
if (char === stringChar && prevChar !== '\\') {
inString = false
}
else if (char === '\\') {
pos++ // Skip escaped character
}
}
else if (cleanValue.includes('console.log')) {
returnType = 'void'
else {
if (char === '"' || char === '\'' || char === '`') {
inString = true
stringChar = char
}
else if (char === '(') {
depth++
}
else if (char === ')') {
depth--
if (depth === 0) {
break
}
}
}
}
if (depth !== 0) {
// Unbalanced parentheses
debugLog('extract-function', 'Unbalanced parentheses in function parameters')
return null
}

const paramsEnd = pos
const params = cleanValue.slice(paramsStart, paramsEnd)

pos++ // Move past ')'

// Handle arrow functions with explicit parameter types
const arrowMatch = value.match(/^\((.*?)\)\s*=>\s*(.*)/)
if (arrowMatch) {
const [, params] = arrowMatch
// Clean parameters while preserving type annotations
const cleanParams = cleanParameterTypes(params || '')
return `(${cleanParams}) => ${returnType}`
// Skip any whitespace
while (pos < length && /\s/.test(cleanValue[pos])) pos++

// Check for optional return type
let returnType = 'unknown'
if (cleanValue[pos] === ':') {
pos++ // Skip ':'
// Skip any whitespace
while (pos < length && /\s/.test(cleanValue[pos])) pos++
const returnTypeStart = pos
// Read until '=>' or '{'
while (pos < length && !cleanValue.startsWith('=>', pos) && cleanValue[pos] !== '{') {
pos++
}
const returnTypeEnd = pos
returnType = cleanValue.slice(returnTypeStart, returnTypeEnd).trim()
}

// Handle function keyword with explicit parameter types
const funcMatch = value.match(/^function\s*\w*\s*\((.*?)\)/)
if (funcMatch) {
const [, params] = funcMatch
const cleanParams = cleanParameterTypes(params || '')
return `(${cleanParams}) => ${returnType}`
// Skip any whitespace
while (pos < length && /\s/.test(cleanValue[pos])) pos++

// Now, check for '=>'
if (cleanValue.startsWith('=>', pos)) {
pos += 2
}
else {
// No '=>', invalid function expression
debugLog('extract-function', 'Function expression missing "=>"')
return null
}

return null
// Now, construct the function type
const cleanParams = cleanParameterTypes(params || '')
debugLog('extract-function', `Extracted function type: (${cleanParams}) => ${returnType}`)
return `(${cleanParams}) => ${returnType}`
}

/**
Expand Down

0 comments on commit 2710821

Please sign in to comment.