Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(solc): fix autodetection edge case #2099

Merged
merged 1 commit into from Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 52 additions & 3 deletions ethers-solc/src/remappings.rs
Expand Up @@ -423,7 +423,7 @@ impl Candidate {
/// Which should be resolved to the top level dir `@openzeppelin`
///
/// We also treat candidates with a `node_modules` parent directory differently and consider
/// them to `hardhat` style. In which case the trailing library barrier `contracts` will be
/// them to be `hardhat` style. In which case the trailing library barrier `contracts` will be
/// stripped from the remapping path. This differs from dapptools style which does not include
/// the library barrier path `src` in the solidity import statements. For example, for
/// dapptools you could have
Expand Down Expand Up @@ -472,8 +472,23 @@ impl Candidate {
window_start: PathBuf,
is_inside_node_modules: bool,
) {
if let Some(pos) =
candidates.iter().position(|c| c.source_dir.ends_with(DAPPTOOLS_CONTRACTS_DIR))
// if there's only a single source dir candidate then we use this
if let Some(pos) = candidates
.iter()
.enumerate()
.fold((0, None), |(mut contracts_dir_count, mut pos), (idx, c)| {
if c.source_dir.ends_with(DAPPTOOLS_CONTRACTS_DIR) {
contracts_dir_count += 1;
if contracts_dir_count == 1 {
pos = Some(idx)
} else {
pos = None;
}
}

(contracts_dir_count, pos)
})
.1
{
let c = candidates.remove(pos);
*candidates = vec![c];
Expand Down Expand Up @@ -630,6 +645,7 @@ fn find_remapping_candidates(
}
}
}

// need to find the actual next window in the event `open` is a lib dir
let window_start = next_nested_window(open, current_dir);
// finally, we need to merge, adjust candidates from the same level and opening window
Expand Down Expand Up @@ -1227,4 +1243,37 @@ mod tests {
"/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/lib.Z6ODLZJQeJQa/repo1/lib/ds-test"
));
}

#[test]
fn find_openzeppelin_remapping() {
let tmp_dir = tempdir("lib").unwrap();
let tmp_dir_path = tmp_dir.path();
let paths = [
"lib/ds-test/src/test.sol",
"lib/forge-std/src/test.sol",
"openzeppelin/contracts/interfaces/c.sol",
];
mkdir_or_touch(tmp_dir_path, &paths[..]);

let path = tmp_dir_path.display().to_string();
let mut remappings = Remapping::find_many(path);
remappings.sort_unstable();

let mut expected = vec![
Remapping {
name: "ds-test/".to_string(),
path: to_str(tmp_dir_path.join("lib/ds-test/src")),
},
Remapping {
name: "openzeppelin/".to_string(),
path: to_str(tmp_dir_path.join("openzeppelin/contracts")),
},
Remapping {
name: "forge-std/".to_string(),
path: to_str(tmp_dir_path.join("lib/forge-std/src")),
},
];
expected.sort_unstable();
pretty_assertions::assert_eq!(remappings, expected);
}
}
4 changes: 2 additions & 2 deletions ethers-solc/src/utils.rs
Expand Up @@ -473,7 +473,7 @@ pub fn create_parent_dir_all(file: impl AsRef<Path>) -> Result<(), SolcError> {
#[cfg(test)]
mod tests {
use super::*;
use crate::resolver::Node;

use solang_parser::pt::SourceUnitPart;
use std::{
collections::HashSet,
Expand Down Expand Up @@ -516,7 +516,7 @@ contract A {}

assert!(!non_existing.exists());

let found = Node::read(&non_existing).unwrap_err();
let found = crate::resolver::Node::read(&non_existing).unwrap_err();
matches!(found, SolcError::ResolveCaseSensitiveFileName { .. });
}

Expand Down