From 8e62933dfbc4c05701398c738f6330127990fd54 Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Thu, 23 May 2024 17:40:06 +0100 Subject: [PATCH] fix subtle bug in recursion in getDependencyGraph --- .../src/app/plugins/contractFlattener.tsx | 6 ++- .../src/lib/logic/flattenerUtilities.ts | 42 ++++++++++++------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/apps/remix-ide/src/app/plugins/contractFlattener.tsx b/apps/remix-ide/src/app/plugins/contractFlattener.tsx index f8205351c6..46176cc07c 100644 --- a/apps/remix-ide/src/app/plugins/contractFlattener.tsx +++ b/apps/remix-ide/src/app/plugins/contractFlattener.tsx @@ -1,3 +1,4 @@ +/* eslint-disable prefer-const */ import React from 'react' import { Plugin } from '@remixproject/engine' import { customAction } from '@remixproject/plugin-api' @@ -57,11 +58,12 @@ export class ContractFlattener extends Plugin { let sorted let result let sources + let order: string[] = [] try { - dependencyGraph = getDependencyGraph(ast, filePath, input.settings.remappings) + dependencyGraph = getDependencyGraph(ast, filePath, input.settings.remappings, order) sorted = dependencyGraph.isEmpty() ? [filePath] : dependencyGraph.sort().reverse() sources = source.sources - result = concatSourceFiles(sorted, sources) + result = concatSourceFiles(sorted, sources, order) } catch (err) { console.warn(err) } diff --git a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts index 2ff814125a..b30ab3be2a 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts @@ -4,39 +4,49 @@ const IMPORT_SOLIDITY_REGEX = /^\s*import(\s+).*$/gm; const SPDX_SOLIDITY_REGEX = /^\s*\/\/ SPDX-License-Identifier:.*$/gm; type Visited = { [key: string]: number } -export function getDependencyGraph(ast: { [name: string]: CompilationSource }, target: string, remappings: string[]) { +export function getDependencyGraph(ast: { [name: string]: CompilationSource }, target: string, remappings: string[], order: string[]) { const graph = tsort(); const visited = {}; visited[target] = 1; - _traverse(graph, visited, ast, target, remappings); + _traverse(graph, visited, ast, target, remappings, order); return graph; } -export function concatSourceFiles(files: any[], sources: any) { - let concat = ''; - for (const file of files) { - const source = sources[file].content; - const sourceWithoutImport = source.replace(IMPORT_SOLIDITY_REGEX, ''); - const sourceWithoutSPDX = sourceWithoutImport.replace(SPDX_SOLIDITY_REGEX, ''); - concat += `\n// File: ${file}\n\n`; - concat += sourceWithoutSPDX; - } - return concat; +export function concatSourceFiles(files: any[], sources: any, order: string[]) { + let concat = '' + order.reverse().forEach((importName) => { + for (const file of files) { + if (file === importName) { + const source = sources[file].content + const sourceWithoutImport = source.replace(IMPORT_SOLIDITY_REGEX, '') + const sourceWithoutSPDX = sourceWithoutImport.replace(SPDX_SOLIDITY_REGEX, '') + concat += `\n// File: ${file}\n\n` + concat += sourceWithoutSPDX + } + const source = sources[importName].content + const sourceWithoutImport = source.replace(IMPORT_SOLIDITY_REGEX, '') + const sourceWithoutSPDX = sourceWithoutImport.replace(SPDX_SOLIDITY_REGEX, '') + concat += `\n// File: ${importName}\n\n` + concat += sourceWithoutSPDX + } + }) + return concat } -function _traverse(graph: Graph, visited: Visited, ast: { [name: string]: CompilationSource }, name: string, remappings: string[]) { +function _traverse(graph: Graph, visited: Visited, ast: { [name: string]: CompilationSource }, name: string, remappings: string[], order: string[]) { let currentAst = null currentAst = ast[name].ast const dependencies = _getDependencies(currentAst); for (const dependency of dependencies) { const path = resolve(name, dependency, remappings); if (path in visited) { - // continue; // fixes wrong ordering of source in flattened file + continue; // fixes wrong ordering of source in flattened file } visited[path] = 1; graph.add(name, path); - _traverse(graph, visited, ast, path, remappings); + _traverse(graph, visited, ast, path, remappings, order); } + order.push(name) } function _getDependencies(ast: AstNode) { @@ -191,4 +201,4 @@ export function normalizeContractPath(contractPath: string): string[] { } const resultingPath = `${folders}${filename}` return [folders,resultingPath, filename] -} \ No newline at end of file +}