From 25c33ffc0b0fdcc52622d72234158d04f9cd4065 Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Tue, 14 Nov 2023 12:12:09 +0100 Subject: [PATCH] Modify dependency resolver to exclude duplicate contents --- .../src/app/services/circomPluginClient.ts | 53 +++++++++++++------ apps/circuit-compiler/src/app/types/index.ts | 7 +++ 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/apps/circuit-compiler/src/app/services/circomPluginClient.ts b/apps/circuit-compiler/src/app/services/circomPluginClient.ts index e97609fbac..0eccddb281 100644 --- a/apps/circuit-compiler/src/app/services/circomPluginClient.ts +++ b/apps/circuit-compiler/src/app/services/circomPluginClient.ts @@ -4,7 +4,7 @@ import EventManager from 'events' import pathModule from 'path' import { parse, compile, generate_witness, generate_r1cs, compiler_list } from 'circom_wasm' import { extractNameFromKey, extractParentFromKey } from '@remix-ui/helper' -import { CompilationConfig, CompilerReport } from '../types' +import { CompilationConfig, CompilerReport, ResolverOutput } from '../types' export class CircomPluginClient extends PluginClient { public internalEvents: EventManager @@ -37,10 +37,7 @@ export class CircomPluginClient extends PluginClient { // @ts-ignore fileContent = await this.call('fileManager', 'readFile', path) } - this.lastParsedFiles = { - [path]: fileContent, - } - this.lastParsedFiles = await this.resolveDependencies(path, fileContent, this.lastParsedFiles) + this.lastParsedFiles = await this.resolveDependencies(path, fileContent, { [path]: { content: fileContent, parent: null } }) const parsedOutput = parse(path, this.lastParsedFiles) try { @@ -211,14 +208,13 @@ export class CircomPluginClient extends PluginClient { this.internalEvents.emit('circuit_computing_witness_done') } - async resolveDependencies(filePath: string, fileContent: string, output = {}, depPath: string = '', blackPath: string[] = []): Promise> { + async resolveDependencies(filePath: string, fileContent: string, output: ResolverOutput = {}, depPath: string = '', parent: string = ''): Promise> { // extract all includes const includes = (fileContent.match(/include ['"].*['"]/g) || []).map((include) => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) await Promise.all( includes.map(async (include) => { // fix for endless recursive includes - if (blackPath.includes(include)) return let dependencyContent = '' let path = include // @ts-ignore @@ -268,20 +264,43 @@ export class CircomPluginClient extends PluginClient { } } } - // extract all includes from the dependency content - const dependencyIncludes = (dependencyContent.match(/include ['"].*['"]/g) || []).map((include) => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) - - blackPath.push(include) - // recursively resolve all dependencies of the dependency - if (dependencyIncludes.length > 0) { - await this.resolveDependencies(filePath, dependencyContent, output, path, blackPath) - output[include] = dependencyContent + const fileNameToInclude = extractNameFromKey(include) + const similarFile = Object.keys(output).find(path => { + return path.indexOf(fileNameToInclude) > -1 + }) + const isDuplicateContent = similarFile && output[similarFile] ? output[similarFile].content === dependencyContent : false + + if (output[include] && output[include].parent) { + // if include import already exists, remove the include import from the parent file + const regexPattern = new RegExp(`include ['"]${include}['"];`, 'g') + + output[output[include].parent].content = output[output[include].parent].content.replace(regexPattern, "") + } else if (isDuplicateContent) { + // if include import has the same content as another file, replace the include import with the file name of the other file (similarFile) + if (output[similarFile].parent) output[output[similarFile].parent].content = output[output[similarFile].parent].content.replace(similarFile, include) + if (include !== similarFile) { + output[include] = output[similarFile] + delete output[similarFile] + } } else { - output[include] = dependencyContent + // extract all includes from the dependency content + const dependencyIncludes = (dependencyContent.match(/include ['"].*['"]/g) || []).map((include) => include.replace(/include ['"]/g, '').replace(/['"]/g, '')) + + output[include] = { + content: dependencyContent, + parent + } + // recursively resolve all dependencies of the dependency + if (dependencyIncludes.length > 0) await this.resolveDependencies(filePath, dependencyContent, output, path, include) } }) ) - return output + const result: Record = {} + + Object.keys(output).forEach((key) => { + result[key] = output[key].content + }) + return result } async resolveReportPath (path: string): Promise { diff --git a/apps/circuit-compiler/src/app/types/index.ts b/apps/circuit-compiler/src/app/types/index.ts index 029b8bea9e..71e1dbfced 100644 --- a/apps/circuit-compiler/src/app/types/index.ts +++ b/apps/circuit-compiler/src/app/types/index.ts @@ -84,4 +84,11 @@ export type CompileOptionsProps = { setCircuitHideWarnings: (value: boolean) => void, autoCompile: boolean, hideWarnings: boolean +} + +export type ResolverOutput = { + [name: string]: { + content: string, + parent: string + } } \ No newline at end of file