ethers-rs/ethers-solc/src/config.rs

1016 lines
38 KiB
Rust
Raw Normal View History

use crate::{
artifacts::{output_selection::ContractOutputSelection, Settings},
cache::SOLIDITY_FILES_CACHE_FILENAME,
error::{Result, SolcError, SolcIoError},
remappings::Remapping,
resolver::{Graph, SolImportAlias},
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
utils, Source, Sources,
};
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeSet, HashSet},
fmt::{self, Formatter},
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
fs,
ops::{Deref, DerefMut},
path::{Component, Path, PathBuf},
};
/// Where to find all files or where to write them
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProjectPathsConfig {
/// Project root
pub root: PathBuf,
/// Path to the cache, if any
pub cache: PathBuf,
/// Where to store build artifacts
pub artifacts: PathBuf,
/// Where to store the build info files
pub build_infos: PathBuf,
/// Where to find sources
pub sources: PathBuf,
/// Where to find tests
pub tests: PathBuf,
/// Where to find scripts
pub scripts: PathBuf,
/// Where to look for libraries
pub libraries: Vec<PathBuf>,
/// The compiler remappings
pub remappings: Vec<Remapping>,
}
impl ProjectPathsConfig {
pub fn builder() -> ProjectPathsConfigBuilder {
ProjectPathsConfigBuilder::default()
}
/// Creates a new hardhat style config instance which points to the canonicalized root path
pub fn hardhat(root: impl AsRef<Path>) -> Result<Self> {
PathStyle::HardHat.paths(root)
}
/// Creates a new dapptools style config instance which points to the canonicalized root path
pub fn dapptools(root: impl AsRef<Path>) -> Result<Self> {
PathStyle::Dapptools.paths(root)
}
/// Creates a new config with the current directory as the root
pub fn current_hardhat() -> Result<Self> {
Self::hardhat(std::env::current_dir().map_err(|err| SolcError::io(err, "."))?)
}
/// Creates a new config with the current directory as the root
pub fn current_dapptools() -> Result<Self> {
Self::dapptools(std::env::current_dir().map_err(|err| SolcError::io(err, "."))?)
}
/// Returns a new [ProjectPaths] instance that contains all directories configured for this
/// project
pub fn paths(&self) -> ProjectPaths {
ProjectPaths {
artifacts: self.artifacts.clone(),
build_infos: self.build_infos.clone(),
sources: self.sources.clone(),
tests: self.tests.clone(),
scripts: self.scripts.clone(),
libraries: self.libraries.iter().cloned().collect(),
}
}
/// Same as [`paths`][ProjectPathsConfig::paths] but strips the `root` form all paths.
///
/// See: [`ProjectPaths::strip_prefix_all`]
pub fn paths_relative(&self) -> ProjectPaths {
let mut paths = self.paths();
paths.strip_prefix_all(&self.root);
paths
}
/// Creates all configured dirs and files
pub fn create_all(&self) -> std::result::Result<(), SolcIoError> {
if let Some(parent) = self.cache.parent() {
fs::create_dir_all(parent).map_err(|err| SolcIoError::new(err, parent))?;
}
fs::create_dir_all(&self.artifacts)
.map_err(|err| SolcIoError::new(err, &self.artifacts))?;
fs::create_dir_all(&self.sources).map_err(|err| SolcIoError::new(err, &self.sources))?;
fs::create_dir_all(&self.tests).map_err(|err| SolcIoError::new(err, &self.tests))?;
fs::create_dir_all(&self.scripts).map_err(|err| SolcIoError::new(err, &self.scripts))?;
for lib in &self.libraries {
fs::create_dir_all(lib).map_err(|err| SolcIoError::new(err, lib))?;
}
Ok(())
}
/// Returns all sources found under the project's configured `sources` path
pub fn read_sources(&self) -> Result<Sources> {
tracing::trace!("reading all sources from \"{}\"", self.sources.display());
Ok(Source::read_all_from(&self.sources)?)
}
/// Returns all sources found under the project's configured `test` path
pub fn read_tests(&self) -> Result<Sources> {
tracing::trace!("reading all tests from \"{}\"", self.tests.display());
Ok(Source::read_all_from(&self.tests)?)
}
/// Returns all sources found under the project's configured `script` path
pub fn read_scripts(&self) -> Result<Sources> {
tracing::trace!("reading all scripts from \"{}\"", self.scripts.display());
Ok(Source::read_all_from(&self.scripts)?)
}
/// Returns true if the there is at least one solidity file in this config.
///
/// See also, `Self::input_files()`
pub fn has_input_files(&self) -> bool {
self.input_files_iter().next().is_some()
}
/// Returns an iterator that yields all solidity file paths for `Self::sources`, `Self::tests`
/// and `Self::scripts`
pub fn input_files_iter(&self) -> impl Iterator<Item = PathBuf> + '_ {
utils::source_files_iter(&self.sources)
.chain(utils::source_files_iter(&self.tests))
.chain(utils::source_files_iter(&self.scripts))
}
/// Returns the combined set solidity file paths for `Self::sources`, `Self::tests` and
/// `Self::scripts`
pub fn input_files(&self) -> Vec<PathBuf> {
self.input_files_iter().collect()
}
/// Returns the combined set of `Self::read_sources` + `Self::read_tests` + `Self::read_scripts`
pub fn read_input_files(&self) -> Result<Sources> {
Ok(Source::read_all_files(self.input_files())?)
}
/// Converts all `\\` separators in _all_ paths to `/`
pub fn slash_paths(&mut self) {
#[cfg(windows)]
{
use path_slash::PathBufExt;
let slashed = |p: &mut PathBuf| {
*p = p.to_slash_lossy().as_ref().into();
};
slashed(&mut self.root);
slashed(&mut self.cache);
slashed(&mut self.artifacts);
slashed(&mut self.build_infos);
slashed(&mut self.sources);
slashed(&mut self.tests);
slashed(&mut self.scripts);
self.libraries.iter_mut().for_each(slashed);
self.remappings.iter_mut().for_each(Remapping::slash_path);
}
}
/// Returns true if the `file` belongs to a `library`, See [`Self::find_library_ancestor()`]
pub fn has_library_ancestor(&self, file: impl AsRef<Path>) -> bool {
self.find_library_ancestor(file).is_some()
}
/// Returns the library the file belongs to
///
/// Returns the first library that is an ancestor of the given `file`.
///
/// **Note:** this does not resolve remappings [`Self::resolve_import()`], instead this merely
/// checks if a `library` is a parent of `file`
///
/// # Example
///
/// ```
/// use std::path::Path;
/// use ethers_solc::ProjectPathsConfig;
/// let config = ProjectPathsConfig::builder().lib("lib").build().unwrap();
/// assert_eq!(config.find_library_ancestor("lib/src/Greeter.sol").unwrap(), Path::new("lib"));
/// ```
pub fn find_library_ancestor(&self, file: impl AsRef<Path>) -> Option<&PathBuf> {
let file = file.as_ref();
for lib in &self.libraries {
if lib.is_relative() &&
file.is_absolute() &&
file.starts_with(&self.root) &&
file.starts_with(self.root.join(lib)) ||
file.is_relative() &&
lib.is_absolute() &&
lib.starts_with(&self.root) &&
self.root.join(file).starts_with(lib)
{
return Some(lib)
}
if file.starts_with(lib) {
return Some(lib)
}
}
None
}
/// Attempts to resolve an `import` from the given working directory.
///
/// The `cwd` path is the parent dir of the file that includes the `import`
///
/// This will also populate the `include_paths` with any nested library root paths that should
/// be provided to solc via `--include-path` because it uses absolute imports.
pub fn resolve_import_and_include_paths(
&self,
cwd: &Path,
import: &Path,
include_paths: &mut IncludePaths,
) -> Result<PathBuf> {
let component = import
.components()
.next()
.ok_or_else(|| SolcError::msg(format!("Empty import path {}", import.display())))?;
if component == Component::CurDir || component == Component::ParentDir {
// if the import is relative we assume it's already part of the processed input
// file set
utils::canonicalize(cwd.join(import)).map_err(|err| {
SolcError::msg(format!("failed to resolve relative import \"{err:?}\""))
})
} else {
// resolve library file
let resolved = self.resolve_library_import(import.as_ref());
if resolved.is_none() {
// absolute paths in solidity are a thing for example `import
// "src/interfaces/IConfig.sol"` which could either point to `cwd +
// src/interfaces/IConfig.sol`, or make use of a remapping (`src/=....`)
if let Some(lib) = self.find_library_ancestor(cwd) {
if let Some((include_path, import)) =
utils::resolve_absolute_library(lib, cwd, import)
{
// track the path for this absolute import inside a nested library
include_paths.insert(include_path);
return Ok(import)
}
}
// also try to resolve absolute imports from the project paths
for path in [&self.root, &self.sources, &self.tests, &self.scripts] {
if cwd.starts_with(path) {
if let Ok(import) = utils::canonicalize(path.join(import)) {
return Ok(import)
}
}
}
}
resolved.ok_or_else(|| {
SolcError::msg(format!(
"failed to resolve library import \"{:?}\"",
import.display()
))
})
}
}
/// Attempts to resolve an `import` from the given working directory.
///
/// The `cwd` path is the parent dir of the file that includes the `import`
pub fn resolve_import(&self, cwd: &Path, import: &Path) -> Result<PathBuf> {
self.resolve_import_and_include_paths(cwd, import, &mut Default::default())
}
/// Attempts to find the path to the real solidity file that's imported via the given `import`
/// path by applying the configured remappings and checking the library dirs
///
/// # Example
///
/// Following `@aave` dependency in the `lib` folder `node_modules`
///
/// ```text
/// <root>/node_modules/@aave
/// ├── aave-token
/// │ ├── contracts
/// │ │ ├── open-zeppelin
/// │ │ ├── token
/// ├── governance-v2
/// ├── contracts
/// ├── interfaces
/// ```
///
/// has this remapping: `@aave/=@aave/` (name:path) so contracts can be imported as
///
/// ```solidity
/// import "@aave/governance-v2/contracts/governance/Executor.sol";
/// ```
///
/// So that `Executor.sol` can be found by checking each `lib` folder (`node_modules`) with
/// applied remappings. Applying remapping works by checking if the import path of an import
/// statement starts with the name of a remapping and replacing it with the remapping's `path`.
///
/// There are some caveats though, dapptools style remappings usually include the `src` folder
/// `ds-test/=lib/ds-test/src/` so that imports look like `import "ds-test/test.sol";` (note the
/// missing `src` in the import path).
///
/// For hardhat/npm style that's not always the case, most notably for [openzeppelin-contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) if installed via npm.
/// The remapping is detected as `'@openzeppelin/=node_modules/@openzeppelin/contracts/'`, which
/// includes the source directory `contracts`, however it's common to see import paths like:
///
/// `import "@openzeppelin/contracts/token/ERC20/IERC20.sol";`
///
/// instead of
///
/// `import "@openzeppelin/token/ERC20/IERC20.sol";`
///
/// There is no strict rule behind this, but because [`crate::remappings::Remapping::find_many`]
/// returns `'@openzeppelin/=node_modules/@openzeppelin/contracts/'` we should handle the
/// case if the remapping path ends with `contracts` and the import path starts with
/// `<remapping name>/contracts`. Otherwise we can end up with a resolved path that has a
/// duplicate `contracts` segment:
/// `@openzeppelin/contracts/contracts/token/ERC20/IERC20.sol` we check for this edge case
/// here so that both styles work out of the box.
pub fn resolve_library_import(&self, import: &Path) -> Option<PathBuf> {
// if the import path starts with the name of the remapping then we get the resolved path by
// removing the name and adding the remainder to the path of the remapping
if let Some(path) = self.remappings.iter().find_map(|r| {
import.strip_prefix(&r.name).ok().map(|stripped_import| {
let lib_path = Path::new(&r.path).join(stripped_import);
// we handle the edge case where the path of a remapping ends with "contracts"
// (`<name>/=.../contracts`) and the stripped import also starts with `contracts`
if let Ok(adjusted_import) = stripped_import.strip_prefix("contracts/") {
if r.path.ends_with("contracts/") && !lib_path.exists() {
return Path::new(&r.path).join(adjusted_import)
}
}
lib_path
})
}) {
Some(self.root.join(path))
} else {
utils::resolve_library(&self.libraries, import)
}
}
/// Attempts to autodetect the artifacts directory based on the given root path
///
/// Dapptools layout takes precedence over hardhat style.
/// This will return:
/// - `<root>/out` if it exists or `<root>/artifacts` does not exist,
/// - `<root>/artifacts` if it exists and `<root>/out` does not exist.
pub fn find_artifacts_dir(root: impl AsRef<Path>) -> PathBuf {
utils::find_fave_or_alt_path(root, "out", "artifacts")
}
/// Attempts to autodetect the source directory based on the given root path
///
/// Dapptools layout takes precedence over hardhat style.
/// This will return:
/// - `<root>/src` if it exists or `<root>/contracts` does not exist,
/// - `<root>/contracts` if it exists and `<root>/src` does not exist.
pub fn find_source_dir(root: impl AsRef<Path>) -> PathBuf {
utils::find_fave_or_alt_path(root, "src", "contracts")
}
/// Attempts to autodetect the lib directory based on the given root path
///
/// Dapptools layout takes precedence over hardhat style.
/// This will return:
/// - `<root>/lib` if it exists or `<root>/node_modules` does not exist,
/// - `<root>/node_modules` if it exists and `<root>/lib` does not exist.
pub fn find_libs(root: impl AsRef<Path>) -> Vec<PathBuf> {
vec![utils::find_fave_or_alt_path(root, "lib", "node_modules")]
}
/// Flattens all file imports into a single string
pub fn flatten(&self, target: &Path) -> Result<String> {
tracing::trace!("flattening file");
let mut input_files = self.input_files();
// we need to ensure that the target is part of the input set, otherwise it's not
// part of the graph if it's not imported by any input file
let flatten_target = target.to_path_buf();
if !input_files.contains(&flatten_target) {
input_files.push(flatten_target);
}
let sources = Source::read_all_files(input_files)?;
let graph = Graph::resolve_sources(self, sources)?;
2022-04-23 08:40:34 +00:00
self.flatten_node(target, &graph, &mut Default::default(), false, false, false).map(|x| {
format!("{}\n", utils::RE_THREE_OR_MORE_NEWLINES.replace_all(&x, "\n\n").trim())
})
}
/// Flattens a single node from the dependency graph
fn flatten_node(
&self,
target: &Path,
graph: &Graph,
2022-03-08 14:46:04 +00:00
imported: &mut HashSet<usize>,
strip_version_pragma: bool,
strip_experimental_pragma: bool,
strip_license: bool,
) -> Result<String> {
let target_dir = target.parent().ok_or_else(|| {
SolcError::msg(format!("failed to get parent directory for \"{:?}\"", target.display()))
})?;
let target_index = graph.files().get(target).ok_or_else(|| {
SolcError::msg(format!("cannot resolve file at {:?}", target.display()))
})?;
2022-03-08 14:46:04 +00:00
if imported.contains(target_index) {
// short circuit nodes that were already imported, if both A.sol and B.sol import C.sol
return Ok(String::new())
}
2022-03-08 14:46:04 +00:00
imported.insert(*target_index);
let target_node = graph.node(*target_index);
let mut imports = target_node.imports().clone();
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 = content.as_bytes().to_vec();
let mut offset = 0_isize;
let mut statements = [
(target_node.license(), strip_license),
(target_node.version(), strip_version_pragma),
(target_node.experimental(), strip_experimental_pragma),
]
.iter()
.filter_map(|(data, condition)| if *condition { data.to_owned().as_ref() } else { None })
.collect::<Vec<_>>();
statements.sort_by_key(|x| x.loc().start);
let (mut imports, mut statements) =
(imports.iter().peekable(), statements.iter().peekable());
while imports.peek().is_some() || statements.peek().is_some() {
let (next_import_start, next_statement_start) = (
imports.peek().map_or(usize::max_value(), |x| x.loc().start),
statements.peek().map_or(usize::max_value(), |x| x.loc().start),
);
if next_statement_start < next_import_start {
let repl_range = statements.next().unwrap().loc_by_offset(offset);
offset -= repl_range.len() as isize;
content.splice(repl_range, std::iter::empty());
} else {
let import = imports.next().unwrap();
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 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| {
SolcError::msg(format!("failed to convert extended bytes to string: {err}"))
})?;
Ok(result)
}
}
impl fmt::Display for ProjectPathsConfig {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln!(f, "root: {}", self.root.display())?;
writeln!(f, "contracts: {}", self.sources.display())?;
writeln!(f, "artifacts: {}", self.artifacts.display())?;
writeln!(f, "tests: {}", self.tests.display())?;
writeln!(f, "scripts: {}", self.scripts.display())?;
writeln!(f, "libs:")?;
for lib in &self.libraries {
writeln!(f, " {}", lib.display())?;
}
writeln!(f, "remappings:")?;
for remapping in &self.remappings {
writeln!(f, " {remapping}")?;
}
Ok(())
}
}
/// This is a subset of [ProjectPathsConfig] that contains all relevant folders in the project
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct ProjectPaths {
pub artifacts: PathBuf,
pub build_infos: PathBuf,
pub sources: PathBuf,
pub tests: PathBuf,
pub scripts: PathBuf,
pub libraries: BTreeSet<PathBuf>,
}
impl ProjectPaths {
/// Joins the folders' location with `root`
pub fn join_all(&mut self, root: impl AsRef<Path>) -> &mut Self {
let root = root.as_ref();
self.artifacts = root.join(&self.artifacts);
self.build_infos = root.join(&self.build_infos);
self.sources = root.join(&self.sources);
self.tests = root.join(&self.tests);
self.scripts = root.join(&self.scripts);
let libraries = std::mem::take(&mut self.libraries);
self.libraries.extend(libraries.into_iter().map(|p| root.join(p)));
self
}
/// Removes `base` from all folders
pub fn strip_prefix_all(&mut self, base: impl AsRef<Path>) -> &mut Self {
let base = base.as_ref();
if let Ok(prefix) = self.artifacts.strip_prefix(base) {
self.artifacts = prefix.to_path_buf();
}
if let Ok(prefix) = self.build_infos.strip_prefix(base) {
self.build_infos = prefix.to_path_buf();
}
if let Ok(prefix) = self.sources.strip_prefix(base) {
self.sources = prefix.to_path_buf();
}
if let Ok(prefix) = self.tests.strip_prefix(base) {
self.tests = prefix.to_path_buf();
}
if let Ok(prefix) = self.scripts.strip_prefix(base) {
self.scripts = prefix.to_path_buf();
}
let libraries = std::mem::take(&mut self.libraries);
self.libraries.extend(
libraries
.into_iter()
.map(|p| p.strip_prefix(base).map(|p| p.to_path_buf()).unwrap_or(p)),
);
self
}
}
impl Default for ProjectPaths {
fn default() -> Self {
Self {
artifacts: "out".into(),
build_infos: ["out", "build-info"].iter().collect::<PathBuf>(),
sources: "src".into(),
tests: "test".into(),
scripts: "script".into(),
libraries: Default::default(),
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PathStyle {
HardHat,
Dapptools,
}
impl PathStyle {
/// Convert into a `ProjectPathsConfig` given the root path and based on the styled
pub fn paths(&self, root: impl AsRef<Path>) -> Result<ProjectPathsConfig> {
let root = root.as_ref();
let root = utils::canonicalize(root)?;
Ok(match self {
PathStyle::Dapptools => ProjectPathsConfig::builder()
.sources(root.join("src"))
.artifacts(root.join("out"))
.build_infos(root.join("out").join("build-info"))
.lib(root.join("lib"))
.remappings(Remapping::find_many(root.join("lib")))
.root(root)
.build()?,
PathStyle::HardHat => ProjectPathsConfig::builder()
.sources(root.join("contracts"))
.artifacts(root.join("artifacts"))
.build_infos(root.join("artifacts").join("build-info"))
.lib(root.join("node_modules"))
.root(root)
.build()?,
})
}
}
#[derive(Debug, Clone, Default)]
pub struct ProjectPathsConfigBuilder {
root: Option<PathBuf>,
cache: Option<PathBuf>,
artifacts: Option<PathBuf>,
build_infos: Option<PathBuf>,
sources: Option<PathBuf>,
tests: Option<PathBuf>,
scripts: Option<PathBuf>,
libraries: Option<Vec<PathBuf>>,
remappings: Option<Vec<Remapping>>,
}
impl ProjectPathsConfigBuilder {
pub fn root(mut self, root: impl Into<PathBuf>) -> Self {
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
self.root = Some(utils::canonicalized(root));
self
}
pub fn cache(mut self, cache: impl Into<PathBuf>) -> Self {
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
self.cache = Some(utils::canonicalized(cache));
self
}
pub fn artifacts(mut self, artifacts: impl Into<PathBuf>) -> Self {
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
self.artifacts = Some(utils::canonicalized(artifacts));
self
}
pub fn build_infos(mut self, build_infos: impl Into<PathBuf>) -> Self {
self.build_infos = Some(utils::canonicalized(build_infos));
self
}
pub fn sources(mut self, sources: impl Into<PathBuf>) -> Self {
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
self.sources = Some(utils::canonicalized(sources));
self
}
pub fn tests(mut self, tests: impl Into<PathBuf>) -> Self {
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
self.tests = Some(utils::canonicalized(tests));
self
}
pub fn scripts(mut self, scripts: impl Into<PathBuf>) -> Self {
self.scripts = Some(utils::canonicalized(scripts));
self
}
/// Specifically disallow additional libraries
pub fn no_libs(mut self) -> Self {
self.libraries = Some(Vec::new());
self
}
pub fn lib(mut self, lib: impl Into<PathBuf>) -> Self {
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
self.libraries.get_or_insert_with(Vec::new).push(utils::canonicalized(lib));
self
}
pub fn libs(mut self, libs: impl IntoIterator<Item = impl Into<PathBuf>>) -> Self {
let libraries = self.libraries.get_or_insert_with(Vec::new);
for lib in libs.into_iter() {
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
libraries.push(utils::canonicalized(lib));
}
self
}
pub fn remapping(mut self, remapping: Remapping) -> Self {
self.remappings.get_or_insert_with(Vec::new).push(remapping);
self
}
pub fn remappings(mut self, remappings: impl IntoIterator<Item = Remapping>) -> Self {
let our_remappings = self.remappings.get_or_insert_with(Vec::new);
for remapping in remappings.into_iter() {
our_remappings.push(remapping);
}
self
}
pub fn build_with_root(self, root: impl Into<PathBuf>) -> ProjectPathsConfig {
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
let root = utils::canonicalized(root);
let libraries = self.libraries.unwrap_or_else(|| ProjectPathsConfig::find_libs(&root));
let artifacts =
self.artifacts.unwrap_or_else(|| ProjectPathsConfig::find_artifacts_dir(&root));
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
ProjectPathsConfig {
cache: self
.cache
.unwrap_or_else(|| root.join("cache").join(SOLIDITY_FILES_CACHE_FILENAME)),
build_infos: self.build_infos.unwrap_or_else(|| artifacts.join("build-info")),
artifacts,
sources: self.sources.unwrap_or_else(|| ProjectPathsConfig::find_source_dir(&root)),
tests: self.tests.unwrap_or_else(|| root.join("test")),
scripts: self.scripts.unwrap_or_else(|| root.join("script")),
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
remappings: self
.remappings
.unwrap_or_else(|| libraries.iter().flat_map(Remapping::find_many).collect()),
libraries,
root,
}
}
pub fn build(self) -> std::result::Result<ProjectPathsConfig, SolcIoError> {
let root = self
.root
.clone()
.map(Ok)
.unwrap_or_else(std::env::current_dir)
.map_err(|err| SolcIoError::new(err, "."))?;
Ok(self.build_with_root(root))
}
}
/// The config to use when compiling the contracts
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct SolcConfig {
/// How the file was compiled
pub settings: Settings,
}
impl SolcConfig {
/// # Example
///
/// Autodetect solc version and default settings
///
/// ```rust
/// use ethers_solc::SolcConfig;
/// let config = SolcConfig::builder().build();
/// ```
pub fn builder() -> SolcConfigBuilder {
SolcConfigBuilder::default()
}
}
impl From<SolcConfig> for Settings {
fn from(config: SolcConfig) -> Self {
config.settings
}
}
#[derive(Default)]
pub struct SolcConfigBuilder {
settings: Option<Settings>,
/// additionally selected outputs that should be included in the `Contract` that `solc´ creates
output_selection: Vec<ContractOutputSelection>,
}
impl SolcConfigBuilder {
pub fn settings(mut self, settings: Settings) -> Self {
self.settings = Some(settings);
self
}
/// Adds another `ContractOutputSelection` to the set
#[must_use]
pub fn additional_output(mut self, output: impl Into<ContractOutputSelection>) -> Self {
self.output_selection.push(output.into());
self
}
/// Adds multiple `ContractOutputSelection` to the set
#[must_use]
pub fn additional_outputs<I, S>(mut self, outputs: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<ContractOutputSelection>,
{
for out in outputs {
self = self.additional_output(out);
}
self
}
/// Creates the solc config
///
/// If no solc version is configured then it will be determined by calling `solc --version`.
pub fn build(self) -> SolcConfig {
let Self { settings, output_selection } = self;
let mut settings = settings.unwrap_or_default();
settings.push_all(output_selection);
SolcConfig { settings }
}
}
/// Container for all `--include-path` arguments for Solc, see also
/// [Solc docs](https://docs.soliditylang.org/en/v0.8.9/using-the-compiler.html#base-path-and-import-remapping).
///
/// The `--include--path` flag:
/// > Makes an additional source directory available to the default import callback. Use this option
/// > if you want to import contracts whose location is not fixed in relation to your main source
/// > tree, e.g. third-party libraries installed using a package manager. Can be used multiple
/// > times. Can only be used if base path has a non-empty value.
///
/// In contrast to `--allow-paths` [`AllowedLibPaths`], which takes multiple arguments,
/// `--include-path` only takes a single path argument.
#[derive(Clone, Debug, Default)]
pub struct IncludePaths(pub(crate) BTreeSet<PathBuf>);
// === impl IncludePaths ===
impl IncludePaths {
/// Returns the [Command](std::process::Command) arguments for this type
///
/// For each entry in the set, it will return `--include-path` + `<entry>`
pub fn args(&self) -> impl Iterator<Item = String> + '_ {
self.paths().flat_map(|path| ["--include-path".to_string(), format!("{}", path.display())])
}
/// Returns all paths that exist
pub fn paths(&self) -> impl Iterator<Item = &PathBuf> + '_ {
self.0.iter().filter(|path| path.exists())
}
}
impl Deref for IncludePaths {
type Target = BTreeSet<PathBuf>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for IncludePaths {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
/// Helper struct for serializing `--allow-paths` arguments to Solc
///
/// From the [Solc docs](https://docs.soliditylang.org/en/v0.8.9/using-the-compiler.html#base-path-and-import-remapping):
/// For security reasons the compiler has restrictions on what directories it can access.
/// Directories of source files specified on the command line and target paths of
/// remappings are automatically allowed to be accessed by the file reader,
/// but everything else is rejected by default. Additional paths (and their subdirectories)
/// can be allowed via the --allow-paths /sample/path,/another/sample/path switch.
/// Everything inside the path specified via --base-path is always allowed.
#[derive(Clone, Debug, Default)]
pub struct AllowedLibPaths(pub(crate) BTreeSet<PathBuf>);
// === impl AllowedLibPaths ===
impl AllowedLibPaths {
/// Returns the [Command](std::process::Command) arguments for this type
///
/// `--allow-paths` takes a single value: all comma separated paths
pub fn args(&self) -> Option<[String; 2]> {
let args = self.to_string();
if args.is_empty() {
return None
}
Some(["--allow-paths".to_string(), args])
}
/// Returns all paths that exist
pub fn paths(&self) -> impl Iterator<Item = &PathBuf> + '_ {
self.0.iter().filter(|path| path.exists())
}
}
impl Deref for AllowedLibPaths {
type Target = BTreeSet<PathBuf>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for AllowedLibPaths {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl fmt::Display for AllowedLibPaths {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let lib_paths =
self.paths().map(|path| format!("{}", path.display())).collect::<Vec<_>>().join(",");
write!(f, "{lib_paths}")
}
}
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
impl<T: Into<PathBuf>> From<Vec<T>> for AllowedLibPaths {
fn from(libs: Vec<T>) -> Self {
let libs = libs.into_iter().map(utils::canonicalized).collect();
AllowedLibPaths(libs)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_autodetect_dirs() {
let root = utils::tempdir("root").unwrap();
let out = root.path().join("out");
let artifacts = root.path().join("artifacts");
let build_infos = artifacts.join("build-info");
let contracts = root.path().join("contracts");
let src = root.path().join("src");
let lib = root.path().join("lib");
let node_modules = root.path().join("node_modules");
let root = root.path();
assert_eq!(ProjectPathsConfig::find_source_dir(root), src,);
std::fs::create_dir_all(&contracts).unwrap();
assert_eq!(ProjectPathsConfig::find_source_dir(root), contracts,);
assert_eq!(
ProjectPathsConfig::builder().build_with_root(root).sources,
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
utils::canonicalized(contracts),
);
std::fs::create_dir_all(&src).unwrap();
assert_eq!(ProjectPathsConfig::find_source_dir(root), src,);
assert_eq!(
ProjectPathsConfig::builder().build_with_root(root).sources,
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
utils::canonicalized(src),
);
assert_eq!(ProjectPathsConfig::find_artifacts_dir(root), out,);
std::fs::create_dir_all(&artifacts).unwrap();
assert_eq!(ProjectPathsConfig::find_artifacts_dir(root), artifacts,);
assert_eq!(
ProjectPathsConfig::builder().build_with_root(root).artifacts,
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
utils::canonicalized(artifacts),
);
std::fs::create_dir_all(&build_infos).unwrap();
assert_eq!(
ProjectPathsConfig::builder().build_with_root(root).build_infos,
utils::canonicalized(build_infos)
);
std::fs::create_dir_all(&out).unwrap();
assert_eq!(ProjectPathsConfig::find_artifacts_dir(root), out,);
assert_eq!(
ProjectPathsConfig::builder().build_with_root(root).artifacts,
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
utils::canonicalized(out),
);
assert_eq!(ProjectPathsConfig::find_libs(root), vec![lib.clone()],);
std::fs::create_dir_all(&node_modules).unwrap();
assert_eq!(ProjectPathsConfig::find_libs(root), vec![node_modules.clone()],);
assert_eq!(
ProjectPathsConfig::builder().build_with_root(root).libraries,
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
vec![utils::canonicalized(node_modules)],
);
std::fs::create_dir_all(&lib).unwrap();
assert_eq!(ProjectPathsConfig::find_libs(root), vec![lib.clone()],);
assert_eq!(
ProjectPathsConfig::builder().build_with_root(root).libraries,
refactor(solc): rewrite compiler passes and cache change detection (#802) * chore: clippy * refactor: rewrite compiler passes and cache * feat: more work on compile pipeline * feat: add cache constructor * add artifact filtering * fine tune api * feat: prepare version integration * docs: more docs * feat: add cacheentry2 * replace cacheentry types * integrate new api * docs: more docs * feat: implement new output handler * feat: integrate cached files in new compile pipeline * refactor: more cache refactor * docs: more docs * feat: add source name mapping * feat: implement new parallel solc * refactor: do a little cleanup * refactor: even more cleanup * even more cleanup * chore: make it compile * chore: make it compile with all features * chore: clippy fix * feat: integrate new compiler pipeline * docs: more docs * refactor: move stuff around * refactor: start deprecating output type * chore: make it compile again * chore(deps): bump solc version 0.2.0 * feat: unify output types * cargo fix * refactor: add contracts wrapper * chore: replace ProjectCompileOutput * docs: add more docs * feat: add offline mode * feat: more artifact helpers * chore: cleanup cache * chore: streamline types * fix: better artifacts mapping * chore: some cleanup * chore: change artifact * chore: add configure solc fn * feat: add artifact reading * feat: implement retain and extend * feat: add cache extending * feat: write to disk * chore: make clippy happy * feat: implement path mapping * chore: nits * feat: introduce states * feat: add compiler state machine * chore: move cache types to cache mod * chore: make clippy happy * feat: add debug derives * fix: use resolved import source unit names * fix: failing tests * test: test multiple libs properly * chore: make clippy happy * chore: update CHANGELOG * fix: doc tests * fix: set offline mode correctly * chore: make it compile again * Update ethers-solc/src/artifacts.rs Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> * feat: find remappings by default * typos * add eth_syncing RPC (#848) * add eth_syncing RPC * Changelo updated * small comments * Intermediate SyncingStatus * fix(core): adjust Ganache for new cli output (#851) * fix: review comments * fix: cache relative path bug * chore: add cache example * chore: use absolute paths * fix: remove overwritten files from cache * fix: rustfmt * chore: more helper functions * chore: export AggregatedOutput * feat: implement helper functions * feat: even more helpers * fix: failing doc tests * refactor: remove source name map tracking * fix: determine artifacts in ephemeral mode * refactor: allowed paths should not fail Co-authored-by: Georgios Konstantopoulos <me@gakonst.com> Co-authored-by: rakita <rakita@users.noreply.github.com> Co-authored-by: wolflo <33909953+wolflo@users.noreply.github.com>
2022-02-04 16:20:24 +00:00
vec![utils::canonicalized(lib)],
);
}
#[test]
fn can_have_sane_build_info_default() {
let root = utils::tempdir("root").unwrap();
let root = root.path();
let artifacts = root.join("forge-artifacts");
// Set the artifacts directory without setting the
// build info directory
let project = ProjectPathsConfig::builder().artifacts(&artifacts).build_with_root(root);
// The artifacts should be set correctly based on the configured value
assert_eq!(project.artifacts, utils::canonicalized(artifacts));
// The build infos should by default in the artifacts directory
assert_eq!(project.build_infos, utils::canonicalized(project.artifacts.join("build-info")));
}
#[test]
fn can_find_library_ancestor() {
let mut config = ProjectPathsConfig::builder().lib("lib").build().unwrap();
config.root = "/root/".into();
assert_eq!(config.find_library_ancestor("lib/src/Greeter.sol").unwrap(), Path::new("lib"));
assert_eq!(
config.find_library_ancestor("/root/lib/src/Greeter.sol").unwrap(),
Path::new("lib")
);
config.libraries.push("/root/test/".into());
assert_eq!(
config.find_library_ancestor("test/src/Greeter.sol").unwrap(),
Path::new("/root/test/")
);
assert_eq!(
config.find_library_ancestor("/root/test/src/Greeter.sol").unwrap(),
Path::new("/root/test/")
);
}
}