fix(solc): strip root path from remappings and sources for standard json (#1136)

* fix(solc): strip root path from remappings and sources for standard json input

* fix: use consistent contract for tests
This commit is contained in:
Matthias Seitz 2022-04-11 22:36:06 +02:00 committed by GitHub
parent 8d4aab91de
commit 3d4356f531
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 4 deletions

View File

@ -144,6 +144,25 @@ impl CompilerInput {
self.settings.remappings = remappings;
self
}
/// Sets the path of the source files to `root` adjoined to the existing path
#[must_use]
pub fn join_path(mut self, root: impl AsRef<Path>) -> Self {
let root = root.as_ref();
self.sources = self.sources.into_iter().map(|(path, s)| (root.join(path), s)).collect();
self
}
/// Removes the `base` path from all source files
pub fn strip_prefix(mut self, base: impl AsRef<Path>) -> Self {
let base = base.as_ref();
self.sources = self
.sources
.into_iter()
.map(|(path, s)| (path.strip_prefix(base).map(|p| p.to_path_buf()).unwrap_or(path), s))
.collect();
self
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]

View File

@ -428,8 +428,9 @@ impl<T: ArtifactOutput> Project<T> {
}
/// Returns standard-json-input to compile the target contract
pub fn standard_json_input(&self, target: &Path) -> Result<CompilerInput> {
tracing::trace!("Building standard-json-input");
pub fn standard_json_input(&self, target: impl AsRef<Path>) -> Result<CompilerInput> {
let target = target.as_ref();
tracing::trace!("Building standard-json-input for {:?}", target);
let graph = Graph::resolve(&self.paths)?;
let target_index = graph.files().get(target).ok_or_else(|| {
SolcError::msg(format!("cannot resolve file at {:?}", target.display()))
@ -444,12 +445,23 @@ impl<T: ArtifactOutput> Project<T> {
let compiler_inputs = CompilerInput::with_sources(
sources.into_iter().map(|(s, p)| (s.clone(), p.clone())).collect(),
);
// strip the path to the project root from all remappings
let remappings = self
.paths
.remappings
.clone()
.into_iter()
.map(|r| r.into_relative(self.root()).to_relative_remapping())
.collect::<Vec<_>>();
let compiler_input = compiler_inputs
.first()
.ok_or_else(|| SolcError::msg("cannot get the compiler input"))?
.clone()
.settings(self.solc_config.settings.clone())
.with_remappings(self.paths.remappings.clone());
.with_remappings(remappings)
.strip_prefix(self.root());
Ok(compiler_input)
}

View File

@ -5,6 +5,8 @@ use crate::{
error::{bail, Result, SolcError},
hh::HardhatArtifacts,
project_util::mock::{MockProjectGenerator, MockProjectSettings},
remappings::Remapping,
utils,
utils::tempdir,
Artifact, ArtifactOutput, Artifacts, ConfigurableArtifacts, ConfigurableContractArtifact,
FileFilter, PathStyle, Project, ProjectCompileOutput, ProjectPathsConfig, SolFilesCache,
@ -311,6 +313,11 @@ contract {} {{}}
assert!(!compiled.is_unchanged());
self
}
/// Returns a list of all source files in the project's `src` directory
pub fn list_source_files(&self) -> Vec<PathBuf> {
utils::source_files(self.project().sources_path())
}
}
impl<T: ArtifactOutput + Default> TempProject<T> {
@ -381,6 +388,16 @@ impl TempProject<ConfigurableArtifacts> {
Ok(Self::create_new(tmp_dir, inner)?)
}
/// Creates an initialized dapptools style workspace in a new temporary dir
pub fn dapptools_init() -> Result<Self> {
let mut project = Self::dapptools()?;
let orig_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test-data/dapp-sample");
copy_dir(&orig_root, project.root())?;
project.project_mut().paths.remappings = Remapping::find_many(project.root());
Ok(project)
}
/// Create a new temporary project and populate it with mock files
///
/// ```no_run

View File

@ -13,7 +13,7 @@ use ethers_solc::{
project_util::*,
remappings::Remapping,
ConfigurableArtifacts, ExtraOutputValues, Graph, Project, ProjectCompileOutput,
ProjectPathsConfig, TestFileFilter,
ProjectPathsConfig, Solc, TestFileFilter,
};
use pretty_assertions::assert_eq;
@ -955,3 +955,22 @@ fn can_sanitize_bytecode_hash() {
assert!(!compiled.has_compiler_errors());
assert!(compiled.find("A").is_some());
}
#[test]
fn can_compile_std_json_input() {
let tmp = TempProject::dapptools_init().unwrap();
tmp.assert_no_errors();
let source =
tmp.list_source_files().into_iter().filter(|p| p.ends_with("Dapp.t.sol")).next().unwrap();
let input = tmp.project().standard_json_input(source).unwrap();
assert!(input.settings.remappings.contains(&"ds-test/=lib/ds-test/src/".parse().unwrap()));
assert!(input.sources.contains_key(Path::new("lib/ds-test/src/test.sol")));
// should be installed
if let Some(solc) = Solc::find_svm_installed_version("0.8.10").ok().flatten() {
let out = solc.compile(&input).unwrap();
assert!(!out.has_error());
assert!(out.sources.contains_key("lib/ds-test/src/test.sol"));
}
}