Skip to content

Commit 0bec3d9

Browse files
committed
chore: wip
1 parent ddb23d1 commit 0bec3d9

1 file changed

Lines changed: 76 additions & 50 deletions

File tree

src/extract.ts

Lines changed: 76 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
66
let declarations = ''
77
let exports = ''
88
const processedDeclarations = new Set()
9+
let pendingComment = ''
910

1011
// Function to extract the body of a function
11-
const extractFunctionBody = (funcName: string) => {
12+
function extractFunctionBody(funcName: string) {
1213
const funcRegex = new RegExp(`function\\s+${funcName}\\s*\\([^)]*\\)\\s*{([\\s\\S]*?)}`, 'g')
1314
const match = funcRegex.exec(fileContent)
1415
return match ? match[1] : ''
1516
}
1617

1718
// Function to check if an identifier is used in a given content
18-
const isIdentifierUsed = (identifier: string, content: string) => {
19+
function isIdentifierUsed(identifier: string, content: string) {
1920
const regex = new RegExp(`\\b${identifier}\\b`, 'g')
2021
return regex.test(content)
2122
}
@@ -48,7 +49,7 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
4849
}
4950

5051
// Function to parse object literal
51-
const parseObjectLiteral = (str: string) => {
52+
function parseObjectLiteral(str: string) {
5253
const obj: Record<string, string> = {}
5354
str.split(',').forEach((pair) => {
5455
const trimmedPair = pair.trim()
@@ -68,65 +69,90 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
6869
const declarationRegex = /(\/\*\*[\s\S]*?\*\/\s*)?(export\s+(const|interface|type|function|async function)\s+(\w+)[\s\S]*?(?=export\s|$))/g
6970
const declarationMatches = Array.from(fileContent.matchAll(declarationRegex))
7071
for (const [, comment, declaration, declType, name] of declarationMatches) {
71-
if (!processedDeclarations.has(name)) {
72-
if (comment)
73-
declarations += `${comment.trim()}\n`
74-
75-
if (declType === 'const') {
76-
const constMatch = declaration.match(/export\s+const\s+(\w+)(\s*:\s*([^=]+))?\s*=\s*(\{[^}]+\})/)
77-
if (constMatch) {
78-
const [, constName, , , constValue] = constMatch
79-
// Parse the object literal
80-
const parsedValue = parseObjectLiteral(constValue.slice(1, -1))
81-
const formattedValue = Object.entries(parsedValue)
82-
.map(([key, value]) => ` ${key}: ${value.includes('/') || value.includes('\'') ? value : `'${value}'`}`)
83-
.join('\n')
84-
85-
declarations += `export declare const ${constName}: {\n${formattedValue}\n}\n\n`
72+
if (comment) {
73+
pendingComment = comment.trim()
74+
}
75+
76+
if (declType === 'const') {
77+
const constMatch = declaration.match(/export\s+const\s+(\w+)(\s*:\s*([^=]+))?\s*=\s*(\{[^}]+\})/)
78+
if (constMatch) {
79+
const [, constName, , , constValue] = constMatch
80+
// Parse the object literal
81+
const parsedValue = parseObjectLiteral(constValue.slice(1, -1))
82+
const formattedValue = Object.entries(parsedValue)
83+
.map(([key, value]) => ` ${key}: ${value.includes('/') || value.includes('\'') ? value : `'${value}'`}`)
84+
.join('\n')
85+
86+
if (pendingComment) {
87+
declarations += `${pendingComment}\n`
88+
pendingComment = ''
89+
}
90+
declarations += `export declare const ${constName}: {\n${formattedValue}\n}\n\n`
91+
}
92+
else {
93+
// Handle constants initialized with function calls
94+
const constFuncMatch = declaration.match(/export\s+const\s+(\w+)\s*:\s*([^=]+)\s*=\s*await\s+\w+\([^)]*\)/)
95+
if (constFuncMatch) {
96+
const [, constName, constType] = constFuncMatch
97+
if (pendingComment) {
98+
declarations += `${pendingComment}\n`
99+
pendingComment = ''
100+
}
101+
declarations += `export declare const ${constName}: ${constType.trim()}\n\n`
86102
}
87103
else {
88104
// Fallback to the original declaration if parsing fails
105+
if (pendingComment) {
106+
declarations += `${pendingComment}\n`
107+
pendingComment = ''
108+
}
89109
declarations += `export declare ${declaration.replace(/export\s+/, '').trim()}\n\n`
90110
}
91111
}
92-
else if (declType === 'interface' || declType === 'type') {
93-
declarations += `${declaration.trim()}\n\n`
112+
}
113+
else if (declType === 'interface' || declType === 'type') {
114+
if (pendingComment) {
115+
declarations += `${pendingComment}\n`
116+
pendingComment = ''
117+
}
118+
declarations += `${declaration.trim()}\n\n`
119+
}
120+
else if (declType === 'function' || declType === 'async function') {
121+
if (pendingComment) {
122+
declarations += `${pendingComment}\n`
123+
pendingComment = ''
94124
}
95-
else if (declType === 'function' || declType === 'async function') {
96-
const funcSignatureRegex = /export\s+(async\s+)?function\s+(\w+)\s*\(([^)]*)\)\s*:\s*([^{]+)/
97-
const funcSignatureMatch = declaration.match(funcSignatureRegex)
125+
const funcSignatureRegex = /export\s+(async\s+)?function\s+(\w+)\s*\(([^)]*)\)\s*:\s*([^{]+)/
126+
const funcSignatureMatch = declaration.match(funcSignatureRegex)
98127

99-
if (funcSignatureMatch) {
100-
const [, isAsync, funcName, params, returnType] = funcSignatureMatch
101-
declarations += `export declare ${isAsync || ''}function ${funcName}(${params.trim()}): ${returnType.trim()}\n\n`
128+
if (funcSignatureMatch) {
129+
const [, isAsync, funcName, params, returnType] = funcSignatureMatch
130+
declarations += `export declare ${isAsync || ''}function ${funcName}(${params.trim()}): ${returnType.trim()}\n\n`
131+
}
132+
else {
133+
// If we can't match the full signature, let's try to extract what we can
134+
const funcNameParamsRegex = /export\s+(async\s+)?function\s+(\w+)\s*\(([^)]*)\)/
135+
const funcNameParamsMatch = declaration.match(funcNameParamsRegex)
136+
137+
if (funcNameParamsMatch) {
138+
const [, isAsync, funcName, params] = funcNameParamsMatch
139+
// Try to find the return type
140+
const returnTypeRegex = /\)\s*:\s*([^{]+)/
141+
const returnTypeMatch = declaration.match(returnTypeRegex)
142+
const returnType = returnTypeMatch ? returnTypeMatch[1].trim() : 'any'
143+
144+
declarations += `export declare ${isAsync || ''}function ${funcName}(${params.trim()}): ${returnType}\n\n`
102145
}
103146
else {
104-
// If we can't match the full signature, let's try to extract what we can
105-
const funcNameParamsRegex = /export\s+(async\s+)?function\s+(\w+)\s*\(([^)]*)\)/
106-
const funcNameParamsMatch = declaration.match(funcNameParamsRegex)
107-
108-
if (funcNameParamsMatch) {
109-
const [, isAsync, funcName, params] = funcNameParamsMatch
110-
// Try to find the return type
111-
const returnTypeRegex = /\)\s*:\s*([^{]+)/
112-
const returnTypeMatch = declaration.match(returnTypeRegex)
113-
const returnType = returnTypeMatch ? returnTypeMatch[1].trim() : 'any'
114-
115-
declarations += `export declare ${isAsync || ''}function ${funcName}(${params.trim()}): ${returnType}\n\n`
116-
}
117-
else {
118-
// If all else fails, just add 'declare' to the original export
119-
const simplifiedDeclaration = declaration.replace(/export\s+/, '').split('{')[0].trim()
120-
declarations += `export declare ${simplifiedDeclaration}\n\n`
121-
}
147+
// If all else fails, just add 'declare' to the original export
148+
const simplifiedDeclaration = declaration.replace(/export\s+/, '').split('{')[0].trim()
149+
declarations += `export declare ${simplifiedDeclaration}\n\n`
122150
}
123151
}
124-
else {
125-
declarations += `${declaration.trim()}\n\n`
126-
}
127-
128-
processedDeclarations.add(name)
129152
}
153+
154+
// Clear any remaining pending comment
155+
pendingComment = ''
130156
}
131157

132158
// Handle re-exports and standalone exports
@@ -157,6 +183,6 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
157183
exports += `\n\nexport default ${defaultExportMatch[1]}`
158184
}
159185

160-
const output = [imports, declarations, exports].filter(Boolean).join('\n').trim()
186+
const output = [imports, declarations.trim(), exports.trim()].filter(Boolean).join('\n').trim()
161187
return formatDeclarations(output)
162188
}

0 commit comments

Comments
 (0)