Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 60 additions & 30 deletions ts-parser/src/parser/ModuleParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,43 +103,73 @@ export class ModuleParser {

private extractImports(sourceFile: SourceFile, _modulePath: string): Array<{ Path: string }> {
const imports: Array<{ Path: string }> = [];

// Track unique import paths to avoid duplicates
const uniquePaths = new Set<string>();

// Import declarations
const importDeclarations = sourceFile.getImportDeclarations();
for (const importDecl of importDeclarations) {
const originalPath = importDecl.getModuleSpecifierValue();
const resolvedPath = importDecl.getModuleSpecifierSourceFile()?.getFilePath();
if (resolvedPath) {
const relativePath = path.relative(this.projectRoot, resolvedPath);

if(uniquePaths.has(relativePath)) {
continue;

// Safely process import declarations
try {
const importDeclarations = sourceFile.getImportDeclarations();
for (const importDecl of importDeclarations) {
try {
const originalPath = importDecl.getModuleSpecifierValue();
if (!originalPath) continue;

const resolvedPathMaybe = importDecl.getModuleSpecifierSourceFile()?.getFilePath();
if (typeof resolvedPathMaybe === 'string') {
const relativePath = path.relative(this.projectRoot, resolvedPathMaybe);
if (!uniquePaths.has(relativePath)) {
uniquePaths.add(relativePath);
imports.push({ Path: relativePath });
}
} else {
const externalPath = `external:${originalPath}`;
if (!uniquePaths.has(externalPath)) {
uniquePaths.add(externalPath);
imports.push({ Path: externalPath });
}
}
} catch (error) {
console.warn(`[Worker ${process.pid}] Skipping problematic import in ${sourceFile.getFilePath()}:`, error);
}
uniquePaths.add(relativePath);
imports.push({ Path: relativePath });
} else {
imports.push({ Path: "external:" + originalPath });
}
} catch (error) {
console.error(`[Worker ${process.pid}] Failed to process import declarations in ${sourceFile.getFilePath()}:`, error);
}

// Export declarations (re-exports)
const exportDeclarations = sourceFile.getExportDeclarations();
for (const exportDecl of exportDeclarations) {
const originalPath = exportDecl.getModuleSpecifierValue();
if (originalPath) {
const resolvedPath = exportDecl.getModuleSpecifierSourceFile()?.getFilePath();
if (resolvedPath) {
const relativePath = path.relative(this.projectRoot, resolvedPath);
imports.push({ Path: relativePath });
} else {
imports.push({ Path: "external:" + originalPath });

// Safely process export declarations
try {
const exportDeclarations = sourceFile.getExportDeclarations();
for (const exportDecl of exportDeclarations) {
try {
const specNode = exportDecl.getModuleSpecifier();
if (!specNode) continue;

const originalPath = specNode.getLiteralText?.() ?? specNode.getText?.() ?? '';
if (!originalPath) continue;

const sourceFileObj = exportDecl.getModuleSpecifierSourceFile();
const resolvedPathMaybe = sourceFileObj ? sourceFileObj.getFilePath() : undefined;

if (typeof resolvedPathMaybe === 'string') {
const relativePath = path.relative(this.projectRoot, resolvedPathMaybe);
if (!uniquePaths.has(relativePath)) {
uniquePaths.add(relativePath);
imports.push({ Path: relativePath });
}
} else {
const externalPath = `external:${originalPath}`;
if (!uniquePaths.has(externalPath)) {
uniquePaths.add(externalPath);
imports.push({ Path: externalPath });
}
}
} catch (error) {
console.warn(`[Worker ${process.pid}] Skipping problematic export in ${sourceFile.getFilePath()}:`, error);
}
}
} catch (error) {
console.error(`[Worker ${process.pid}] Failed to process export declarations in ${sourceFile.getFilePath()}:`, error);
}

return imports;
}

}
6 changes: 5 additions & 1 deletion ts-parser/src/parser/RepositoryParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,12 @@ export class RepositoryParser {
const result = await processPackagesWithCluster(packages, this.projectRoot, options);

if (!result.success) {
const errorMessages = result.errors.map((e, index) => {
const message = e.message || 'Unknown error';
return `Error ${index + 1}: ${message}`;
}).join(', ');
throw new Error(
`Cluster processing failed: ${result.errors.map(e => e.message).join(', ')}`
`Cluster processing failed: ${errorMessages}`
);
}

Expand Down
28 changes: 27 additions & 1 deletion ts-parser/src/utils/cluster-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,31 @@ export function processPackagesWithCluster(
for (const result of message.results) {
results.push(result);
if (!result.success && result.error) {
errors.push(result.error);
const err: unknown = result.error as unknown;
let normalizedError: Error | null = null;

if (err instanceof Error) {
normalizedError = err;
} else if (typeof err === 'object' && err !== null) {
const maybe = err as { message?: string; stack?: string; name?: string };
const pkgName = (result as any).packageInfo?.name || (result as any).packageInfo?.path;
const msg = (maybe.message && String(maybe.message)) || `Worker error${pkgName ? ` in ${pkgName}` : ''}`;
normalizedError = new Error(msg);
if (maybe.stack) {
(normalizedError as any).stack = maybe.stack;
}
if (maybe.name) {
(normalizedError as any).name = maybe.name;
}
} else if (typeof err === 'string') {
normalizedError = new Error(err);
}

if (normalizedError) {
errors.push(normalizedError);
} else {
errors.push(new Error('Unknown worker error'));
}
}
}
}
Expand All @@ -195,6 +219,8 @@ export function processPackagesWithCluster(
if (workerInfo?.currentBatch) {
console.error(`Worker ${workerPid} (ID: ${workerId}) exited unexpectedly while processing batch. Re-queueing.`);
packagesToProcessQueue.unshift(workerInfo.currentBatch);
// Add an error to the errors array for this unexpected exit
errors.push(new Error(`Worker ${workerPid} (ID: ${workerId}) exited unexpectedly while processing batch`));
}

// Try to launch new workers if there are batches and capacity
Expand Down
40 changes: 27 additions & 13 deletions ts-parser/src/utils/cluster-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ export function handleWorkerProcess(): void {
const processor = new PackageProcessor(projectRoot);
const workerResults: PackageProcessingResult[] = [];

for (const pkg of packages) {
try {
const result = await processor.processPackage(pkg, options);
workerResults.push(result);
for (const pkg of packages) {
try {
const result = await processor.processPackage(pkg, options);
workerResults.push(result);

if (result.success) {
console.log(`Worker ${process.pid} finished processing package ${pkg.name || pkg.path}`);
Expand All @@ -43,27 +43,41 @@ export function handleWorkerProcess(): void {
} catch (error) {
console.error(`Worker ${process.pid} error processing package ${pkg.name || pkg.path}:`, error);

// Ensure error is an instance of Error
const processedError = error instanceof Error ? error : new Error(String(error));

// Add failed result
workerResults.push({
success: false,
error: error as Error,
error: processedError,
packageInfo: {
name: pkg.name || pkg.path,
path: pkg.path,
fileCount: 0,
size: 0,
},
});
}
}
}

if (process.send) {
const response: WorkerResult = {
results: workerResults,
workerId: process.pid || 0,
};
process.send(response);
}
if (process.send) {
const serializedResults = workerResults.map(r => ({
...r,
error: r.error
? {
message: (r.error as Error).message,
stack: (r.error as Error).stack,
name: (r.error as Error).name,
}
: undefined,
}));

const response: WorkerResult = {
results: serializedResults as unknown as PackageProcessingResult[],
workerId: process.pid || 0,
};
process.send(response);
}

console.log(`Worker ${process.pid} finished current batch, awaiting next task or shutdown signal.`);
});
Expand Down
2 changes: 1 addition & 1 deletion ts-parser/src/utils/package-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface PackageProcessingResult {
module?: Module;
repository?: Repository;
outputPath?: string;
error?: Error;
error?: Error | { message?: string; stack?: string; name?: string };
packageInfo: {
name: string;
path: string;
Expand Down
Loading