Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
fix(solc): flatten import aliases (#1192)
Browse files Browse the repository at this point in the history
* import aliases

* fix solang alias parsing

* fix token replacement

* minor

* remove log

* remove log

* address pr comments

* rollback
  • Loading branch information
rkrasiuk authored May 4, 2022
1 parent b34c034 commit a656830
Show file tree
Hide file tree
Showing 5 changed files with 339 additions and 78 deletions.
58 changes: 42 additions & 16 deletions ethers-solc/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
cache::SOLIDITY_FILES_CACHE_FILENAME,
error::{Result, SolcError, SolcIoError},
remappings::Remapping,
resolver::Graph,
resolver::{Graph, SolImportAlias},
utils, Source, Sources,
};

Expand Down Expand Up @@ -281,43 +281,69 @@ impl ProjectPathsConfig {
let target_node = graph.node(*target_index);

let mut imports = target_node.imports().clone();
imports.sort_by_key(|x| x.loc().0);
imports.sort_by_key(|x| x.loc().start);

let mut content = target_node.content().to_owned();

for alias in imports.iter().flat_map(|i| i.data().aliases()) {
let (alias, target) = match alias {
SolImportAlias::Contract(alias, target) => (alias.clone(), target.clone()),
_ => continue,
};
let name_regex = utils::create_contract_or_lib_name_regex(&alias);
let target_len = target.len() as isize;
let mut replace_offset = 0;
for cap in name_regex.captures_iter(&content.clone()) {
if cap.name("ignore").is_some() {
continue
}
if let Some(name_match) =
vec!["n1", "n2", "n3"].iter().find_map(|name| cap.name(name))
{
let name_match_range =
utils::range_by_offset(&name_match.range(), replace_offset);
replace_offset += target_len - (name_match_range.len() as isize);
content.replace_range(name_match_range, &target);
}
}
}

let mut content = target_node.content().as_bytes().to_vec();
let mut content = content.as_bytes().to_vec();
let mut offset = 0_isize;

if strip_license {
if let Some(license) = target_node.license() {
let (start, end) = license.loc_by_offset(offset);
content.splice(start..end, std::iter::empty());
offset -= (end - start) as isize;
let license_range = license.loc_by_offset(offset);
offset -= license_range.len() as isize;
content.splice(license_range, std::iter::empty());
}
}

if strip_version_pragma {
if let Some(version) = target_node.version() {
let (start, end) = version.loc_by_offset(offset);
content.splice(start..end, std::iter::empty());
offset -= (end - start) as isize;
let version_range = version.loc_by_offset(offset);
offset -= version_range.len() as isize;
content.splice(version_range, std::iter::empty());
}
}

if strip_experimental_pragma {
if let Some(experiment) = target_node.experimental() {
let (start, end) = experiment.loc_by_offset(offset);
content.splice(start..end, std::iter::empty());
offset -= (end - start) as isize;
let experimental_pragma_range = experiment.loc_by_offset(offset);
offset -= experimental_pragma_range.len() as isize;
content.splice(experimental_pragma_range, std::iter::empty());
}
}

for import in imports.iter() {
let import_path = self.resolve_import(target_dir, import.data())?;
let import_path = self.resolve_import(target_dir, import.data().path())?;
let s = self.flatten_node(&import_path, graph, imported, true, true, true)?;

let import_content = s.as_bytes();
let import_content_len = import_content.len() as isize;
let (start, end) = import.loc_by_offset(offset);
content.splice(start..end, import_content.iter().copied());
offset += import_content_len - ((end - start) as isize);
let import_range = import.loc_by_offset(offset);
offset += import_content_len - (import_range.len() as isize);
content.splice(import_range, import_content.iter().copied());
}

let result = String::from_utf8(content).map_err(|err| {
Expand Down
14 changes: 8 additions & 6 deletions ethers-solc/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use std::{
path::{Path, PathBuf},
};

use parse::{SolData, SolDataUnit};
use parse::{SolData, SolDataUnit, SolImport};
use rayon::prelude::*;

use semver::VersionReq;
Expand All @@ -62,6 +62,7 @@ use crate::{error::Result, utils, ProjectPathsConfig, SolcError, Source, Sources
mod parse;
mod tree;

pub use parse::SolImportAlias;
pub use tree::{print, Charset, TreeOptions};

/// The underlying edges of the graph which only contains the raw relationship data.
Expand Down Expand Up @@ -339,13 +340,14 @@ impl Graph {
};

for import in node.data.imports.iter() {
match paths.resolve_import(cwd, import.data()) {
let import_path = import.data().path();
match paths.resolve_import(cwd, import_path) {
Ok(import) => {
add_node(&mut unresolved, &mut index, &mut resolved_imports, import)?;
}
Err(err) => {
if unresolved_paths.insert(import.data().to_path_buf()) {
crate::report::unresolved_import(import.data(), &paths.remappings);
if unresolved_paths.insert(import_path.to_path_buf()) {
crate::report::unresolved_import(import_path, &paths.remappings);
}
tracing::trace!(
"failed to resolve import component \"{:?}\" for {:?}",
Expand Down Expand Up @@ -772,7 +774,7 @@ impl Node {
&self.source.content
}

pub fn imports(&self) -> &Vec<SolDataUnit<PathBuf>> {
pub fn imports(&self) -> &Vec<SolDataUnit<SolImport>> {
&self.data.imports
}

Expand Down Expand Up @@ -854,7 +856,7 @@ mod tests {
let dapp_test = graph.node(1);
assert_eq!(dapp_test.path, paths.sources.join("Dapp.t.sol"));
assert_eq!(
dapp_test.data.imports.iter().map(|i| i.data()).collect::<Vec<&PathBuf>>(),
dapp_test.data.imports.iter().map(|i| i.data().path()).collect::<Vec<&PathBuf>>(),
vec![&PathBuf::from("ds-test/test.sol"), &PathBuf::from("./Dapp.sol")]
);
assert_eq!(graph.imported_nodes(1).to_vec(), vec![2, 0]);
Expand Down
Loading

0 comments on commit a656830

Please sign in to comment.