Merge pull request #4814 from ethereum/contract-flattener-patch

Fix Contract Flattener Recursion bug
pull/4828/head
Joseph Izang 6 months ago committed by GitHub
commit 9334e95680
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      apps/remix-ide/src/app/plugins/contractFlattener.tsx
  2. 59
      libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts

@ -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)
}

@ -1,42 +1,49 @@
import type { CompilationSource, AstNode } from '@remix-project/remix-solidity'
const IMPORT_SOLIDITY_REGEX = /^\s*import(\s+).*$/gm;
const SPDX_SOLIDITY_REGEX = /^\s*\/\/ SPDX-License-Identifier:.*$/gm;
const IMPORT_SOLIDITY_REGEX = /^\s*import(\s+).*$/gm
const SPDX_SOLIDITY_REGEX = /^\s*\/\/ SPDX-License-Identifier:.*$/gm
const PRAGMA_SOLIDITY_REGEX = /^pragma experimental\s+.*$/gm
type Visited = { [key: string]: number }
export function getDependencyGraph(ast: { [name: string]: CompilationSource }, target: string, remappings: string[]) {
const graph = tsort();
const visited = {};
visited[target] = 1;
_traverse(graph, visited, ast, target, remappings);
return graph;
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, 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.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, '')
const sourceWithoutDuplicatePragma = sourceWithoutSPDX.replace(PRAGMA_SOLIDITY_REGEX, '')
concat += `\n// File: ${file}\n\n`
concat += sourceWithoutDuplicatePragma
}
}
})
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);
const dependencies = _getDependencies(currentAst)
for (const dependency of dependencies) {
const path = resolve(name, dependency, remappings);
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);
visited[path] = 1
graph.add(name, path)
_traverse(graph, visited, ast, path, remappings, order)
}
order.push(name)
}
function _getDependencies(ast: AstNode) {
@ -191,4 +198,4 @@ export function normalizeContractPath(contractPath: string): string[] {
}
const resultingPath = `${folders}${filename}`
return [folders,resultingPath, filename]
}
}

Loading…
Cancel
Save