From f9b0360d9045aa08cd26cb62d899cf279403f62a Mon Sep 17 00:00:00 2001 From: Roman Krasiuk Date: Wed, 19 Jan 2022 08:11:37 -0800 Subject: [PATCH] fix(solc): flatten duplicates (#813) * fix solc flatten duplicates * upd changelog * sample eof newlines * fix test name * linter --- CHANGELOG.md | 2 ++ ethers-solc/src/config.rs | 11 +++++++++-- .../test-data/flatten-sample/contracts/Bar.sol | 4 ++++ .../test-data/flatten-sample/contracts/Foo.sol | 6 ++++++ .../flatten-sample/contracts/FooBar.sol | 7 +++++++ ethers-solc/tests/project.rs | 17 +++++++++++++++++ 6 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 ethers-solc/test-data/flatten-sample/contracts/Bar.sol create mode 100644 ethers-solc/test-data/flatten-sample/contracts/Foo.sol create mode 100644 ethers-solc/test-data/flatten-sample/contracts/FooBar.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index c3be326d..10f1d6fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,8 @@ ### Unreleased +- Fix duplicate files during flattening + [#813](https://github.com/gakonst/ethers-rs/pull/813) - Add ability to flatten file imports [#774](https://github.com/gakonst/ethers-rs/pull/774) - Add dependency graph and resolve all imported libraryfiles diff --git a/ethers-solc/src/config.rs b/ethers-solc/src/config.rs index 8ed92257..6308fdf2 100644 --- a/ethers-solc/src/config.rs +++ b/ethers-solc/src/config.rs @@ -176,7 +176,7 @@ impl ProjectPathsConfig { pub fn flatten(&self, target: &Path) -> Result { tracing::trace!("flattening file"); let graph = Graph::resolve(self)?; - self.flatten_node(target, &graph, false, false) + self.flatten_node(target, &graph, &mut vec![], false, false) } /// Flattens a single node from the dependency graph @@ -184,6 +184,7 @@ impl ProjectPathsConfig { &self, target: &Path, graph: &Graph, + imported: &mut Vec, strip_version_pragma: bool, strip_license: bool, ) -> Result { @@ -193,6 +194,11 @@ impl ProjectPathsConfig { let target_index = graph.files().get(target).ok_or_else(|| { SolcError::msg(format!("cannot resolve file at \"{:?}\"", target.display())) })?; + + if imported.iter().any(|&idx| idx == *target_index) { + return Ok(String::new()) + } + let target_node = graph.node(*target_index); let mut imports = target_node.imports().clone(); @@ -219,7 +225,7 @@ impl ProjectPathsConfig { for import in imports.iter() { let import_path = self.resolve_import(target_dir, import.data())?; - let import_content = self.flatten_node(&import_path, graph, true, true)?; + let import_content = self.flatten_node(&import_path, graph, imported, true, true)?; let import_content = import_content.trim().as_bytes().to_owned(); let import_content_len = import_content.len() as isize; let (start, end) = import.loc_by_offset(offset); @@ -230,6 +236,7 @@ impl ProjectPathsConfig { let result = String::from_utf8(content).map_err(|err| { SolcError::msg(format!("failed to convert extended bytes to string: {}", err)) })?; + imported.push(*target_index); Ok(result) } diff --git a/ethers-solc/test-data/flatten-sample/contracts/Bar.sol b/ethers-solc/test-data/flatten-sample/contracts/Bar.sol new file mode 100644 index 00000000..5cb19aba --- /dev/null +++ b/ethers-solc/test-data/flatten-sample/contracts/Bar.sol @@ -0,0 +1,4 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity >=0.6.0; + +contract Bar {} diff --git a/ethers-solc/test-data/flatten-sample/contracts/Foo.sol b/ethers-solc/test-data/flatten-sample/contracts/Foo.sol new file mode 100644 index 00000000..f9cf562d --- /dev/null +++ b/ethers-solc/test-data/flatten-sample/contracts/Foo.sol @@ -0,0 +1,6 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity >=0.6.0; + +import { Bar } from './Bar.sol'; + +contract Foo {} diff --git a/ethers-solc/test-data/flatten-sample/contracts/FooBar.sol b/ethers-solc/test-data/flatten-sample/contracts/FooBar.sol new file mode 100644 index 00000000..eda3b10b --- /dev/null +++ b/ethers-solc/test-data/flatten-sample/contracts/FooBar.sol @@ -0,0 +1,7 @@ +//SPDX-License-Identifier: Unlicense +pragma solidity >=0.6.0; + +import { Bar } from './Bar.sol'; +import { Foo } from './Foo.sol'; + +contract FooBar {} diff --git a/ethers-solc/tests/project.rs b/ethers-solc/tests/project.rs index 2a9a91c8..0025c77e 100644 --- a/ethers-solc/tests/project.rs +++ b/ethers-solc/tests/project.rs @@ -360,3 +360,20 @@ fn can_flatten_file_in_dapp_sample() { assert!(result.find("contract Dapp").is_some()); assert!(result.find("contract DappTest").is_some()); } + +#[test] +fn can_flatten_file_with_duplicates() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test-data/flatten-sample"); + let paths = ProjectPathsConfig::builder().sources(root.join("contracts")); + let project = TempProject::::new(paths).unwrap(); + + let target = root.join("contracts/FooBar.sol"); + + let result = project.flatten(&target); + assert!(result.is_ok()); + + let result = result.unwrap(); + assert!(result.matches("contract Foo {").collect::>().len() == 1); + assert!(result.matches("contract Bar {").collect::>().len() == 1); + assert!(result.matches("contract FooBar {").collect::>().len() == 1); +}