From 00f4ac6178b7891594eb1175ea94c7dbe2a796db Mon Sep 17 00:00:00 2001 From: Joseph Izang Date: Tue, 28 Mar 2023 17:51:00 +0100 Subject: [PATCH] refactored path resolution logic. fix undefined bug in flattener utils --- .../src/app/plugins/contractFlattener.tsx | 43 +++++++++++++------ .../src/app/plugins/solidity-umlgen.tsx | 31 +++++++++---- .../src/lib/logic/flattenerUtilities.ts | 29 ++++++++++--- 3 files changed, 74 insertions(+), 29 deletions(-) diff --git a/apps/remix-ide/src/app/plugins/contractFlattener.tsx b/apps/remix-ide/src/app/plugins/contractFlattener.tsx index 7883852b3f..f117f2a2b6 100644 --- a/apps/remix-ide/src/app/plugins/contractFlattener.tsx +++ b/apps/remix-ide/src/app/plugins/contractFlattener.tsx @@ -1,7 +1,7 @@ import React from 'react' import { Plugin } from '@remixproject/engine' import { customAction } from '@remixproject/plugin-api' -import { concatSourceFiles, getDependencyGraph } from '@remix-ui/solidity-compiler' +import { concatSourceFiles, getDependencyGraph, normalizeContractPath } from '@remix-ui/solidity-compiler' const _paq = window._paq = window._paq || [] @@ -9,8 +9,9 @@ const profile = { name: 'contractflattener', displayName: 'Contract Flattener', description: 'Flatten solidity contracts', - methods: ['flattenAContract'], + methods: ['flattenAContract', 'normalizeContractPath'], events: [], + maintainedBy: 'Remix Team', } export class ContractFlattener extends Plugin { @@ -29,25 +30,39 @@ export class ContractFlattener extends Plugin { async flattenAContract(action: customAction) { this.fileName = action.path[0] + this.call('manager', 'deactivatePlugin', 'solidityumlgen') await this.call('solidity', 'compile', this.fileName) } /** * Takes currently compiled contract that has a bunch of imports at the top - * and flattens them ready for UML creation. Takes the flattened result - * and assigns to a local property - * @returns {Promise} + * and flattens them ready, ideally for UML creation or for other purposes. + * Takes the flattened result, writes it to a file and returns the result. + * @returns {Promise} */ - async flattenContract (source: any, filePath: string, data: any) { - const filename = filePath.split('/')[1].split('.')[0] + async flattenContract (source: { sources: any, target: string }, + filePath: string, data: { contracts: any, sources: any }): Promise { + const path = normalizeContractPath(filePath) const ast = data.sources - const dependencyGraph = getDependencyGraph(ast, filePath) - const sorted = dependencyGraph.isEmpty() - ? [filePath] - : dependencyGraph.sort().reverse() - const sources = source.sources - const result = concatSourceFiles(sorted, sources) - await this.call('fileManager', 'writeFile', `${filePath.split('/')[0]}/${filename}_flattened.sol`, result) + let dependencyGraph + let sorted + let result + let sources + try{ + dependencyGraph = getDependencyGraph(ast, filePath) + sorted = dependencyGraph.isEmpty() + ? [filePath] + : dependencyGraph.sort().reverse() + sources = source.sources + result = concatSourceFiles(sorted, sources) + }catch(err){ + console.warn(err) + } + await this.call('fileManager', 'writeFile', path , result) _paq.push(['trackEvent', 'plugin', 'contractFlattener', 'flattenAContract']) + sorted = null + sources = null + dependencyGraph = null + return result } } \ No newline at end of file diff --git a/apps/remix-ide/src/app/plugins/solidity-umlgen.tsx b/apps/remix-ide/src/app/plugins/solidity-umlgen.tsx index 656f7bd3ff..ebae55b97f 100644 --- a/apps/remix-ide/src/app/plugins/solidity-umlgen.tsx +++ b/apps/remix-ide/src/app/plugins/solidity-umlgen.tsx @@ -5,7 +5,7 @@ import React from 'react' import { RemixUiSolidityUmlGen } from '@remix-ui/solidity-uml-gen' import { ISolidityUmlGen, ThemeQualityType, ThemeSummary } from 'libs/remix-ui/solidity-uml-gen/src/types' import { RemixAppManager } from 'libs/remix-ui/plugin-manager/src/types' -import { concatSourceFiles, getDependencyGraph } from 'libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities' +import { concatSourceFiles, getDependencyGraph, normalizeContractPath } from 'libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities' import { convertUmlClasses2Dot } from 'sol2uml/lib/converterClasses2Dot' import { convertAST2UmlClasses } from 'sol2uml/lib/converterAST2Classes' import vizRenderStringSync from '@aduh95/viz.js/sync' @@ -136,17 +136,30 @@ export class SolidityUmlGen extends ViewPlugin implements ISolidityUmlGen { * @returns {Promise} */ async flattenContract (source: any, filePath: string, data: any) { - let filename = filePath.split('/')[1].split('.')[0] - const dependencyGraph = getDependencyGraph(data.sources, filePath) - const sorted = dependencyGraph.isEmpty() - ? [filePath] - : dependencyGraph.sort().reverse() - const result = concatSourceFiles(sorted, source.sources) - await this.call('fileManager', 'writeFile', `${filePath.split('/')[0]}/${filename}_flattened.sol`, result) - filename = null + const normalPath = normalizeContractPath(filePath) + let dependencyGraph + let sorted + let result + let sources + try{ + dependencyGraph = getDependencyGraph(data.sources, filePath) + sorted = dependencyGraph.isEmpty() + ? [filePath] + : dependencyGraph.sort().reverse() + sources = source.sources + result = concatSourceFiles(sorted, sources) + }catch(err){ + console.warn(err) + } + await this.call('fileManager', 'writeFile', normalPath, result) + sorted = null + sources = null + dependencyGraph = null return result } + + async showUmlDiagram(svgPayload: string) { this.updatedSvg = svgPayload this.renderComponent() 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 462353d8e7..9f6616e22b 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts +++ b/libs/remix-ui/solidity-compiler/src/lib/logic/flattenerUtilities.ts @@ -9,8 +9,7 @@ export function getDependencyGraph(ast, target) { return graph; } -export function concatSourceFiles(files, sources) { - +export function concatSourceFiles(files: any[], sources: any) { let concat = ''; for (const file of files) { const source = sources[file].content; @@ -23,7 +22,9 @@ export function concatSourceFiles(files, sources) { } function _traverse(graph, visited, ast, name) { - const currentAst = ast[name].ast; + let currentAst = null + if(ast[name] === null || ast[name] === undefined || ast[name] === 'undefined') return + currentAst = ast[name].ast const dependencies = _getDependencies(currentAst); for (const dependency of dependencies) { const path = resolve(name, dependency); @@ -37,9 +38,9 @@ function _traverse(graph, visited, ast, name) { } function _getDependencies(ast) { - const dependencies = ast.nodes - .filter(node => node.nodeType === 'ImportDirective') - .map(node => node.file); + const dependencies = ast?.nodes + .filter(node => node?.nodeType === 'ImportDirective') + .map(node => node?.file); return dependencies; } @@ -166,4 +167,20 @@ function _resolvePathArray(parts) { } return res; +} + +export function normalizeContractPath(contractPath: string): string { + let paths = contractPath.split('/') + let filename = paths[paths.length - 1].split('.')[0] + let folders = '' + for (let i = 0; i < paths.length - 1; i++) { + if(i !== paths.length -1) { + folders += `${paths[i]}/` + } + } + const resultingPath = `${folders}${filename}_flattened.sol` + paths = null + filename = null + folders = null + return resultingPath } \ No newline at end of file